浏览代码

Merge pull request #284 from EvgeniiG/master

Tweak SSS transmission
/RenderPassXR_Sandbox
GitHub 8 年前
当前提交
6af2a906
共有 13 个文件被更改,包括 106 次插入202 次删除
  1. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 35
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  3. 12
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  4. 103
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  5. 30
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  6. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.hlsl
  7. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawSssProfile.shader
  8. 13
      Assets/ScriptableRenderPipeline/ShaderLibrary/CommonMaterial.hlsl
  9. 14
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader
  10. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawGaussianProfile.shader.meta
  11. 84
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawGaussianProfile.shader
  12. 0
      /Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader.meta
  13. 0
      /Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


Shader.SetGlobalInt( "_TransmissionFlags", (int)sssParameters.transmissionFlags);
cmd.SetGlobalFloatArray( "_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray("_ShapeParameters", sssParameters.shapeParameters);
cmd.SetGlobalVectorArray("_SurfaceAlbedos", sssParameters.surfaceAlbedos);
cmd.SetGlobalVectorArray("_VolumeAlbedos", sssParameters.volumeAlbedos);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();

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


#define LTC_LUT_OFFSET (0.5 * rcp(LTC_LUT_SIZE))
#define MIN_N_DOT_V 0.0001 // The minimum value of 'NdotV'
#define SSS_WRAP_ANGLE (PI/12) // Used for wrap lighting
#define SSS_WRAP_LIGHT cos(PI/2 - SSS_WRAP_ANGLE)
uint _EnableSSS; // Globally toggles subsurface scattering on/off
uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter

float4 _SurfaceAlbedos[SSS_N_PROFILES]; // RGB = color, A = unused
float4 _VolumeAlbedos[SSS_N_PROFILES]; // RGB = color, A = unused
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material

if (bsdfData.enableTransmission)
{
bsdfData.transmittance = ComputeTransmittance(_ShapeParameters[subsurfaceProfile].rgb,
_SurfaceAlbedos[subsurfaceProfile].rgb,
_VolumeAlbedos[subsurfaceProfile].rgb,
bsdfData.thickness, bsdfData.subsurfaceRadius);
}

float3 positionWS = posInput.positionWS;
float3 L = -lightData.forward; // Lights are pointing backward in Unity
float illuminance = saturate(dot(bsdfData.normalWS, L));
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);

[branch] if (bsdfData.enableTransmission)
{
float LdotV = dot(L, V); // Also computed in BSDF()
// Compute the normal at the back of the object as R = reflect(N, -V)
// float RdotL = NdotL - 2 * preLightData.NdotV * LdotV;
float illuminance = saturate(-LdotV);
// Reverse the normal + do some wrap lighting to have a nicer transition between regular lighting and transmittance
// Ref: Steve McAuley - Energy-Conserving Wrapped Diffuse
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT);
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;

float attenuation = GetDistanceAttenuation(unL, lightData.invSqrAttenuationRadius);
// Reminder: lights are ortiented backward (-Z)
attenuation *= GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
float illuminance = saturate(dot(bsdfData.normalWS, L)) * attenuation;
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL * attenuation);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);

[branch] if (bsdfData.enableTransmission)
{
float LdotV = dot(L, V); // Also computed in BSDF()
// Compute the normal at the back of the object as R = reflect(N, -V)
// float RdotL = NdotL - 2 * preLightData.NdotV * LdotV;
float illuminance = saturate(-LdotV * attenuation);
// Reverse the normal + do some wrap lighting to have a nicer transition between regular lighting and transmittance
// Ref: Steve McAuley - Energy-Conserving Wrapped Diffuse
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * attenuation;
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;

float clipFactor = ((positionLS.z >= 0) && (abs(positionNDC.x) <= 1 && abs(positionNDC.y) <= 1)) ? 1 : 0;
float3 L = -lightData.forward; // Lights are pointing backward in Unity
float illuminance = saturate(dot(bsdfData.normalWS, L) * clipFactor);
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL * clipFactor);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);

