浏览代码

Add volume albedo to SSS

/RenderPassXR_Sandbox
Evgenii Golubev 7 年前
当前提交
76455f03
共有 3 个文件被更改,包括 23 次插入17 次删除
  1. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  2. 28
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  3. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawTransmittanceGraph.shader

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


uint _TransmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
float _ThicknessRemaps[SSS_N_PROFILES][2]; // Remap: 0 = start, 1 = end - start
float4 _ShapeParameters[SSS_N_PROFILES]; // RGB = S = 1 / D; A = filter radius
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

// 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.
// Ref: Approximate Reflectance Profiles for Efficient Subsurface Scattering by Pixar (BSSRDF only).
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.5 * (expOneThird + expOneThird * expOneThird * expOneThird) * volumeAlbedo;
}
void FillMaterialIdStandardData(float3 baseColor, float specular, float metallic, float roughness, float3 normalWS, float3 tangentWS, float anisotropy, inout BSDFData bsdfData)

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

28
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 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 sssProfileVolumeAlbedo = new GUIContent("Volume Albedo", "Color which tints transmitted light. Alpha is ignored.");
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);

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/DrawTransmittanceGraph.shader


// Inputs & outputs
//-------------------------------------------------------------------------------------
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, _VolumeAlbedo.rgb, d, 1);
return float4(T, 1);
}

正在加载...
取消
保存