aboutsummaryrefslogtreecommitdiff
path: root/samples/d3d11/shaders/tess_hs.hlsl
diff options
context:
space:
mode:
Diffstat (limited to 'samples/d3d11/shaders/tess_hs.hlsl')
-rw-r--r--samples/d3d11/shaders/tess_hs.hlsl124
1 files changed, 124 insertions, 0 deletions
diff --git a/samples/d3d11/shaders/tess_hs.hlsl b/samples/d3d11/shaders/tess_hs.hlsl
new file mode 100644
index 0000000..630ea60
--- /dev/null
+++ b/samples/d3d11/shaders/tess_hs.hlsl
@@ -0,0 +1,124 @@
+//----------------------------------------------------------------------------------
+// File: FaceWorks/samples/sample_d3d11/shaders/tess_hs.hlsl
+// SDK Version: v1.0
+// Site: http://developer.nvidia.com/
+//
+// Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of NVIDIA CORPORATION nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//----------------------------------------------------------------------------------
+
+#include "common.hlsli"
+#include "tess.hlsli"
+
+void calcHSConstants(
+ in InputPatch<Vertex, 3> i_cps,
+ out PatchConstData o_pcd)
+{
+ // Backface culling: check if the camera is behind all three tangent planes
+ float3 vecNdotV =
+ {
+ dot(g_posCamera - i_cps[0].m_pos, i_cps[0].m_normal),
+ dot(g_posCamera - i_cps[1].m_pos, i_cps[1].m_normal),
+ dot(g_posCamera - i_cps[2].m_pos, i_cps[2].m_normal),
+ };
+ if (all(vecNdotV < 0.0))
+ {
+ o_pcd.m_tessFactor[0] = 0.0;
+ o_pcd.m_tessFactor[1] = 0.0;
+ o_pcd.m_tessFactor[2] = 0.0;
+ o_pcd.m_insideTessFactor = 0.0;
+ return;
+ }
+
+ // Frustum culling: check if all three verts are out on the same side of the frustum
+ // This isn't quite correct because the displacement could make a patch visible even if
+ // it fails this test; but in practice this is nearly impossible to notice
+ float4 posClip0 = mul(float4(i_cps[0].m_pos, 1.0), g_matWorldToClip);
+ float4 posClip1 = mul(float4(i_cps[1].m_pos, 1.0), g_matWorldToClip);
+ float4 posClip2 = mul(float4(i_cps[2].m_pos, 1.0), g_matWorldToClip);
+ float3 xs = { posClip0.x, posClip1.x, posClip2.x };
+ float3 ys = { posClip0.y, posClip1.y, posClip2.y };
+ float3 ws = { posClip0.w, posClip1.w, posClip2.w };
+ if (all(xs < -ws) || all(xs > ws) || all(ys < -ws) || all(ys > ws))
+ {
+ o_pcd.m_tessFactor[0] = 0.0;
+ o_pcd.m_tessFactor[1] = 0.0;
+ o_pcd.m_tessFactor[2] = 0.0;
+ o_pcd.m_insideTessFactor = 0.0;
+ return;
+ }
+
+ // Adaptive tessellation based on a screen-space error estimate using curvature
+
+ // Calculate approximate screen-space edge length, but including z length as well,
+ // so we don't undertessellate edges that are foreshortened
+ float edge0 = length(i_cps[2].m_pos - i_cps[1].m_pos) / (0.5 * (posClip2.w + posClip1.w));
+ float edge1 = length(i_cps[0].m_pos - i_cps[2].m_pos) / (0.5 * (posClip0.w + posClip2.w));
+ float edge2 = length(i_cps[1].m_pos - i_cps[0].m_pos) / (0.5 * (posClip1.w + posClip0.w));
+
+ // Calculate dots of the two normals on each edge - used to give more tessellation
+ // in areas with higher curvature
+ float normalDot0 = dot(i_cps[2].m_normal, i_cps[1].m_normal);
+ float normalDot1 = dot(i_cps[0].m_normal, i_cps[2].m_normal);
+ float normalDot2 = dot(i_cps[1].m_normal, i_cps[0].m_normal);
+
+ // Calculate target screen-space error
+ static const float errPxTarget = 0.5;
+ static const float tanHalfFov = tan(0.5 * 0.5);
+ static const float errTarget = errPxTarget * 2.0 * tanHalfFov / 1080.0;
+
+ // Calculate tess factors using curve fitting approximation to screen-space error
+ // derived from curvature and edge length
+ static const float tessScale = 0.41 / sqrt(errTarget);
+ o_pcd.m_tessFactor[0] = g_tessScale * sqrt(edge0) * pow(1.0 - saturate(normalDot0), 0.27);
+ o_pcd.m_tessFactor[1] = g_tessScale * sqrt(edge1) * pow(1.0 - saturate(normalDot1), 0.27);
+ o_pcd.m_tessFactor[2] = g_tessScale * sqrt(edge2) * pow(1.0 - saturate(normalDot2), 0.27);
+
+ // Clamp to supported range
+ o_pcd.m_tessFactor[0] = clamp(o_pcd.m_tessFactor[0], 1.0, s_tessFactorMax);
+ o_pcd.m_tessFactor[1] = clamp(o_pcd.m_tessFactor[1], 1.0, s_tessFactorMax);
+ o_pcd.m_tessFactor[2] = clamp(o_pcd.m_tessFactor[2], 1.0, s_tessFactorMax);
+
+ // Set interior tess factor to maximum of edge factors
+ o_pcd.m_insideTessFactor = max(max(o_pcd.m_tessFactor[0],
+ o_pcd.m_tessFactor[1]),
+ o_pcd.m_tessFactor[2]);
+}
+
+[domain("tri")]
+[maxtessfactor(s_tessFactorMax)]
+[outputcontrolpoints(3)]
+[outputtopology("triangle_cw")]
+[partitioning("fractional_odd")]
+[patchconstantfunc("calcHSConstants")]
+Vertex main(
+ in InputPatch<Vertex, 3> i_cps,
+ in uint iCp : SV_OutputControlPointID)
+{
+ return i_cps[iCp];
+}