[branch] if (bsdfData.enableTransmission)
{
float LdotV = dot(L, V); // Also computed in BSDF()
// Compute the normal at the back of the object as R = reflect(N, -V)
// float RdotL = NdotL - 2 * preLightData.NdotV * LdotV;
float illuminance = saturate(-LdotV * clipFactor);
// Reverse the normal + do some wrap lighting to have a nicer transition between regular lighting and transmittance
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * clipFactor;
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;

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


// Done one time for all layered - cumulate with spec occ alpha for now
surfaceData.specularOcclusion *= GetHorizonOcclusion(V, surfaceData.normalWS, interpolatedVertexNormal, _HorizonFade);
uint transmissionMode = BitFieldExtract(_TransmissionFlags, 2u, 2u * surfaceData.subsurfaceProfile);
if (transmissionMode != SSS_TRSM_MODE_THIN)
{
// Convert thickness along the normal to thickness along the viewing direction.
// We assume that the thickness along the normal corresponds to the diameter of a sphere.
// We then find a position on the sphere which corresponds to the normal, and
// compute the length of the chord of the sphere along the viewing direction.
// We add a small bias to (hopefully) have non-zero thickness.
surfaceData.thickness *= saturate(dot(interpolatedVertexNormal, V) + 0.01);
}
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
}

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


return /* 0.25 * */ S * (expOneThird + expOneThird * expOneThird * expOneThird);
}
// Computes F(x)/P(x), s.t. x = sqrt(r^2 + z^2).
float3 ComputeBilateralWeight(float3 S, float r, float z, float rcpDistScale, float rcpPdf)
// Computes F(x)/P(x), s.t. x = sqrt(r^2 + t^2).
float3 ComputeBilateralWeight(float3 S, float r, float t, float rcpDistScale, float rcpPdf)
float3 valX = KernelValCircle(sqrt(r * r + z * z) * rcpDistScale, S);
float3 valX = KernelValCircle(sqrt(r * r + t * t) * rcpDistScale, S);
float rcpPdfX = rcpPdf * (1 + abs(z) / r);
float rcpPdfX = rcpPdf * (1 + abs(t) / r);
return valX * rcpPdfX;
}

{ \
float r = kernel[profileID][i][0]; \
/* The relative sample position is known at the compile time. */ \
/* The relative sample position is known at compile time. */ \
float depth = LOAD_TEXTURE2D(_MainDepthTexture, position).r; \
/* TODO: see if making this a [branch] improves performance. */ \
if (any(irradiance) == false) \
if (any(irradiance)) \
{ \
/* Apply bilateral weighting. */ \
float z = LOAD_TEXTURE2D(_MainDepthTexture, position).r; \
float d = LinearEyeDepth(z, _ZBufferParams); \
float t = millimPerUnit * d - (millimPerUnit * centerDepthVS); \
float3 w = ComputeBilateralWeight(shapeParam, r, t, rcpDistScale, rcpPdf); \
\
totalIrradiance += w * irradiance; \
totalWeight += w; \
} \
else \
{ \
/*************************************************************************/ \
/* The irradiance is 0. This could happen for 3 reasons. */ \

/* We do not terminate the loop since we want to gather the contribution */ \
/* of the remaining samples (e.g. in case of hair covering skin). */ \
/*************************************************************************/ \
continue; \
}
#define SSS_LOOP(n, kernel, profileID, shapeParam, centerPosUnSS, centerDepthVS, \
millimPerUnit, scaledPixPerMm, rcpDistScale, totalIrradiance, totalWeight) \
{ \
float centerRcpPdf = kernel[profileID][0][1]; \
float3 centerWeight = KernelValCircle(0, shapeParam) * centerRcpPdf; \
/* Apply bilateral weighting. */ \
float d = LinearEyeDepth(depth, _ZBufferParams); \
float z = millimPerUnit * d - (millimPerUnit * centerDepthVS); \
float3 w = ComputeBilateralWeight(shapeParam, r, z, rcpDistScale, rcpPdf); \
totalIrradiance = centerWeight * centerIrradiance; \
totalWeight = centerWeight; \
totalIrradiance += w * irradiance; \
totalWeight += w; \
/* Perform integration over the screen-aligned plane in the view space. */ \
/* TODO: it would be more accurate to use the tangent plane instead. */ \
[unroll] \
for (uint i = 1; i < n; i++) \
{ \
SSS_ITER(i, n, kernel, profileID, shapeParam, centerPosUnSS, centerDepthVS, \
millimPerUnit, scaledPixPerMm, rcpDistScale, totalIrradiance, totalWeight) \
} \
}
struct Attributes

