1 /************************************************************************** 2 * 3 * Copyright 2010 Luca Barbieri 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27 #define INPUT_PATCH_SIZE 3 28 #define OUTPUT_PATCH_SIZE 3 29 30 static const float PI = 3.141592653589793238462643f; 31 32 cbuffer cb_frame 33 { 34 float4x4 model; 35 float4x4 view_proj; 36 float disp_scale; 37 float disp_freq; 38 float tess_factor; 39 }; 40 41 struct IA2VS 42 { 43 float3 position : POSITION; 44 }; 45 46 struct VS2HS 47 { 48 float3 position : POSITION; 49 }; 50 51 VS2HS vs(IA2VS input) 52 { 53 VS2HS result; 54 result.position = input.position; 55 return result; 56 } 57 58 struct HS2DS_PATCH 59 { 60 float tessouter[3] : SV_TessFactor; 61 float tessinner[1] : SV_InsideTessFactor; 62 }; 63 64 struct HS2DS 65 { 66 float3 position : POSITION; 67 }; 68 69 HS2DS_PATCH hs_patch(InputPatch<VS2HS, INPUT_PATCH_SIZE> ip) 70 { 71 HS2DS_PATCH result; 72 73 result.tessouter[0] = result.tessouter[1] = result.tessouter[2] 74 = result.tessinner[0] = tess_factor; 75 return result; 76 } 77 78 [domain("tri")] 79 [partitioning("fractional_even")] 80 [outputtopology("triangle_cw")] 81 [outputcontrolpoints(OUTPUT_PATCH_SIZE)] 82 [patchconstantfunc("hs_patch")] 83 HS2DS hs(InputPatch<VS2HS, INPUT_PATCH_SIZE> p, uint i : SV_OutputControlPointID) 84 { 85 HS2DS result; 86 result.position = p[i].position; 87 return result; 88 } 89 90 struct DS2PS 91 { 92 float4 position : SV_POSITION; 93 float3 objpos : OBJPOS; 94 // float3 worldpos : WORLDPOS; 95 float3 objnormal : OBJNORMAL; 96 float3 worldnormal : WORLDNORMAL; 97 }; 98 99 float3 dnormf_dt(float3 f, float3 dfdt) 100 { 101 float ff = dot(f, f); 102 return (ff * dfdt - dot(f, dfdt) * f) / (ff * sqrt(ff)); 103 } 104 105 float3 map(float3 p, float3 q, float3 r, float3 k) 106 { 107 return normalize(p * k.x + q * k.y + r * k.z); 108 } 109 110 float3 dmap_du(float3 p, float3 q, float3 r, float3 k) 111 { 112 return dnormf_dt(p * k.x + q * k.y + r * k.z, p); 113 } 114 115 float dispf(float v) 116 { 117 return cos(v * disp_freq); 118 } 119 120 float ddispf(float v) 121 { 122 return -sin(v * disp_freq) * disp_freq; 123 } 124 125 float disp(float3 k) 126 { 127 return dispf(k.x) * dispf(k.y) * dispf(k.z); 128 } 129 130 float ddisp_du(float3 k) 131 { 132 return ddispf(k.x) * dispf(k.y) * dispf(k.z); 133 } 134 135 float3 ddisp(float3 k) 136 { 137 float3 f = float3(dispf(k.x), dispf(k.y), dispf(k.z)); 138 return float3(ddispf(k.x) * f.y * f.z, ddispf(k.y) * f.z * f.x, ddispf(k.z) * f.x * f.y); 139 } 140 141 [domain("tri")] 142 DS2PS ds(HS2DS_PATCH input, 143 float3 k : SV_DomainLocation, 144 const OutputPatch<HS2DS, OUTPUT_PATCH_SIZE> patch) 145 { 146 DS2PS result; 147 148 float3 s = map(patch[0].position, patch[1].position, patch[2].position, k); 149 float3 d = 1.0 + disp(s) * disp_scale; 150 result.objpos = s * d; 151 result.objpos /= (1.0 + disp_scale); 152 float3 worldpos = mul(model, float4(result.objpos, 1.0f)); 153 result.position = mul(view_proj, float4(worldpos, 1.0f)); 154 155 float3 dd = ddisp(s) * disp_scale; 156 157 /* 158 float3 ds_du = dmap_du(patch[0].position, patch[1].position, patch[2].position, k); 159 float3 ds_dv = dmap_du(patch[1].position, patch[2].position, patch[0].position, k.yzx); 160 float3 ds_dw = dmap_du(patch[2].position, patch[0].position, patch[1].position, k.zxy); 161 162 float3 ds_dU = ds_du - ds_dw; 163 float3 ds_dV = ds_dv - ds_dw; 164 165 float3 dc_dU = s * dot(dd, ds_dU) + ds_dU * d; 166 float3 dc_dV = s * dot(dd, ds_dV) + ds_dV * d; 167 */ 168 169 // this should be faster 170 float3 _u = normalize((abs(s.x) > abs(s.y)) ? float3(-s.z, 0, s.x) : float3(0, -s.z, s.y)); 171 float3 _v = normalize(cross(s, _u)); 172 float3 dc_dU = s * dot(dd, _u) + _u * d; 173 float3 dc_dV = s * dot(dd, _v) + _v * d; 174 175 result.objnormal = normalize(cross(dc_dU, dc_dV)); 176 result.worldnormal = mul(model, result.objnormal); 177 return result; 178 } 179 180 float4 ps(DS2PS input) : SV_TARGET 181 { 182 float3 pseudoambient = float3(0.4, 0.4, 0.6); 183 float3 diffuse = float3(0.6, 0.6, 0.4); 184 float3 light = normalize(float3(0, 1, -1)); 185 186 float4 r; 187 // r.xyz = normalize(input.objpos + 2 * input.objnormal); 188 r.xyz = pseudoambient * saturate(dot(normalize(input.objnormal), normalize(input.objpos))); 189 r.xyz += saturate(dot(light, normalize(input.worldnormal))) * diffuse; 190 191 r.w = 1; 192 return r; 193 } 194