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 30static const float PI = 3.141592653589793238462643f; 31 32cbuffer cb_frame 33{ 34 float4x4 model; 35 float4x4 view_proj; 36 float disp_scale; 37 float disp_freq; 38 float tess_factor; 39}; 40 41struct IA2VS 42{ 43 float3 position : POSITION; 44}; 45 46struct VS2HS 47{ 48 float3 position : POSITION; 49}; 50 51VS2HS vs(IA2VS input) 52{ 53 VS2HS result; 54 result.position = input.position; 55 return result; 56} 57 58struct HS2DS_PATCH 59{ 60 float tessouter[3] : SV_TessFactor; 61 float tessinner[1] : SV_InsideTessFactor; 62}; 63 64struct HS2DS 65{ 66 float3 position : POSITION; 67}; 68 69HS2DS_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")] 83HS2DS 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 90struct 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 99float3 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 105float3 map(float3 p, float3 q, float3 r, float3 k) 106{ 107 return normalize(p * k.x + q * k.y + r * k.z); 108} 109 110float3 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 115float dispf(float v) 116{ 117 return cos(v * disp_freq); 118} 119 120float ddispf(float v) 121{ 122 return -sin(v * disp_freq) * disp_freq; 123} 124 125float disp(float3 k) 126{ 127 return dispf(k.x) * dispf(k.y) * dispf(k.z); 128} 129 130float ddisp_du(float3 k) 131{ 132 return ddispf(k.x) * dispf(k.y) * dispf(k.z); 133} 134 135float3 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")] 142DS2PS 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 180float4 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