float4 Frag(Varyings input) : SV_Target
{
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(0, 0));
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float3 unused;

float2 centerPosition = posInput.unPositionSS;
float3 centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, centerPosition).rgb;
float maxDistancePixels = maxDistance * max(scaledPixPerMm.x, scaledPixPerMm.y);
float maxDistInPixels = maxDistance * max(scaledPixPerMm.x, scaledPixPerMm.y);
if (maxDistancePixels < 0.5)
if (maxDistInPixels < 1)
#if SSS_DEBUG
return float4(0, 0, 1, 1);
#else
return float4(bsdfData.diffuseColor * centerIrradiance, 1);
#endif
#if SSS_DEBUG
return float4(0, 0, 1, 1);
#else
return float4(bsdfData.diffuseColor * centerIrradiance, 1);
#endif
}
// Accumulate filtered irradiance and bilateral weights (for renormalization).

[branch]
if (maxDistancePixels < 4)
if (maxDistInPixels < SSS_LOD_THRESHOLD)
#endif
float centerRcpPdf = _FilterKernelsFarField[profileID][0][1];
float3 centerWeight = KernelValCircle(0, shapeParam) * centerRcpPdf;
totalIrradiance = centerWeight * centerIrradiance;
totalWeight = centerWeight;
// Perform integration over the screen-aligned plane in the view space.
// TODO: it would be more accurate to use the tangent plane in the world space.
[unroll]
for (uint i = 1; i < SSS_N_SAMPLES_FAR_FIELD; i++)
{
SSS_ITER(i, SSS_N_SAMPLES_FAR_FIELD, _FilterKernelsFarField,
#else
SSS_LOOP(SSS_N_SAMPLES_FAR_FIELD, _FilterKernelsFarField,
}
#endif
#endif
float centerRcpPdf = _FilterKernelsNearField[profileID][0][1];
float3 centerWeight = KernelValCircle(0, shapeParam) * centerRcpPdf;
totalIrradiance = centerWeight * centerIrradiance;
totalWeight = centerWeight;
// Perform integration over the screen-aligned plane in the view space.
// TODO: it would be more accurate to use the tangent plane in the world space.
[unroll]
for (uint i = 1; i < SSS_N_SAMPLES_NEAR_FIELD; i++)
{
SSS_ITER(i, SSS_N_SAMPLES_NEAR_FIELD, _FilterKernelsNearField,
#else
SSS_LOOP(SSS_N_SAMPLES_NEAR_FIELD, _FilterKernelsNearField,
}
#endif
}
return float4(bsdfData.diffuseColor * totalIrradiance / totalWeight, 1);

30
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs


public const int SSS_NEUTRAL_PROFILE_ID = SSS_N_PROFILES - 1; // Does not result in blurring
public const int SSS_N_SAMPLES_NEAR_FIELD = 55; // Used for extreme close ups; must be a Fibonacci number
public const int SSS_N_SAMPLES_FAR_FIELD = 21; // Used at a regular distance; must be a Fibonacci number
public const int SSS_LOD_THRESHOLD = 4; // The LoD threshold of the near-field kernel (in pixels)
public const int SSS_TRSM_MODE_NONE = 0;
public const int SSS_TRSM_MODE_THIN = 1;
}

public enum TransmissionMode : uint { None = SssConstants.SSS_TRSM_MODE_NONE, ThinObject = SssConstants.SSS_TRSM_MODE_THIN, Regular };
public Color surfaceAlbedo; // Color, 0 to 1
public Color volumeAlbedo; // Color, 0 to 1
public float lenVolMeanFreePath; // Length of the volume mean free path (in millimeters)
public TexturingMode texturingMode;
public TransmissionMode transmissionMode;

public SubsurfaceScatteringProfile()
{
surfaceAlbedo = Color.white;
volumeAlbedo = Color.white;
lenVolMeanFreePath = 0.5f;
texturingMode = TexturingMode.PreAndPostScatter;
transmissionMode = TransmissionMode.None;

[NonSerialized] public uint transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public float[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[NonSerialized] public Vector4[] shapeParameters; // RGB = S = 1 / D, A = filter radius
[NonSerialized] public Vector4[] surfaceAlbedos; // RGB = color, A = unused
[NonSerialized] public Vector4[] volumeAlbedos; // RGB = color, A = unused
[NonSerialized] public float[] worldScales; // Size of the world unit in meters
[NonSerialized] public float[] filterKernelsNearField; // 0 = radius, 1 = reciprocal of the PDF
[NonSerialized] public float[] filterKernelsFarField; // 0 = radius, 1 = reciprocal of the PDF

shapeParameters = new Vector4[shapeParametersLen];
}
const int surfaceAlbedosLen = SssConstants.SSS_N_PROFILES;
if (surfaceAlbedos == null || surfaceAlbedos.Length != surfaceAlbedosLen)
const int volumeAlbedosLen = SssConstants.SSS_N_PROFILES;
if (volumeAlbedos == null || volumeAlbedos.Length != volumeAlbedosLen)
surfaceAlbedos = new Vector4[surfaceAlbedosLen];
volumeAlbedos = new Vector4[volumeAlbedosLen];
}
const int filterKernelsNearFieldLen = 2 * SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD;

worldScales[i] = profiles[i].worldScale;
shapeParameters[i] = profiles[i].shapeParameter;
shapeParameters[i].w = profiles[i].scatteringDistance;
surfaceAlbedos[i] = profiles[i].surfaceAlbedo;
volumeAlbedos[i] = profiles[i].volumeAlbedo;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)
{

int i = SssConstants.SSS_NEUTRAL_PROFILE_ID;
shapeParameters[i] = Vector4.zero;
surfaceAlbedos[i] = Vector4.zero;
volumeAlbedos[i] = Vector4.zero;
worldScales[i] = 1.0f;
for (int j = 0, n = SssConstants.SSS_N_SAMPLES_NEAR_FIELD; j < n; j++)

public readonly GUIContent sssTransmittancePreview0 = new GUIContent("Transmittance Preview");
public readonly GUIContent sssTransmittancePreview1 = new GUIContent("Shows the fraction of light passing through the object for thickness values from the remap.");
public readonly GUIContent sssTransmittancePreview2 = new GUIContent("Can be viewed as a cross section of a slab of material illuminated by white light from the left.");
public readonly GUIContent sssProfileSurfaceAlbedo = new GUIContent("Surface Albedo", "Color which determines the shape of the profile. Alpha is ignored.");
public readonly GUIContent sssProfileSurfaceAlbedo = new GUIContent("Surface Albedo", "Color which determines the shape of the profile. Alpha is ignored. Typically, it is similar to the diffuse color.");
public readonly GUIContent sssProfileVolumeAlbedo = new GUIContent("Volume Albedo", "Color which tints transmitted light. Alpha is ignored. Typically, it is a more saturated version of the diffuse color.");
public readonly GUIContent sssProfileLenVolMeanFreePath = new GUIContent("Volume Mean Free Path", "The length of the volume mean free path (in millimeters) describes the average distance a photon travels within the volume before an extinction event occurs. Determines the effective radius of the filter.");
public readonly GUIContent sssProfileScatteringDistance = new GUIContent("Scattering Distance", "Effective radius of the filter (in millimeters). The blur is energy-preserving, so a wide filter results in a large area with small contributions of individual samples. Reducing the distance increases the sharpness of the result.");
public readonly GUIContent sssTexturingMode = new GUIContent("Texturing Mode", "Specifies when the diffuse texture should be applied.");

private RenderTexture m_ProfileImage, m_TransmittanceImage;
private Material m_ProfileMaterial, m_TransmittanceMaterial;
private SerializedProperty m_LenVolMeanFreePath, m_ScatteringDistance, m_SurfaceAlbedo, m_S,
private SerializedProperty m_LenVolMeanFreePath, m_ScatteringDistance, m_SurfaceAlbedo, m_VolumeAlbedo, m_S,
m_VolumeAlbedo = serializedObject.FindProperty("volumeAlbedo");
m_LenVolMeanFreePath = serializedObject.FindProperty("lenVolMeanFreePath");
m_ScatteringDistance = serializedObject.FindProperty("m_ScatteringDistance");
m_S = serializedObject.FindProperty("m_S");

EditorGUI.BeginChangeCheck();
{
EditorGUILayout.PropertyField(m_SurfaceAlbedo, styles.sssProfileSurfaceAlbedo);
EditorGUILayout.PropertyField(m_SurfaceAlbedo, styles.sssProfileSurfaceAlbedo);
m_LenVolMeanFreePath.floatValue = EditorGUILayout.Slider(styles.sssProfileLenVolMeanFreePath, m_LenVolMeanFreePath.floatValue, 0.01f, 1.0f);
GUI.enabled = false;

m_TexturingMode.intValue = EditorGUILayout.Popup(styles.sssTexturingMode, m_TexturingMode.intValue, styles.sssTexturingModeOptions);
m_TransmissionMode.intValue = EditorGUILayout.Popup(styles.sssProfileTransmissionMode, m_TransmissionMode.intValue, styles.sssTransmissionModeOptions);
EditorGUILayout.PropertyField(m_VolumeAlbedo, styles.sssProfileVolumeAlbedo);
EditorGUILayout.PropertyField(m_ThicknessRemap, styles.sssProfileMinMaxThickness);
Vector2 thicknessRemap = m_ThicknessRemap.vector2Value;
EditorGUILayout.MinMaxSlider(styles.sssProfileThicknessRemap, ref thicknessRemap.x, ref thicknessRemap.y, 0.0f, 50.0f);

float d = m_ScatteringDistance.floatValue;
Vector4 A = m_SurfaceAlbedo.colorValue;
Vector4 V = m_VolumeAlbedo.colorValue;
bool transmissionEnabled = m_TransmissionMode.intValue != (int)SubsurfaceScatteringProfile.TransmissionMode.None;
// Draw the profile.
m_ProfileMaterial.SetFloat("_ScatteringDistance", d);

EditorGUILayout.LabelField(styles.sssTransmittancePreview2, EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
bool transmissionEnabled = m_TransmissionMode.intValue != (int)SubsurfaceScatteringProfile.TransmissionMode.None;
m_TransmittanceMaterial.SetVector("_SurfaceAlbedo", transmissionEnabled ? A : Vector4.zero);
m_TransmittanceMaterial.SetVector("_VolumeAlbedo", transmissionEnabled ? V : Vector4.zero);
m_TransmittanceMaterial.SetVector("_ShapeParameter", S);
m_TransmittanceMaterial.SetVector("_ThicknessRemap", R);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImage, m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.hlsl


#define SSS_NEUTRAL_PROFILE_ID (7)
#define SSS_N_SAMPLES_NEAR_FIELD (55)
#define SSS_N_SAMPLES_FAR_FIELD (21)
#define SSS_LOD_THRESHOLD (4)
#define SSS_TRSM_MODE_NONE (0)
#define SSS_TRSM_MODE_THIN (1)

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawSssProfile.shader


//-------------------------------------------------------------------------------------
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../../ShaderLibrary/Color.hlsl"
#include "../../ShaderVariables.hlsl"
//-------------------------------------------------------------------------------------

float3 S = _ShapeParameter.rgb;
float3 M = S * (exp(-r * S) + exp(-r * S * (1.0 / 3.0))) / (8 * PI * r);
// Apply gamma for visualization only. It is not present in the actual formula!
return float4(pow(M * _SurfaceAlbedo.rgb, 1.0 / 3.0), 1);
// Apply gamma for visualization only. Do not apply gamma to the color.
return float4(pow(M, 1.0 / 3.0) * _SurfaceAlbedo.rgb, 1);
}
ENDHLSL
}

13
Assets/ScriptableRenderPipeline/ShaderLibrary/CommonMaterial.hlsl


// ----------------------------------------------------------------------------
// Computes the fraction of light passing through the object.
// N.b.: it is not just zero scattering (light traveling in a straight path)!
// We derive the transmittance function from the SSS profile, by normalizing it s.t. R(0) = 1.
// Evaluate Int{0, inf}{2 * Pi * r * R(sqrt(r^2 + d^2))}, where R is the diffusion profile.
float3 ComputeTransmittance(float3 S, float3 surfaceAlbedo, float thickness, float radiusScale)
float3 ComputeTransmittance(float3 S, float3 volumeAlbedo, float thickness, float radiusScale)
{
// Thickness and SSS radius are decoupled for artists.
// In theory, we should modify the thickness by the inverse of the radius scale of the profile.

return 0.5 * (expOneThird + expOneThird * expOneThird * expOneThird) * surfaceAlbedo;
return 0.25 * (expOneThird + 3 * expOneThird * expOneThird * expOneThird) * volumeAlbedo;
}
// Ref: Steve McAuley - Energy-Conserving Wrapped Diffuse
float ComputeWrappedDiffuseLighting(float NdotL, float w)
{
return saturate((-NdotL + w) / ((1 + w) * (1 + w)));
}
// MACRO from Legacy Untiy

14
Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader


// Include
//-------------------------------------------------------------------------------------
#include "../../ShaderLibrary/Common.hlsl"
#include "../../ShaderLibrary/Color.hlsl"
#include "../../ShaderLibrary/CommonMaterial.hlsl"
#include "../ShaderVariables.hlsl"
#include "../../../ShaderLibrary/CommonMaterial.hlsl"
#include "../../../ShaderLibrary/Common.hlsl"
#include "../../ShaderVariables.hlsl"
float4 _SurfaceAlbedo, _ShapeParameter, _ThicknessRemap;
float4 _VolumeAlbedo, _ShapeParameter, _ThicknessRemap;
float _ScatteringDistance; // See 'SubsurfaceScatteringProfile'
//-------------------------------------------------------------------------------------

float4 Frag(Varyings input) : SV_Target
{
float d = (_ThicknessRemap.x + input.texcoord.x * (_ThicknessRemap.y - _ThicknessRemap.x));
float3 T = ComputeTransmittance(_ShapeParameter.rgb, _SurfaceAlbedo.rgb, d, 1);
float3 T = ComputeTransmittance(_ShapeParameter.rgb, float3(1, 1, 1), d, 1);
return float4(T, 1);
// Apply gamma for visualization only. Do not apply gamma to the color.
return float4(pow(T, 1.0 / 3) * _VolumeAlbedo.rgb, 1);
}
ENDHLSL
}

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawGaussianProfile.shader.meta


fileFormatVersion: 2
guid: 2e8a76823cb2af944b4b45169f2649f9
timeCreated: 1487181006
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

84
Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawGaussianProfile.shader


Shader "Hidden/HDRenderPipeline/DrawGaussianProfile"
{
Properties
{
[HideInInspector] _StdDev1("", Color) = (0, 0, 0)
[HideInInspector] _StdDev2("", Color) = (0, 0, 0)
[HideInInspector] _LerpWeight("", Float) = 0
}
SubShader
{
Pass
{
Cull Off
ZTest Off
ZWrite Off
Blend Off
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#pragma vertex Vert
#pragma fragment Frag
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------
#include "../../ShaderLibrary/Common.hlsl"
#include "../../ShaderLibrary/Color.hlsl"
#include "../ShaderVariables.hlsl"
//-------------------------------------------------------------------------------------
// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _StdDev1, _StdDev2; float _LerpWeight; // See 'SubsurfaceScatteringParameters'
//-------------------------------------------------------------------------------------
// Implementation
//-------------------------------------------------------------------------------------
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
float4 Frag(Varyings input) : SV_Target
{
float dist = length(input.texcoord - 0.5);
float3 var1 = _StdDev1.rgb * _StdDev1.rgb;
float3 var2 = _StdDev2.rgb * _StdDev2.rgb;
// Evaluate the linear combination of two 2D Gaussians instead of
// product of a linear combination of two normalized 1D Gaussians
// since we do not want to bother artists with the lack of radial symmetry.
float3 magnitude = lerp(exp(-dist * dist / (2 * var1)) / (TWO_PI * var1),
exp(-dist * dist / (2 * var2)) / (TWO_PI * var2), _LerpWeight);
return float4(magnitude, 1);
}
ENDHLSL
}
}
Fallback Off
}

/Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawTransmittanceGraph.shader.meta → /Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader.meta

/Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawTransmittanceGraph.shader → /Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader

正在加载...
取消
保存