浏览代码

HDRenderPipeline: Add thin material option + Fix issue with transmission and shadow

- Add a thin material option on SSS profile
- Shadow was not working anymore with transmission due to merge conflict
with shadow branch
- Done a pass of format on file in Lit directory
- Share constant for number of profile between c#a and hlsl
/Branch_Batching2
sebastienlagarde 7 年前
当前提交
8aa908b7
共有 8 个文件被更改,包括 109 次插入63 次删除
  1. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  2. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  4. 7
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  5. 40
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  6. 93
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  7. 13
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.hlsl
  8. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.hlsl.meta

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


public readonly GUIContent shadowsAtlasHeight = new GUIContent("Atlas height");
// Subsurface Scattering Settings
public readonly GUIContent[] sssProfiles = new GUIContent[SubsurfaceScatteringSettings.maxNumProfiles] { new GUIContent("Profile #0"), new GUIContent("Profile #1"), new GUIContent("Profile #2"), new GUIContent("Profile #3"), new GUIContent("Profile #4"), new GUIContent("Profile #5"), new GUIContent("Profile #6"), new GUIContent("Profile #7") };
public readonly GUIContent[] sssProfiles = new GUIContent[SSSConstants.SSS_PROFILES_MAX] { new GUIContent("Profile #0"), new GUIContent("Profile #1"), new GUIContent("Profile #2"), new GUIContent("Profile #3"), new GUIContent("Profile #4"), new GUIContent("Profile #5"), new GUIContent("Profile #6"), new GUIContent("Profile #7") };
public readonly GUIContent sssNumProfiles = new GUIContent("Number of profiles");
// Tile pass Settings

public readonly GUIContent[] debugViewLightingStrings = { new GUIContent("None"), new GUIContent("Diffuse Lighting"), new GUIContent("Specular Lighting"), new GUIContent("Visualize Cascades") };
public readonly int[] debugViewLightingValues = { (int)DebugLightingMode.None, (int)DebugLightingMode.DiffuseLighting, (int)DebugLightingMode.SpecularLighting, (int)DebugLightingMode.VisualizeCascade };
public readonly GUIContent shadowDebugVisualizationMode = new GUIContent("Shadow Maps Debug Mode");
public readonly GUIContent shadowDebugVisualizeShadowIndex = new GUIContent("Visualize Shadow Index");
public readonly GUIContent shadowDebugVisualizeShadowIndex = new GUIContent("Visualize Shadow Index");
public readonly GUIContent lightingDebugOverrideSmoothness = new GUIContent("Override Smoothness");
public readonly GUIContent lightingDebugOverrideSmoothnessValue = new GUIContent("Smoothness Value");
public readonly GUIContent lightingDebugAlbedo = new GUIContent("Lighting Debug Albedo");

