diff options
| author | Marco Foco <[email protected]> | 2016-03-07 15:47:07 +0100 |
|---|---|---|
| committer | Marco Foco <[email protected]> | 2016-03-08 16:04:19 +0100 |
| commit | cd6e0492903f8a9eb5efa14263d7d9ab092517de (patch) | |
| tree | 05c010b75bf777335565819dcceb140886c5a7e9 /samples/d3d11/shaders/lighting.hlsli | |
| download | faceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.tar.xz faceworks-cd6e0492903f8a9eb5efa14263d7d9ab092517de.zip | |
FaceWorks 1.0
Diffstat (limited to 'samples/d3d11/shaders/lighting.hlsli')
| -rw-r--r-- | samples/d3d11/shaders/lighting.hlsli | 293 |
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 +// Email: [email protected] +// 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 |