/************************************************************************** * * Copyright 2010 Luca Barbieri * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ #define INPUT_PATCH_SIZE 3 #define OUTPUT_PATCH_SIZE 3 static const float PI = 3.141592653589793238462643f; cbuffer cb_frame { float4x4 model; float4x4 view_proj; float disp_scale; float disp_freq; float tess_factor; }; struct IA2VS { float3 position : POSITION; }; struct VS2HS { float3 position : POSITION; }; VS2HS vs(IA2VS input) { VS2HS result; result.position = input.position; return result; } struct HS2DS_PATCH { float tessouter[3] : SV_TessFactor; float tessinner[1] : SV_InsideTessFactor; }; struct HS2DS { float3 position : POSITION; }; HS2DS_PATCH hs_patch(InputPatch ip) { HS2DS_PATCH result; result.tessouter[0] = result.tessouter[1] = result.tessouter[2] = result.tessinner[0] = tess_factor; return result; } [domain("tri")] [partitioning("fractional_even")] [outputtopology("triangle_cw")] [outputcontrolpoints(OUTPUT_PATCH_SIZE)] [patchconstantfunc("hs_patch")] HS2DS hs(InputPatch p, uint i : SV_OutputControlPointID) { HS2DS result; result.position = p[i].position; return result; } struct DS2PS { float4 position : SV_POSITION; float3 objpos : OBJPOS; // float3 worldpos : WORLDPOS; float3 objnormal : OBJNORMAL; float3 worldnormal : WORLDNORMAL; }; float3 dnormf_dt(float3 f, float3 dfdt) { float ff = dot(f, f); return (ff * dfdt - dot(f, dfdt) * f) / (ff * sqrt(ff)); } float3 map(float3 p, float3 q, float3 r, float3 k) { return normalize(p * k.x + q * k.y + r * k.z); } float3 dmap_du(float3 p, float3 q, float3 r, float3 k) { return dnormf_dt(p * k.x + q * k.y + r * k.z, p); } float dispf(float v) { return cos(v * disp_freq); } float ddispf(float v) { return -sin(v * disp_freq) * disp_freq; } float disp(float3 k) { return dispf(k.x) * dispf(k.y) * dispf(k.z); } float ddisp_du(float3 k) { return ddispf(k.x) * dispf(k.y) * dispf(k.z); } float3 ddisp(float3 k) { float3 f = float3(dispf(k.x), dispf(k.y), dispf(k.z)); return float3(ddispf(k.x) * f.y * f.z, ddispf(k.y) * f.z * f.x, ddispf(k.z) * f.x * f.y); } [domain("tri")] DS2PS ds(HS2DS_PATCH input, float3 k : SV_DomainLocation, const OutputPatch patch) { DS2PS result; float3 s = map(patch[0].position, patch[1].position, patch[2].position, k); float3 d = 1.0 + disp(s) * disp_scale; result.objpos = s * d; result.objpos /= (1.0 + disp_scale); float3 worldpos = mul(model, float4(result.objpos, 1.0f)); result.position = mul(view_proj, float4(worldpos, 1.0f)); float3 dd = ddisp(s) * disp_scale; /* float3 ds_du = dmap_du(patch[0].position, patch[1].position, patch[2].position, k); float3 ds_dv = dmap_du(patch[1].position, patch[2].position, patch[0].position, k.yzx); float3 ds_dw = dmap_du(patch[2].position, patch[0].position, patch[1].position, k.zxy); float3 ds_dU = ds_du - ds_dw; float3 ds_dV = ds_dv - ds_dw; float3 dc_dU = s * dot(dd, ds_dU) + ds_dU * d; float3 dc_dV = s * dot(dd, ds_dV) + ds_dV * d; */ // this should be faster float3 _u = normalize((abs(s.x) > abs(s.y)) ? float3(-s.z, 0, s.x) : float3(0, -s.z, s.y)); float3 _v = normalize(cross(s, _u)); float3 dc_dU = s * dot(dd, _u) + _u * d; float3 dc_dV = s * dot(dd, _v) + _v * d; result.objnormal = normalize(cross(dc_dU, dc_dV)); result.worldnormal = mul(model, result.objnormal); return result; } float4 ps(DS2PS input) : SV_TARGET { float3 pseudoambient = float3(0.4, 0.4, 0.6); float3 diffuse = float3(0.6, 0.6, 0.4); float3 light = normalize(float3(0, 1, -1)); float4 r; // r.xyz = normalize(input.objpos + 2 * input.objnormal); r.xyz = pseudoambient * saturate(dot(normalize(input.objnormal), normalize(input.objpos))); r.xyz += saturate(dot(light, normalize(input.worldnormal))) * diffuse; r.w = 1; return r; }