浏览代码

Merge pull request #182 from EvgeniiG/master

Fix shadows for POM & tess, and add 3 SSS texturing modes
/Branch_Batching2
GitHub 8 年前
当前提交
a7e808ac
共有 13 个文件被更改,包括 241 次插入112 次删除
  1. 95
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  2. 20
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader
  4. 46
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  5. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  6. 46
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  7. 12
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  8. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader
  9. 49
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  10. 13
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs
  11. 51
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl
  12. 10
      Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl
  13. 3
      Assets/ScriptableRenderPipeline/ShaderLibrary/PerPixelDisplacement.hlsl

95
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


public readonly GUIContent sssProfileLerpWeight = new GUIContent("Filter interpolation", "Controls linear interpolation between the two Gaussian filters.");
public readonly GUIContent sssProfileTransmission = new GUIContent("Enable transmission", "Toggles simulation of light passing through thin objects. Depends on the thickness of the material.");
public readonly GUIContent sssProfileThicknessRemap = new GUIContent("Thickness remap", "Remaps the thickness parameter from [0, 1] to the desired range.");
public readonly GUIContent sssTexturingMode = new GUIContent("Texturing mode", "Specifies when the diffuse texture should be applied.");
public readonly GUIContent[] sssTexturingModeOptions = new GUIContent[3] { new GUIContent("Pre-scatter", "Before the blurring pass. Effectively results in the diffuse texture getting blurred together with the lighting."), new GUIContent("Post-scatter", "After the blurring pass. Effectively preserves the sharpness of the diffuse texture."), new GUIContent("Pre- and post-scatter", "Both before and after the blurring pass.") };
public readonly GUIStyle centeredMiniBoldLabel = new GUIStyle(GUI.skin.label);

SerializedProperty m_RenderingUseDepthPrepass = null;
// Subsurface Scattering Settings
SerializedProperty m_TexturingMode = null;
SerializedProperty m_Profiles = null;
SerializedProperty m_NumProfiles = null;

m_RenderingUseDepthPrepass = FindProperty(x => x.renderingSettings.useDepthPrepass);
// Subsurface Scattering Settings
m_TexturingMode = FindProperty(x => x.sssSettings.texturingMode);
m_Profiles = FindProperty(x => x.sssSettings.profiles);
m_NumProfiles = m_Profiles.FindPropertyRelative("Array.size");
}

EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_NumProfiles, styles.sssNumProfiles);
EditorGUILayout.PropertyField(m_Profiles);
m_TexturingMode.intValue = EditorGUILayout.Popup(styles.sssTexturingMode, m_TexturingMode.intValue, styles.sssTexturingModeOptions, (GUILayoutOption[])null);
if (m_Profiles.isExpanded)
for (int i = 0, n = Math.Min(m_Profiles.arraySize, SubsurfaceScatteringSettings.maxNumProfiles); i < n; i++)
EditorGUI.indentLevel++;
SerializedProperty profile = m_Profiles.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(profile, styles.sssProfiles[i]);
for (int i = 0, n = Math.Min(m_Profiles.arraySize, SubsurfaceScatteringSettings.maxNumProfiles); i < n; i++)
if (profile.isExpanded)
SerializedProperty profile = m_Profiles.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(profile, styles.sssProfiles[i]);
EditorGUI.indentLevel++;
if (profile.isExpanded)
{
EditorGUI.indentLevel++;
SerializedProperty profileStdDev1 = profile.FindPropertyRelative("stdDev1");
SerializedProperty profileStdDev2 = profile.FindPropertyRelative("stdDev2");
SerializedProperty profileLerpWeight = profile.FindPropertyRelative("lerpWeight");
SerializedProperty profileTransmission = profile.FindPropertyRelative("enableTransmission");
SerializedProperty profileThicknessRemap = profile.FindPropertyRelative("thicknessRemap");
SerializedProperty profileStdDev1 = profile.FindPropertyRelative("stdDev1");
SerializedProperty profileStdDev2 = profile.FindPropertyRelative("stdDev2");
SerializedProperty profileLerpWeight = profile.FindPropertyRelative("lerpWeight");
SerializedProperty profileTransmission = profile.FindPropertyRelative("enableTransmission");
SerializedProperty profileThicknessRemap = profile.FindPropertyRelative("thicknessRemap");
EditorGUILayout.PropertyField(profileStdDev1, styles.sssProfileStdDev1);
EditorGUILayout.PropertyField(profileStdDev2, styles.sssProfileStdDev2);
EditorGUILayout.PropertyField(profileLerpWeight, styles.sssProfileLerpWeight);
EditorGUILayout.PropertyField(profileTransmission, styles.sssProfileTransmission);
EditorGUILayout.PropertyField(profileStdDev1, styles.sssProfileStdDev1);
EditorGUILayout.PropertyField(profileStdDev2, styles.sssProfileStdDev2);
EditorGUILayout.PropertyField(profileLerpWeight, styles.sssProfileLerpWeight);
EditorGUILayout.PropertyField(profileTransmission, styles.sssProfileTransmission);
Vector2 thicknessRemap = profileThicknessRemap.vector2Value;
EditorGUILayout.LabelField("Min thickness: ", thicknessRemap.x.ToString());
EditorGUILayout.LabelField("Max thickness: ", thicknessRemap.y.ToString());
EditorGUILayout.MinMaxSlider(styles.sssProfileThicknessRemap, ref thicknessRemap.x, ref thicknessRemap.y, 0, 10);
profileThicknessRemap.vector2Value = thicknessRemap;
Vector2 thicknessRemap = profileThicknessRemap.vector2Value;
EditorGUILayout.LabelField("Min thickness: ", thicknessRemap.x.ToString());
EditorGUILayout.LabelField("Max thickness: ", thicknessRemap.y.ToString());
EditorGUILayout.MinMaxSlider(styles.sssProfileThicknessRemap, ref thicknessRemap.x, ref thicknessRemap.y, 0, 10);
profileThicknessRemap.vector2Value = thicknessRemap;
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssProfilePreview0, styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(styles.sssProfilePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(styles.sssProfilePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssProfilePreview0, styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(styles.sssProfilePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.LabelField(styles.sssProfilePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
// Draw the profile.
m_ProfileMaterial.SetColor("_StdDev1", profileStdDev1.colorValue);
m_ProfileMaterial.SetColor("_StdDev2", profileStdDev2.colorValue);
m_ProfileMaterial.SetFloat("_LerpWeight", profileLerpWeight.floatValue);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256, 256), m_ProfileImages[i], m_ProfileMaterial, ScaleMode.ScaleToFit, 1.0f);
// Draw the profile.
m_ProfileMaterial.SetColor("_StdDev1", profileStdDev1.colorValue);
m_ProfileMaterial.SetColor("_StdDev2", profileStdDev2.colorValue);
m_ProfileMaterial.SetFloat("_LerpWeight", profileLerpWeight.floatValue);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256, 256), m_ProfileImages[i], m_ProfileMaterial, ScaleMode.ScaleToFit, 1.0f);
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssTransmittancePreview0, styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(styles.sssTransmittancePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssTransmittancePreview0, styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(styles.sssTransmittancePreview1, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
// Draw the transmittance graph.
m_TransmittanceMaterial.SetColor("_StdDev1", profileStdDev1.colorValue);
m_TransmittanceMaterial.SetColor("_StdDev2", profileStdDev2.colorValue);
m_TransmittanceMaterial.SetFloat("_LerpWeight", profileLerpWeight.floatValue);
m_TransmittanceMaterial.SetVector("_ThicknessRemap", profileThicknessRemap.vector2Value);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImages[i], m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);
// Draw the transmittance graph.
m_TransmittanceMaterial.SetColor("_StdDev1", profileStdDev1.colorValue);
m_TransmittanceMaterial.SetColor("_StdDev2", profileStdDev2.colorValue);
m_TransmittanceMaterial.SetFloat("_LerpWeight", profileLerpWeight.floatValue);
m_TransmittanceMaterial.SetVector("_ThicknessRemap", profileThicknessRemap.vector2Value);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImages[i], m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;

20
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


m_CameraFilteringBufferRT = new RenderTargetIdentifier(m_CameraFilteringBuffer);
m_FilterSubsurfaceScattering = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CombineSubsurfaceScattering");
m_FilterSubsurfaceScattering.DisableKeyword("FILTER_HORIZONTAL");
m_FilterSubsurfaceScattering.DisableKeyword("FILTER_HORIZONTAL_AND_COMBINE");
m_FilterSubsurfaceScattering.EnableKeyword("FILTER_HORIZONTAL");
m_FilterSubsurfaceScattering.EnableKeyword("FILTER_HORIZONTAL_AND_COMBINE");
m_FilterAndCombineSubsurfaceScattering.SetFloat("_DstBlend", (float)BlendMode.One);
InitializeDebugMaterials();

Shader.SetGlobalInt("_TransmissionFlags", sssParameters.transmissionFlags);
cmd.SetGlobalFloatArray("_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray("_HalfRcpVariancesAndLerpWeights", sssParameters.halfRcpVariancesAndLerpWeights);
switch (sssParameters.texturingMode)
{
case SubsurfaceScatteringSettings.TexturingMode.PreScatter:
cmd.EnableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.DisableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
case SubsurfaceScatteringSettings.TexturingMode.PostScatter:
cmd.DisableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.EnableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
case SubsurfaceScatteringSettings.TexturingMode.PreAndPostScatter:
cmd.DisableShaderKeyword("SSS_PRE_SCATTER_TEXTURING");
cmd.DisableShaderKeyword("SSS_POST_SCATTER_TEXTURING");
break;
}
if (globalDebugSettings.renderingDebugSettings.enableSSS)
{

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Resources/Deferred.shader


HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma vertex Vert
#pragma fragment Frag

// Split lighting is utilized during the SSS pass.
#pragma multi_compile _ OUTPUT_SPLIT_LIGHTING
// #ifdef OUTPUT_SPLIT_LIGHTING
#pragma shader_feature _ SSS_PRE_SCATTER_TEXTURING SSS_POST_SCATTER_TEXTURING
// #endif
#pragma multi_compile _ LIGHTING_DEBUG

46
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


#endif
}
void ConfigureTexturingForSSS(inout BSDFData bsdfData)
{
#ifdef SSS_PRE_SCATTER_TEXTURING
bsdfData.diffuseColor = bsdfData.diffuseColor;
#elif SSS_POST_SCATTER_TEXTURING
bsdfData.diffuseColor = float3(1, 1, 1);
#else // combine pre-scatter and post-scatter texturing
bsdfData.diffuseColor = sqrt(bsdfData.diffuseColor);
#endif
}
// Evaluates transmittance for a linear combination of two normalized 2D Gaussians.
// Computes results for each color channel separately.
// Ref: Real-Time Realistic Skin Translucency (2010), equation 9 (modified).

bsdfData.fresnel0 = surfaceData.specularColor;
}
#ifdef OUTPUT_SPLIT_LIGHTING
ConfigureTexturingForSSS(bsdfData);
#endif
return bsdfData;
}

#endif
}
void DecodeFromGBuffer(
float4 DecodeGBuffer0(GBufferType0 encodedGBuffer0)
{
float4 decodedGBuffer0;
#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
decodedGBuffer0.x = UnpackUIntToFloat(encodedGBuffer0.x, 8, 0);
decodedGBuffer0.y = UnpackUIntToFloat(encodedGBuffer0.x, 8, 8);
decodedGBuffer0.z = UnpackUIntToFloat(encodedGBuffer0.y, 8, 0);
decodedGBuffer0.w = UnpackUIntToFloat(encodedGBuffer0.y, 8, 8);
decodedGBuffer0.xyz = Gamma20ToLinear(encodedGBuffer0.xyz);
#else
decodedGBuffer0 = encodedGBuffer0;
#endif
return decodedGBuffer0;
}
void DecodeFromGBuffer(
#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
GBufferType0 inGBufferU0,
GBufferType1 inGBufferU1,

#if SHADEROPTIONS_PACK_GBUFFER_IN_U16
float4 inGBuffer0, inGBuffer1, inGBuffer2, inGBuffer3;
inGBuffer0.x = UnpackUIntToFloat(inGBufferU0.x, 8, 0);
inGBuffer0.y = UnpackUIntToFloat(inGBufferU0.x, 8, 8);
inGBuffer0.z = UnpackUIntToFloat(inGBufferU0.y, 8, 0);
inGBuffer0.w = UnpackUIntToFloat(inGBufferU0.y, 8, 8);
inGBuffer0.xyz = Gamma20ToLinear(inGBuffer0.xyz);
inGBuffer0 = DecodeGBuffer0(inGBufferU0);
inGBuffer2.x = UnpackUIntToFloat(inGBufferU1.x, 8, 0);
inGBuffer2.y = UnpackUIntToFloat(inGBufferU1.x, 8, 8);
inGBuffer2.z = UnpackUIntToFloat(inGBufferU1.y, 8, 0);

bakeDiffuseLighting = inGBuffer3.rgb;
#ifdef OUTPUT_SPLIT_LIGHTING
ConfigureTexturingForSSS(bsdfData);
#endif
ApplyDebugToBSDFData(bsdfData);
}

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go futher in dev
//#pragma enable_d3d11_debug_symbols
// #pragma enable_d3d11_debug_symbols
//-------------------------------------------------------------------------------------
// Variant

46
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


PerPixelHeightDisplacementParam ppdParam;
float height; // final height processed
float NdotV;
// planar/triplanar
float2 uvXZ;

layerTexCoord.base.uvXY += offsetXY;
layerTexCoord.details.uvXY += offsetXY;
height += layerTexCoord.triplanarWeights.z * planeHeight;
NdotV = 1; // TODO.
#ifdef SURFACE_GRADIENT
// The TBN is not normalize, normalize it to do per pixel displacement
#ifdef SURFACE_GRADIENT
// The TBN is not normalize, normalize it to do per pixel displacement
#else
float3x3 worldToTangent = input.worldToTangent;
#endif
#endif
NdotV = viewDirTS.z;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);

// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
return maxHeight - height * maxHeight;
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
return tilingScale * verticalDisplacement / NdotV;
}
return 0.0;

float height = (SAMPLE_UVMAPPING_TEXTURE2D_LOD(_HeightMap, sampler_HeightMap, layerTexCoord.base, lod).r - _HeightCenter) * _HeightAmplitude;
#ifdef _TESSELLATION_TILING_SCALE
// When we change the tiling, we have want to conserve the ratio with the displacement (and this is consistent with per pixel displacement)
height /= max(_BaseColorMap_ST.x, _BaseColorMap_ST.y);
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
height *= tilingScale;
#endif
return height;
}

float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, _ViewProjMatrix, posInput);
ApplyDepthOffsetPositionInput(GetCameraForwardDir(), depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
// We perform the conversion to world of the normalTS outside of the GetSurfaceData

#endif
float height; // final height processed
float NdotV;
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)

// Apply to all layer that used triplanar
*/
height = 1;
NdotV = 1;
}
else
{

ppdParam.uv[3] = layerTexCoord.base3.uv;
#ifdef SURFACE_GRADIENT
float3x3 worldToTangent = input.worldToTangent;
#ifdef SURFACE_GRADIENT
float3x3 worldToTangent = input.worldToTangent;
#else
float3x3 worldToTangent = input.worldToTangent;
#endif
#endif
NdotV = viewDirTS.z;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);

// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
return maxHeight - height * maxHeight;
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap0_ST.x, _BaseColorMap0_ST.y));
return tilingScale * verticalDisplacement / NdotV;
}
return 0.0;

float depthOffset = ApplyPerPixelDisplacement(input, V, layerTexCoord);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, _ViewProjMatrix, posInput);
ApplyDepthOffsetPositionInput(GetCameraForwardDir(), depthOffset, GetWorldToHClipMatrix(), posInput);
#endif
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;

12
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl


bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes);
bool faceCull = false;
// We use the position of the primary (scene view) camera in order
// to have identical tessellation levels for both the scene view and
// shadow views. Otherwise, depth comparisons become meaningless!
float3 camPosWS = _WorldSpaceCameraPos;
faceCull = BackFaceCullTriangle(p0, p1, p2, _TessellationBackFaceCullEpsilon, _WorldSpaceCameraPos);
faceCull = BackFaceCullTriangle(p0, p1, p2, _TessellationBackFaceCullEpsilon, camPosWS);
}
#endif

// Distance based tessellation
if (_TessellationFactorMaxDistance > 0.0)
{
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, _WorldSpaceCameraPos, _TessellationFactorMinDistance, _TessellationFactorMaxDistance);
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, camPosWS, _TessellationFactorMinDistance, _TessellationFactorMaxDistance);
// We square the disance factor as it allow a better percptual descrease of vertex density.
tessFactor *= distFactor * distFactor;
}

#else
float2(0.0, 0.0),
#endif
input.positionWS,
input.positionWS,
input.normalWS,
layerTexCoord);

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader


#pragma target 5.0
#pragma only_renderers d3d11 ps4// TEMP: until we go futher in dev
// #pragma enable_d3d11_debug_symbols
//-------------------------------------------------------------------------------------
// Variant

49
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader


HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma multi_compile _ FILTER_HORIZONTAL
#pragma shader_feature _ SSS_PRE_SCATTER_TEXTURING SSS_POST_SCATTER_TEXTURING
#pragma multi_compile _ FILTER_HORIZONTAL_AND_COMBINE
//-------------------------------------------------------------------------------------
// Include

