aboutsummaryrefslogtreecommitdiff
path: root/samples/d3d11/shaders/lighting.hlsli
diff options
context:
space:
mode:
authorMarco Foco <[email protected]>2016-03-07 15:47:07 +0100
committerMarco Foco <[email protected]>2016-03-08 16:04:19 +0100
commitcd6e0492903f8a9eb5efa14263d7d9ab092517de (patch)
tree05c010b75bf777335565819dcceb140886c5a7e9 /samples/d3d11/shaders/lighting.hlsli
downloadfaceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.tar.xz
faceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.zip
FaceWorks 1.0
Diffstat (limited to 'samples/d3d11/shaders/lighting.hlsli')
-rw-r--r--samples/d3d11/shaders/lighting.hlsli293
1 files changed, 293 insertions, 0 deletions
diff --git a/samples/d3d11/shaders/lighting.hlsli b/samples/d3d11/shaders/lighting.hlsli
new file mode 100644
index 0000000..52258d2
--- /dev/null
+++ b/samples/d3d11/shaders/lighting.hlsli
@@ -0,0 +1,293 @@
+//----------------------------------------------------------------------------------
+// File: FaceWorks/samples/sample_d3d11/shaders/lighting.hlsli
+// 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.
+//
+//----------------------------------------------------------------------------------
+
+#ifndef LIGHTING_HLSLI
+#define LIGHTING_HLSLI
+
+#include "common.hlsli"
+#include "tonemap.hlsli"
+#include "GFSDK_FaceWorks.hlsli"
+
+
+
+// Normal mapping
+
+float3 UnpackNormal(
+ float3 sample,
+ float normalStrength)
+{
+ return lerp(float3(0, 0, 1),
+ sample * 2.0 - 1.0,
+ normalStrength);
+}
+
+
+
+// Shadow filtering, using variance shadow maps
+
+float EvaluateShadowVSM(
+ float4 uvzwShadow,
+ float3 normalGeom)
+{
+ float3 uvzShadow = uvzwShadow.xyz / uvzwShadow.w;
+
+ float2 vsmValue = g_texVSM.Sample(g_ssBilinearClamp, uvzShadow.xy);
+ float mean = vsmValue.x;
+ float variance = max(g_vsmMinVariance, vsmValue.y - mean*mean);
+
+ return saturate(variance / (variance + square(uvzShadow.z - mean)));
+}
+
+
+
+// Diffuse lighting
+
+float3 EvaluateDiffuseLight(
+ float3 normalGeom,
+ float3 normalShade,
+ float shadow)
+{
+ // Directional light diffuse
+ float NdotL = saturate(dot(normalShade, g_vecDirectionalLight));
+ float3 rgbLightDiffuse = g_rgbDirectionalLight * (NdotL * shadow);
+
+ // IBL diffuse
+ rgbLightDiffuse += g_texCubeDiffuse.Sample(g_ssTrilinearRepeat, normalShade);
+
+ return rgbLightDiffuse;
+}
+
+float3 EvaluateSSSDiffuseLight(
+ float3 normalGeom,
+ float3 normalShade,
+ float3 normalBlurred,
+ float shadow,
+ float curvature,
+ GFSDK_FaceWorks_CBData faceworksData)
+{
+ // Directional light diffuse
+ float3 rgbSSS = GFSDK_FaceWorks_EvaluateSSSDirectLight(
+ faceworksData,
+ normalGeom, normalShade, normalBlurred,
+ g_vecDirectionalLight, curvature,
+ g_texCurvatureLUT, g_ssBilinearClamp);
+ float3 rgbShadow = GFSDK_FaceWorks_EvaluateSSSShadow(
+ faceworksData,
+ normalGeom, g_vecDirectionalLight, shadow,
+ g_texShadowLUT, g_ssBilinearClamp);
+ float3 rgbLightDiffuse = g_rgbDirectionalLight * rgbSSS * rgbShadow;
+
+ // IBL diffuse
+ float3 normalAmbient0, normalAmbient1, normalAmbient2;
+ GFSDK_FaceWorks_CalculateNormalsForAmbientLight(
+ normalShade, normalBlurred,
+ normalAmbient0, normalAmbient1, normalAmbient2);
+ float3 rgbAmbient0 = g_texCubeDiffuse.Sample(g_ssTrilinearRepeat, normalAmbient0);
+ float3 rgbAmbient1 = g_texCubeDiffuse.Sample(g_ssTrilinearRepeat, normalAmbient1);
+ float3 rgbAmbient2 = g_texCubeDiffuse.Sample(g_ssTrilinearRepeat, normalAmbient2);
+ rgbLightDiffuse += GFSDK_FaceWorks_EvaluateSSSAmbientLight(
+ rgbAmbient0, rgbAmbient1, rgbAmbient2);
+
+ return rgbLightDiffuse;
+}
+
+
+
+// Specular lighting
+
+float3 EvaluateSpecularLight(
+ float3 normalGeom,
+ float3 normalShade,
+ float3 vecCamera,
+ float specReflectance,
+ float gloss,
+ float shadow)
+{
+ // Directional light spec
+
+ float3 vecHalf = normalize(g_vecDirectionalLight + vecCamera);
+ float NdotL = saturate(dot(normalShade, g_vecDirectionalLight));
+ float NdotH = saturate(dot(normalShade, vecHalf));
+ float LdotH = dot(g_vecDirectionalLight, vecHalf);
+ float NdotV = saturate(dot(normalShade, vecCamera));
+ float specPower = exp2(gloss * 13.0);
+
+ // Evaluate NDF and visibility function:
+ // Two-lobe Blinn-Phong, with double gloss on second lobe
+ float specLobeBlend = 0.05;
+ float specPower0 = specPower;
+ float specPower1 = square(specPower);
+ float ndf0 = pow(NdotH, specPower0) * (specPower0 + 2.0) * 0.5;
+ float schlickSmithFactor0 = rsqrt(specPower0 * (3.14159 * 0.25) + (3.14159 * 0.5));
+ float visibilityFn0 = 0.25 / (lerp(schlickSmithFactor0, 1, NdotL) *
+ lerp(schlickSmithFactor0, 1, NdotV));
+ float ndf1 = pow(NdotH, specPower1) * (specPower1 + 2.0) * 0.5;
+ float schlickSmithFactor1 = rsqrt(specPower1 * (3.14159 * 0.25) + (3.14159 * 0.5));
+ float visibilityFn1 = 0.25 / (lerp(schlickSmithFactor1, 1, NdotL) *
+ lerp(schlickSmithFactor1, 1, NdotV));
+ float ndfResult = lerp(ndf0 * visibilityFn0, ndf1 * visibilityFn1, specLobeBlend);
+
+ float fresnel = lerp(specReflectance, 1.0, pow(1.0 - LdotH, 5.0));
+ float specResult = ndfResult * fresnel;
+ // Darken spec where the *geometric* NdotL gets too low -
+ // avoids it showing up on bumps in shadowed areas
+ float edgeDarken = saturate(5.0 * dot(normalGeom, g_vecDirectionalLight));
+ float3 rgbLitSpecular = g_rgbDirectionalLight * (NdotL * edgeDarken * specResult * shadow);
+
+ // IBL spec - again two-lobe
+ float3 vecReflect = reflect(-vecCamera, normalShade);
+ float gloss0 = gloss;
+ float gloss1 = saturate(2.0 * gloss);
+ float fresnelIBL0 = lerp(specReflectance, 1.0,
+ pow(1.0 - NdotV, 5.0) / (-3.0 * gloss0 + 4.0));
+ float mipLevel0 = -9.0 * gloss0 + 9.0;
+ float3 iblSpec0 = fresnelIBL0 * g_texCubeSpec.SampleLevel(
+ g_ssTrilinearRepeat, vecReflect, mipLevel0);
+ float fresnelIBL1 = lerp(specReflectance, 1.0,
+ pow(1.0 - NdotV, 5.0) / (-3.0 * gloss1 + 4.0));
+ float mipLevel1 = -9.0 * gloss1 + 9.0;
+ float3 iblSpec1 = fresnelIBL1 * g_texCubeSpec.SampleLevel(
+ g_ssTrilinearRepeat, vecReflect, mipLevel1);
+ rgbLitSpecular += lerp(iblSpec0, iblSpec1, specLobeBlend);
+
+ return rgbLitSpecular;
+}
+
+
+
+// Master lighting routine
+
+void LightingMegashader(
+ in Vertex i_vtx,
+ in float3 i_vecCamera,
+ in float4 i_uvzwShadow,
+ in float3 rgbDiffuse,
+ in float3 normalTangent,
+ in float3 normalTangentBlurred,
+ in float specReflectance,
+ in float gloss,
+ in float3 rgbDeepScatter,
+ in GFSDK_FaceWorks_CBData faceworksData,
+ out float3 o_rgbLit,
+ uniform bool useNormalMap,
+ uniform bool useSSS,
+ uniform bool useDeepScatter)
+{
+ float3 normalGeom = normalize(i_vtx.m_normal);
+ float3 vecCamera = normalize(i_vecCamera);
+ float2 uv = i_vtx.m_uv;
+
+ float3 normalShade, normalBlurred;
+ if (useNormalMap)
+ {
+ // Transform normal maps to world space
+
+ float3x3 matTangentToWorld = float3x3(
+ normalize(i_vtx.m_tangent),
+ normalize(cross(normalGeom, i_vtx.m_tangent)),
+ normalGeom);
+
+ normalShade = normalize(mul(normalTangent, matTangentToWorld));
+
+ if (useSSS || useDeepScatter)
+ {
+ normalBlurred = normalize(mul(normalTangentBlurred, matTangentToWorld));
+ }
+ }
+ else
+ {
+ normalShade = normalGeom;
+ normalBlurred = normalGeom;
+ }
+
+ // Evaluate shadow map
+ float shadow = EvaluateShadowVSM(i_uvzwShadow, normalGeom);
+
+ float3 rgbLitDiffuse;
+ if (useSSS)
+ {
+ // Evaluate diffuse lighting
+ float3 rgbDiffuseLight = EvaluateSSSDiffuseLight(
+ normalGeom, normalShade, normalBlurred,
+ shadow, i_vtx.m_curvature, faceworksData);
+ rgbLitDiffuse = rgbDiffuseLight * rgbDiffuse;
+
+ // Remap shadow to 1/3-as-wide penumbra to match shadow from LUT.
+ shadow = GFSDK_FaceWorks_SharpenShadow(shadow, g_shadowSharpening);
+ }
+ else
+ {
+ // Remap shadow to 1/3-as-wide penumbra to match shadow in SSS case.
+ shadow = GFSDK_FaceWorks_SharpenShadow(shadow, g_shadowSharpening);
+
+ // Evaluate diffuse lighting
+ float3 rgbDiffuseLight = EvaluateDiffuseLight(normalGeom, normalShade, shadow);
+ rgbLitDiffuse = rgbDiffuseLight * rgbDiffuse;
+ }
+
+ // Evaluate specular lighting
+ float3 rgbLitSpecular = EvaluateSpecularLight(
+ normalGeom, normalShade, vecCamera,
+ specReflectance, gloss,
+ shadow);
+
+ // Put it all together
+ o_rgbLit = rgbLitDiffuse + rgbLitSpecular;
+
+ if (useDeepScatter)
+ {
+ float3 uvzShadow = i_uvzwShadow.xyz / i_uvzwShadow.w;
+
+ // Apply normal offset to avoid silhouette edge artifacts
+ // !!!UNDONE: move this to vertex shader
+ float3 normalShadow = mul(normalGeom, g_matWorldToUvzShadowNormal);
+ uvzShadow += normalShadow * g_deepScatterNormalOffset;
+
+ float thickness = GFSDK_FaceWorks_EstimateThicknessFromParallelShadowPoisson32(
+ faceworksData,
+ g_texShadowMap, g_ssBilinearClamp, uvzShadow);
+
+ float deepScatterFactor = GFSDK_FaceWorks_EvaluateDeepScatterDirectLight(
+ faceworksData,
+ normalBlurred, g_vecDirectionalLight, thickness);
+ rgbDeepScatter *= g_deepScatterIntensity;
+ o_rgbLit += (g_deepScatterIntensity * deepScatterFactor) * rgbDeepScatter *
+ rgbDiffuse * g_rgbDirectionalLight;
+ }
+
+ // Apply tonemapping to the result
+ o_rgbLit = Tonemap(o_rgbLit);
+}
+
+#endif // LIGHTING_HLSLI