EditorGUILayout.PropertyField(m_NumProfiles, styles.sssNumProfiles);
for (int i = 0, n = Math.Min(m_Profiles.arraySize, SubsurfaceScatteringSettings.maxNumProfiles); i < n; i++)
for (int i = 0, n = Math.Min(m_Profiles.arraySize, SSSConstants.SSS_PROFILES_MAX); i < n; i++)
{
SerializedProperty profile = m_Profiles.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(profile, styles.sssProfiles[i]);

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


Shader.SetGlobalInt("_EnableSSS", debugDisplaySettings.renderingDebugSettings.enableSSS ? 1 : 0);
Shader.SetGlobalInt("_TransmissionFlags", sssParameters.transmissionFlags);
Shader.SetGlobalInt("_TexturingModeFlags", sssParameters.texturingModeFlags);
Shader.SetGlobalInt("_ThinMaterialFlags", sssParameters.thinMaterialFlags);
cmd.SetGlobalFloatArray("_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray("_TintColors", sssParameters.tintColors);
cmd.SetGlobalVectorArray("_HalfRcpVariancesAndLerpWeights", sssParameters.halfRcpVariancesAndLerpWeights);

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


public float thickness;
public int subsurfaceProfile;
public bool enableTransmission; // Read from the SSS profile
public Vector3 transmittance;
public bool enableThinMaterial; // Read from the SSS profile
public Vector3 transmittance; // Compute from SSS profile
// SpecColor
// fold into fresnel0

7
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


#define DEBUGVIEW_LIT_BSDFDATA_THICKNESS (1043)
#define DEBUGVIEW_LIT_BSDFDATA_SUBSURFACE_PROFILE (1044)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION (1045)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1046)
#define DEBUGVIEW_LIT_BSDFDATA_ENABLE_THIN_MATERIAL (1046)
#define DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE (1047)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.GBufferMaterial: static fields

float thickness;
int subsurfaceProfile;
bool enableTransmission;
bool enableThinMaterial;
float3 transmittance;
};

break;
case DEBUGVIEW_LIT_BSDFDATA_ENABLE_TRANSMISSION:
result = (bsdfdata.enableTransmission) ? float3(1.0, 1.0, 1.0) : float3(0.0, 0.0, 0.0);
break;
case DEBUGVIEW_LIT_BSDFDATA_ENABLE_THIN_MATERIAL:
result = (bsdfdata.enableThinMaterial) ? float3(1.0, 1.0, 1.0) : float3(0.0, 0.0, 0.0);
break;
case DEBUGVIEW_LIT_BSDFDATA_TRANSMITTANCE:
result = bsdfdata.transmittance;

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


// SurfaceData is define in Lit.cs which generate Lit.cs.hlsl
#include "Lit.cs.hlsl"
#include "SubsurfaceScatteringProfile.cs.hlsl"
// In case we pack data uint16 buffer we need to change the output render target format to uint16
// TODO: Is there a way to automate these output type based on the format declare in lit.cs ?

#define MIN_N_DOT_V 0.0001 // The minimum value of 'NdotV'
// SSS parameters
#define SSS_N_PROFILES 8
#define SSS_LOW_THICKNESS 0.005 // 0.5 cm
uint _EnableSSS; // Globally toggles subsurface scattering on/off
uint _TransmissionFlags; // 1 bit/profile; 0 = inf. thick, 1 = supports transmission
uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
float4 _TintColors[SSS_N_PROFILES]; // For transmission; alpha is unused
float _ThicknessRemaps[SSS_N_PROFILES][2]; // Remap: 0 = start, 1 = end - start
float4 _HalfRcpVariancesAndLerpWeights[SSS_N_PROFILES][2]; // 2x Gaussians per color channel, A is the the associated interpolation weight
uint _EnableSSS; // Globally toggles subsurface scattering on/off
uint _TransmissionFlags; // 1 bit/profile; 0 = inf. thick, 1 = supports transmission
uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
uint _ThinMaterialFlags; // 1 bit/profile; 1 = is thin material (allow specific optimization)
float4 _TintColors[SSS_PROFILES_MAX]; // For transmission; alpha is unused
float _ThicknessRemaps[SSS_PROFILES_MAX][2]; // Remap: 0 = start, 1 = end - start
float4 _HalfRcpVariancesAndLerpWeights[SSS_PROFILES_MAX][2]; // 2x Gaussians per color channel, A is the the associated interpolation weight
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material

_ThicknessRemaps[subsurfaceProfile][1] * thickness);
bsdfData.enableTransmission = IsBitSet(_TransmissionFlags, subsurfaceProfile);
bsdfData.enableThinMaterial = IsBitSet(_ThinMaterialFlags, subsurfaceProfile);
if (bsdfData.enableTransmission)
{
bsdfData.transmittance = ComputeTransmittance( _HalfRcpVariancesAndLerpWeights[subsurfaceProfile][0].xyz,

}
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
{
outGBuffer2 = float4(surfaceData.subsurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subsurfaceProfile * rcp(SSS_N_PROFILES - 1));
outGBuffer2 = float4(surfaceData.subsurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subsurfaceProfile * rcp(SSS_PROFILES_MAX - 1));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{

}
else if (supportsSSS && bsdfData.materialId == MATERIALID_LIT_SSS)
{
int subsurfaceProfile = (SSS_N_PROFILES - 0.9) * inGBuffer2.a;
int subsurfaceProfile = (SSS_PROFILES_MAX - 0.9) * inGBuffer2.a;
float subsurfaceRadius = inGBuffer2.r;
float thickness = inGBuffer2.g;
FillMaterialIdSSSData(baseColor, subsurfaceProfile, subsurfaceRadius, thickness, bsdfData);

[branch] if (lightData.shadowIndex >= 0)
{
float shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
illuminance *= shadow;
}

const float w = 0.15;
float illuminance = saturate((dot(-bsdfData.normalWS, L) + w) / ((1.0 + w) * (1.0 + w)));
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = (bsdfData.thickness <= SSS_LOW_THICKNESS) ? shadow : 1;
// For thin material we can reuse the shadowing status for the back of the object.
shadow = bsdfData.enableThinMaterial ? shadow : 1;
illuminance *= shadow * cookie.a;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.

[branch] if (lightData.shadowIndex >= 0)
{
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
float shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = lerp(1.0, shadow, lightData.shadowDimmer);
illuminance *= shadow;

float illuminance = saturate((dot(-bsdfData.normalWS, L) + w) / ((1.0 + w) * (1.0 + w)));
illuminance *= attenuation;
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = (bsdfData.thickness <= SSS_LOW_THICKNESS) ? shadow : 1;
// For thin material we can reuse the shadowing status for the back of the object.
shadow = bsdfData.enableThinMaterial ? shadow : 1;
illuminance *= shadow * cookie.a;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.

[branch] if (lightData.shadowIndex >= 0)
{
float shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
illuminance *= shadow;
}

float illuminance = saturate((dot(-bsdfData.normalWS, L) + w) / ((1.0 + w) * (1.0 + w)));
illuminance *= clipFactor;
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = (bsdfData.thickness <= SSS_LOW_THICKNESS) ? shadow : 1;
// For thin material we can reuse the shadowing status for the back of the object.
shadow = bsdfData.enableThinMaterial ? shadow : 1;
illuminance *= shadow * cookie.a;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.

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


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL]
public class SSSConstants
{
public const int SSS_PROFILES_MAX = 8;
}
[Serializable]
public class SubsurfaceScatteringProfile : ScriptableObject
{

[ColorUsage(false, true, 0.05f, 2.0f, 1.0f, 1.0f)]
public Color scatterDistance1;
public Color scatterDistance1;
public Color scatterDistance2;
public float lerpWeight;
public TexturingMode texturingMode;
public bool enableTransmission;
public Color tintColor;
public Vector2 thicknessRemap;
public Color scatterDistance2;
public float lerpWeight;
public TexturingMode texturingMode;
public bool enableTransmission;
public bool enableThinMaterial;
public Color tintColor;
public Vector2 thicknessRemap;
public int settingsIndex;
public int settingsIndex;
Vector4[] m_FilterKernel;
Vector4[] m_FilterKernel;
Vector3[] m_HalfRcpVariances;
Vector3[] m_HalfRcpVariances;
Vector4 m_HalfRcpWeightedVariances;
Vector4 m_HalfRcpWeightedVariances;
scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0.0f);
scatterDistance2 = new Color(0.6f, 0.6f, 0.6f, 0.0f);
lerpWeight = 0.5f;
texturingMode = TexturingMode.PreAndPostScatter;
enableTransmission = false;
tintColor = Color.white;
thicknessRemap = new Vector2(0, 1);
settingsIndex = SubsurfaceScatteringSettings.neutralProfileID; // Updated by SubsurfaceScatteringSettings.OnValidate() once assigned
scatterDistance1 = new Color(0.3f, 0.3f, 0.3f, 0.0f);
scatterDistance2 = new Color(0.6f, 0.6f, 0.6f, 0.0f);
lerpWeight = 0.5f;
texturingMode = TexturingMode.PreAndPostScatter;
enableTransmission = false;
enableThinMaterial = false;
tintColor = Color.white;
thicknessRemap = new Vector2(0, 1);
settingsIndex = SubsurfaceScatteringSettings.neutralProfileID; // Updated by SubsurfaceScatteringSettings.OnValidate() once assigned
UpdateKernelAndVarianceData();
}

[Serializable]
public class SubsurfaceScatteringSettings : ISerializationCallbackReceiver
{
public const int maxNumProfiles = 8;
public const int neutralProfileID = maxNumProfiles - 1;
public const int neutralProfileID = SSSConstants.SSS_PROFILES_MAX - 1;
public int numProfiles;
public SubsurfaceScatteringProfile[] profiles;

[NonSerialized] public int thinMaterialFlags; // 1 bit/profile; 1 = is thin material (allow specific optimization)
[NonSerialized] public Vector4[] tintColors; // For transmission; alpha is unused
[NonSerialized] public float[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[NonSerialized] public Vector4[] halfRcpVariancesAndLerpWeights;

profiles[0] = null;
texturingModeFlags = 0;
transmissionFlags = 0;
thinMaterialFlags = 0;
tintColors = null;
thicknessRemaps = null;
halfRcpVariancesAndLerpWeights = null;

public void OnValidate()
{
// Reserve one slot for the neutral profile.
numProfiles = Math.Min(profiles.Length, maxNumProfiles - 1);
numProfiles = Math.Min(profiles.Length, SSSConstants.SSS_PROFILES_MAX - 1);
if (profiles.Length != numProfiles)
{

public void UpdateCache()
{
texturingModeFlags = 0;
transmissionFlags = 0;
texturingModeFlags = 0;
transmissionFlags = 0;
thinMaterialFlags = 0;
if (tintColors == null || tintColors.Length != maxNumProfiles)
if (tintColors == null || tintColors.Length != SSSConstants.SSS_PROFILES_MAX)
tintColors = new Vector4[maxNumProfiles];
tintColors = new Vector4[SSSConstants.SSS_PROFILES_MAX];
if (thicknessRemaps == null || thicknessRemaps.Length != (maxNumProfiles * 2))
if (thicknessRemaps == null || thicknessRemaps.Length != (SSSConstants.SSS_PROFILES_MAX * 2))
thicknessRemaps = new float[maxNumProfiles * 2];
thicknessRemaps = new float[SSSConstants.SSS_PROFILES_MAX * 2];
if (halfRcpVariancesAndLerpWeights == null || halfRcpVariancesAndLerpWeights.Length != (maxNumProfiles * 2))
if (halfRcpVariancesAndLerpWeights == null || halfRcpVariancesAndLerpWeights.Length != (SSSConstants.SSS_PROFILES_MAX * 2))
halfRcpVariancesAndLerpWeights = new Vector4[maxNumProfiles * 2];
halfRcpVariancesAndLerpWeights = new Vector4[SSSConstants.SSS_PROFILES_MAX * 2];
if (halfRcpWeightedVariances == null || halfRcpWeightedVariances.Length != maxNumProfiles)
if (halfRcpWeightedVariances == null || halfRcpWeightedVariances.Length != SSSConstants.SSS_PROFILES_MAX)
halfRcpWeightedVariances = new Vector4[maxNumProfiles];
halfRcpWeightedVariances = new Vector4[SSSConstants.SSS_PROFILES_MAX];
if (filterKernels == null || filterKernels.Length != (maxNumProfiles * SubsurfaceScatteringProfile.numSamples))
if (filterKernels == null || filterKernels.Length != (SSSConstants.SSS_PROFILES_MAX * SubsurfaceScatteringProfile.numSamples))
filterKernels = new Vector4[maxNumProfiles * SubsurfaceScatteringProfile.numSamples];
filterKernels = new Vector4[SSSConstants.SSS_PROFILES_MAX * SubsurfaceScatteringProfile.numSamples];
}
for (int i = 0; i < numProfiles; i++)

texturingModeFlags |= ((int)profiles[i].texturingMode) << i;
transmissionFlags |= (profiles[i].enableTransmission ? 1 : 0) << i;
thinMaterialFlags |= (profiles[i].enableThinMaterial ? 1 : 0) << i;
tintColors[i] = profiles[i].tintColor;
thicknessRemaps[2 * i] = profiles[i].thicknessRemap.x;

};
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 sssProfileTintColor = new GUIContent("Transmission Tint Color", "Tints transmitted light.");
public readonly GUIContent sssProfileThinMaterial = new GUIContent("Enable Thin Material", "Define is the material is thin (paper, leaf) or not. Allow to get cheap transmission and shadow.");
public readonly GUIContent sssProfileMinMaxThickness = new GUIContent("Min-Max Thickness", "Shows the values of the thickness remap below (in centimeters).");
public readonly GUIContent sssProfileThicknessRemap = new GUIContent("Thickness Remap", "Remaps the thickness parameter from [0, 1] to the desired range (in centimeters).");

private RenderTexture m_ProfileImage, m_TransmittanceImage;
private Material m_ProfileMaterial, m_TransmittanceMaterial;
private SerializedProperty m_ScatterDistance1, m_ScatterDistance2, m_LerpWeight, m_TintColor,
private SerializedProperty m_ScatterDistance1, m_ScatterDistance2, m_LerpWeight, m_TintColor, m_ThinMaterial,
m_TexturingMode, m_Transmission, m_ThicknessRemap;
void OnEnable()

m_LerpWeight = serializedObject.FindProperty("lerpWeight");
m_TexturingMode = serializedObject.FindProperty("texturingMode");
m_Transmission = serializedObject.FindProperty("enableTransmission");
m_ThinMaterial = serializedObject.FindProperty("enableThinMaterial");
m_TintColor = serializedObject.FindProperty("tintColor");
m_ThicknessRemap = serializedObject.FindProperty("thicknessRemap");

m_TexturingMode.intValue = EditorGUILayout.Popup(styles.sssTexturingMode, m_TexturingMode.intValue, styles.sssTexturingModeOptions);
EditorGUILayout.PropertyField(m_Transmission, styles.sssProfileTransmission);
EditorGUILayout.PropertyField(m_TintColor, styles.sssProfileTintColor);
EditorGUILayout.PropertyField(m_ThinMaterial, styles.sssProfileThinMaterial);
EditorGUILayout.PropertyField(m_ThicknessRemap, styles.sssProfileMinMaxThickness);
Vector2 thicknessRemap = m_ThicknessRemap.vector2Value;

EditorGUILayout.Space();
// Draw the transmittance graph.
m_TransmittanceMaterial.SetColor("_StdDev1", stdDev1);
m_TransmittanceMaterial.SetColor("_StdDev2", stdDev2);
m_TransmittanceMaterial.SetFloat("_LerpWeight", m_LerpWeight.floatValue);
m_TransmittanceMaterial.SetColor("_StdDev1", stdDev1);
m_TransmittanceMaterial.SetColor("_StdDev2", stdDev2);
m_TransmittanceMaterial.SetFloat("_LerpWeight", m_LerpWeight.floatValue);
m_TransmittanceMaterial.SetVector("_TintColor", m_TintColor.colorValue);
m_TransmittanceMaterial.SetVector("_TintColor", m_TintColor.colorValue);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImage, m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);
serializedObject.ApplyModifiedProperties();

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


//
// This file was automatically generated from Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs. Please don't edit by hand.
//
#ifndef SUBSURFACESCATTERINGPROFILE_CS_HLSL
#define SUBSURFACESCATTERINGPROFILE_CS_HLSL
//
// UnityEngine.Experimental.Rendering.HDPipeline.SSSConstants: static fields
//
#define SSS_PROFILES_MAX (8)
#endif

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs.hlsl.meta


fileFormatVersion: 2
guid: 0348d78eb59f5e143ab4aa357c26f2c4
timeCreated: 1494501874
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存