#include "HDRenderPipeline/ShaderConfig.cs.hlsl"
#define UNITY_MATERIAL_LIT // Need to be defined before including Material.hlsl
#include "HDRenderPipeline/Material/Material.hlsl"
//-------------------------------------------------------------------------------------
// Inputs & outputs

#define N_SAMPLES 7
float4 _FilterKernels[N_PROFILES][N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[N_PROFILES]; // RGB for chromatic, A for achromatic
float4 _FilterKernels[N_PROFILES][N_SAMPLES]; // RGB = weights, A = radial distance
float4 _HalfRcpWeightedVariances[N_PROFILES]; // RGB for chromatic, A for achromatic
#ifndef SSS_PRE_SCATTER_TEXTURING
TEXTURE2D(_GBufferTexture0); // RGB = baseColor, A = spec. occlusion
#endif
TEXTURE2D(_GBufferTexture2);
TEXTURE2D(_IrradianceSource);
TEXTURE2D(_GBufferTexture2); // R = SSS radius, G = SSS thickness, A = SSS profile
TEXTURE2D(_IrradianceSource); // RGB = irradiance on the back side of the object
//-------------------------------------------------------------------------------------
// Implementation

float3 centerPosVS = ComputeViewSpacePosition(posInput.positionSS, rawDepth, _InvProjMatrix);
// Compute the dimensions of the surface fragment viewed as a quad facing the camera.
float fragWidth = ddx(centerPosVS.x);
float fragheight = ddy(centerPosVS.y);
float fragWidth = ddx_fine(centerPosVS.x);
float fragheight = ddy_fine(centerPosVS.y);
#ifdef FILTER_HORIZONTAL
#ifdef FILTER_HORIZONTAL_AND_COMBINE
float stepSize = stepSizeX;
float2 unitDirection = float2(1, 0);
#else

#else
float halfRcpVariance = _HalfRcpWeightedVariances[profileID].a;
#endif
// Accumulate filtered irradiance (already weighted by (albedo / Pi)).
float3 totalIrradiance = sampleIrradiance * sampleWeight;
// Accumulate filtered irradiance.
float3 totalIrradiance = sampleWeight * sampleIrradiance;
// Make sure bilateral filtering does not cause energy loss.
// TODO: ask Morten if there is a better way to do this.

sampleWeight = _FilterKernels[profileID][i].rgb;
rawDepth = LOAD_TEXTURE2D(_MainDepthTexture, samplePosition).r;
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
sampleIrradiance = LOAD_TEXTURE2D(_IrradianceSource, samplePosition).rgb;
// Apply bilateral weighting.
// Ref #1: Skin Rendering by Pseudo–Separable Cross Bilateral Filtering.

sampleWeight *= exp(-zDistance * zDistance * halfRcpVariance);
totalIrradiance += sampleIrradiance * sampleWeight;
totalIrradiance += sampleWeight * sampleIrradiance;
#ifdef SSS_PRE_SCATTER_TEXTURING
float3 diffuseContrib = float3(1, 1, 1);
#elif SSS_POST_SCATTER_TEXTURING
float3 diffuseColor = DecodeGBuffer0(LOAD_TEXTURE2D(_GBufferTexture0, posInput.unPositionSS)).rgb;
float3 diffuseContrib = diffuseColor;
#else // combine pre-scatter and post-scatter texturing
float3 diffuseColor = DecodeGBuffer0(LOAD_TEXTURE2D(_GBufferTexture0, posInput.unPositionSS)).rgb;
float3 diffuseContrib = sqrt(diffuseColor);
#endif
#ifdef FILTER_HORIZONTAL_AND_COMBINE
return float4(diffuseContrib * totalIrradiance / totalWeight, 1.0);
#else
#endif
}
ENDHLSL
}

13
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringSettings.cs


[Serializable]
public class SubsurfaceScatteringSettings
{
public enum TexturingMode : int { PreScatter = 0, PostScatter = 1, PreAndPostScatter = 2, MaxValue = 2 };
public TexturingMode texturingMode;
public int transmissionFlags;
public SubsurfaceScatteringProfile[] profiles;
public float[] thicknessRemaps;

public SubsurfaceScatteringSettings()
{
numProfiles = 1;
profiles = new SubsurfaceScatteringProfile[numProfiles];
numProfiles = 1;
texturingMode = 0;
profiles = new SubsurfaceScatteringProfile[numProfiles];
for (int i = 0; i < numProfiles; i++)
{

Array.Resize(ref profiles, maxNumProfiles);
}
numProfiles = profiles.Length;
transmissionFlags = 0;
numProfiles = profiles.Length;
texturingMode = (TexturingMode)Math.Max(0, Math.Min((int)texturingMode, (int)TexturingMode.MaxValue));
if (thicknessRemaps == null)
{

filterKernels = new Vector4[maxNumProfiles * SubsurfaceScatteringProfile.numSamples];
}
transmissionFlags = 0;
Color c = new Color();
for (int i = 0; i < numProfiles; i++)

51
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
}
float3 GetCurrentCameraPosition()
{
#if SHADERPASS != SHADERPASS_DEPTH_ONLY
return _WorldSpaceCameraPos;
#else
// TEMP: this is rather expensive. Then again, we need '_WorldSpaceCameraPos'
// to represent the position of the primary (scene view) camera in order to
// have identical tessellation levels for both the scene view and shadow views.
// Otherwise, depth comparisons become meaningless!
float4x4 viewMat = transpose(GetWorldToViewMatrix());
float3 rotCamPos = viewMat[3].xyz;
return mul((float3x3)viewMat, -rotCamPos);
#endif
}
// Returns the forward direction of the current camera in the world space.
float3 GetCameraForwardDir()
{
float4x4 viewMat = GetWorldToViewMatrix();
return -viewMat[2].xyz;
}
float3 V = _WorldSpaceCameraPos.xyz - positionWS;
// Uncomment this once the compiler bug is fixed.
// if (unity_OrthoParams.w == 1.0)
// {
// float4x4 M = GetWorldToViewMatrix();
// V = M[1].xyz;
// }
return normalize(V);
#if SHADERPASS != SHADERPASS_DEPTH_ONLY
if (unity_OrthoParams.w == 0)
#else
// TODO: set 'unity_OrthoParams' during the shadow pass.
if (GetWorldToHClipMatrix()[3].x != 0 &&
GetWorldToHClipMatrix()[3].y != 0 &&
GetWorldToHClipMatrix()[3].z != 0 &&
GetWorldToHClipMatrix()[3].w != 1)
#endif
{
// Perspective
float3 V = GetCurrentCameraPosition() - positionWS;
return normalize(V);
}
else
{
// Orthographic
return -GetCameraForwardDir();
}
}
float3x3 CreateWorldToTangent(float3 normal, float3 tangent, float flipSign)

10
Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl


// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
// It may be necessary to flip the Y axis as the origin of the screen-space coordinate system
// of Direct3D is at the top left corner of the screen, with the Y axis pointing downwards.
void UpdatePositionInput(float depthRaw, float4x4 invViewProjMatrix, float4x4 ViewProjMatrix,
void UpdatePositionInput(float depthRaw, float4x4 invViewProjMatrix, float4x4 viewProjMatrix,
inout PositionInputs posInput, bool flipY = false)
{
posInput.depthRaw = depthRaw;

posInput.positionWS = hpositionWS.xyz / hpositionWS.w;
// The compiler should optimize this (less expensive than reconstruct depth VS from depth buffer)
posInput.depthVS = mul(ViewProjMatrix, float4(posInput.positionWS, 1.0)).w;
posInput.depthVS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
}
// It may be necessary to flip the Y axis as the origin of the screen-space coordinate system

return positionVS.xyz / positionVS.w;
}
// 'depthOffsetVS' is in the direction opposite to the view vector 'V', e.i. away from the camera.
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float4x4 viewProjMatrix, inout PositionInputs posInput)
// 'depthOffsetVS' is always along the forward direction 'camDirWS' pointing away from the camera.
void ApplyDepthOffsetPositionInput(float3 camDirWS, float depthOffsetVS, float4x4 viewProjMatrix, inout PositionInputs posInput)
posInput.positionWS += depthOffsetVS * -V; // opposite to V
posInput.positionWS += depthOffsetVS * camDirWS;
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0));
posInput.depthRaw = positionCS.z / positionCS.w;

3
Assets/ScriptableRenderPipeline/ShaderLibrary/PerPixelDisplacement.hlsl


// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, float maxHeight, PerPixelHeightDisplacementParam ppdParam, out float outHeight)
{
// TEMP: 0.1 to achieve parity between tessellation and POM w.r.t. height for a single tile.
// TODO: for tiling, the max. height of the tessellated height map should be reduced by NumTiles.
// TODO: explain this factor! Necessary to achieve parity between tessellation and POM w.r.t. height.
maxHeight *= 0.1;
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion

正在加载...
取消
保存