浏览代码

Use standard deviation instead of variance as it is more intuitive

/main
Evgenii Golubev 8 年前
当前提交
27059d4f
共有 4 个文件被更改,包括 87 次插入86 次删除
  1. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs
  2. 50
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/CommonSettings.cs
  3. 32
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/Editor/CommonSettingsEditor.cs
  4. 83
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/SubsurfaceScatteringParameters.cs

8
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs


m_ShadowSettings.directionalLightCascades = new Vector3(m_CommonSettings.shadowCascadeSplit0, m_CommonSettings.shadowCascadeSplit1, m_CommonSettings.shadowCascadeSplit2);
m_ShadowSettings.maxShadowDistance = m_CommonSettings.shadowMaxDistance;
sssParameters.profiles[0].filterVariance1 = m_CommonSettings.sssProfileFilterVariance1;
sssParameters.profiles[0].filterVariance2 = m_CommonSettings.sssProfileFilterVariance2;
sssParameters.profiles[0].filterLerpWeight = m_CommonSettings.sssProfileFilterLerpWeight;
sssParameters.bilateralScale = m_CommonSettings.sssBilateralScale;
sssParameters.profiles[0].stdDev1 = m_CommonSettings.sssProfileStdDev1;
sssParameters.profiles[0].stdDev2 = m_CommonSettings.sssProfileStdDev2;
sssParameters.profiles[0].lerpWeight = m_CommonSettings.sssProfileLerpWeight;
sssParameters.bilateralScale = m_CommonSettings.sssBilateralScale;
}
}

50
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/CommonSettings.cs


// Subsurface scattering
[SerializeField] [ColorUsage(false, true, 0.05f, 4, 1.0f, 1.0f)]
Color m_SssProfileFilterVariance1 = SubsurfaceScatteringProfile.Default.filterVariance1;
[SerializeField] [ColorUsage(false, true, 0.05f, 4, 1.0f, 1.0f)]
Color m_SssProfileFilterVariance2 = SubsurfaceScatteringProfile.Default.filterVariance2;
[SerializeField] float m_SssProfileFilterLerpWeight = SubsurfaceScatteringProfile.Default.filterLerpWeight;
[SerializeField] float m_SssBilateralScale = SubsurfaceScatteringParameters.Default.bilateralScale;
[ColorUsage(false, true, 0.05f, 2.0f, 1.0f, 1.0f)]
[SerializeField] Color m_SssProfileStdDev1 = SubsurfaceScatteringProfile.Default.stdDev1;
[ColorUsage(false, true, 0.05f, 2.0f, 1.0f, 1.0f)]
[SerializeField] Color m_SssProfileStdDev2 = SubsurfaceScatteringProfile.Default.stdDev2;
[SerializeField] float m_SssProfileLerpWeight = SubsurfaceScatteringProfile.Default.lerpWeight;
[SerializeField] float m_SssBilateralScale = SubsurfaceScatteringParameters.Default.bilateralScale;
public Color sssProfileFilterVariance1 { set { m_SssProfileFilterVariance1 = value; OnValidate(); } get { return m_SssProfileFilterVariance1; } }
public Color sssProfileFilterVariance2 { set { m_SssProfileFilterVariance2 = value; OnValidate(); } get { return m_SssProfileFilterVariance2; } }
public float sssProfileFilterLerpWeight { set { m_SssProfileFilterLerpWeight = value; OnValidate(); } get { return m_SssProfileFilterLerpWeight; } }
public float sssBilateralScale { set { m_SssBilateralScale = value; OnValidate(); } get { return m_SssBilateralScale; } }
public Color sssProfileStdDev1 { set { m_SssProfileStdDev1 = value; OnValidate(); } get { return m_SssProfileStdDev1; } }
public Color sssProfileStdDev2 { set { m_SssProfileStdDev2 = value; OnValidate(); } get { return m_SssProfileStdDev2; } }
public float sssProfileLerpWeight { set { m_SssProfileLerpWeight = value; OnValidate(); } get { return m_SssProfileLerpWeight; } }
public float sssBilateralScale { set { m_SssBilateralScale = value; OnValidate(); } get { return m_SssBilateralScale; } }
void OnEnable()
{

void OnValidate()
{
m_ShadowMaxDistance = Mathf.Max(0.0f, m_ShadowMaxDistance);
m_ShadowCascadeCount = Math.Min(4, Math.Max(1, m_ShadowCascadeCount));
m_ShadowCascadeSplit0 = Mathf.Clamp01(m_ShadowCascadeSplit0);
m_ShadowCascadeSplit1 = Mathf.Clamp01(m_ShadowCascadeSplit1);
m_ShadowCascadeSplit2 = Mathf.Clamp01(m_ShadowCascadeSplit2);
m_ShadowMaxDistance = Mathf.Max(0.0f, m_ShadowMaxDistance);
m_ShadowCascadeCount = Math.Min(4, Math.Max(1, m_ShadowCascadeCount));
m_ShadowCascadeSplit0 = Mathf.Clamp01(m_ShadowCascadeSplit0);
m_ShadowCascadeSplit1 = Mathf.Clamp01(m_ShadowCascadeSplit1);
m_ShadowCascadeSplit2 = Mathf.Clamp01(m_ShadowCascadeSplit2);
m_SssProfileFilterVariance1.r = Mathf.Max(0.05f, m_SssProfileFilterVariance1.r);
m_SssProfileFilterVariance1.g = Mathf.Max(0.05f, m_SssProfileFilterVariance1.g);
m_SssProfileFilterVariance1.b = Mathf.Max(0.05f, m_SssProfileFilterVariance1.b);
m_SssProfileFilterVariance1.a = 0.0f;
m_SssProfileFilterVariance2.r = Mathf.Max(0.05f, m_SssProfileFilterVariance2.r);
m_SssProfileFilterVariance2.g = Mathf.Max(0.05f, m_SssProfileFilterVariance2.g);
m_SssProfileFilterVariance2.b = Mathf.Max(0.05f, m_SssProfileFilterVariance2.b);
m_SssProfileFilterVariance2.a = 0.0f;
m_SssProfileFilterLerpWeight = Mathf.Clamp01(m_SssProfileFilterLerpWeight);
m_SssBilateralScale = Mathf.Clamp01(m_SssBilateralScale);
m_SssProfileStdDev1.r = Mathf.Max(0.05f, m_SssProfileStdDev1.r);
m_SssProfileStdDev1.g = Mathf.Max(0.05f, m_SssProfileStdDev1.g);
m_SssProfileStdDev1.b = Mathf.Max(0.05f, m_SssProfileStdDev1.b);
m_SssProfileStdDev1.a = 0.0f;
m_SssProfileStdDev2.r = Mathf.Max(0.05f, m_SssProfileStdDev2.r);
m_SssProfileStdDev2.g = Mathf.Max(0.05f, m_SssProfileStdDev2.g);
m_SssProfileStdDev2.b = Mathf.Max(0.05f, m_SssProfileStdDev2.b);
m_SssProfileStdDev2.a = 0.0f;
m_SssProfileLerpWeight = Mathf.Clamp01(m_SssProfileLerpWeight);
m_SssBilateralScale = Mathf.Clamp01(m_SssBilateralScale);
OnSkyRendererChanged();
}

32
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/Editor/CommonSettingsEditor.cs


public readonly GUIContent shadowsCascades = new GUIContent("Cascade values");
public readonly GUIContent[] shadowSplits = new GUIContent[] { new GUIContent("Split 0"), new GUIContent("Split 1"), new GUIContent("Split 2") };
public readonly GUIContent sssCategory = new GUIContent("Subsurface scattering");
public readonly GUIContent sssProfileFilterVariance1 = new GUIContent("SSS profile filter variance #1", "Determines the shape of the 1st Gaussian filter. Increases the strength of the blur of the corresponding color channel.");
public readonly GUIContent sssProfileFilterVariance2 = new GUIContent("SSS profile filter variance #2", "Determines the shape of the 2nd Gaussian filter. Increases the strength of the blur of the corresponding color channel.");
public readonly GUIContent sssProfileFilterLerpWeight = new GUIContent("SSS profile filter interpolation", "Controls linear interpolation between the two Gaussian filters.");
public readonly GUIContent sssBilateralScale = new GUIContent("SSS bilateral filtering scale", "Larger values make the filter more tolerant to depth differences.");
public readonly GUIContent sssCategory = new GUIContent("Subsurface scattering");
public readonly GUIContent sssProfileStdDev1 = new GUIContent("SSS profile standard deviation #1", "Determines the shape of the 1st Gaussian filter. Increases the strength and the radius of the blur of the corresponding color channel.");
public readonly GUIContent sssProfileStdDev2 = new GUIContent("SSS profile standard deviation #2", "Determines the shape of the 2nd Gaussian filter. Increases the strength and the radius of the blur of the corresponding color channel.");
public readonly GUIContent sssProfileLerpWeight = new GUIContent("SSS profile filter interpolation", "Controls linear interpolation between the two Gaussian filters.");
public readonly GUIContent sssBilateralScale = new GUIContent("SSS bilateral filtering scale", "Larger values make the filter more tolerant to depth differences.");
}
private static Styles s_Styles = null;

private SerializedProperty[] m_ShadowCascadeSplits = new SerializedProperty[3];
// Subsurface scattering
private SerializedProperty m_SssProfileFilterVariance1;
private SerializedProperty m_SssProfileFilterVariance2;
private SerializedProperty m_SssProfileFilterLerpWeight;
private SerializedProperty m_SssProfileStdDev1;
private SerializedProperty m_SssProfileStdDev2;
private SerializedProperty m_SssProfileLerpWeight;
private SerializedProperty m_SssBilateralScale;
void OnEnable()

m_SkyRendererTypeValues.Add(m_SkyRendererTypeValues.Count);
m_SkyRendererTypes.Add(null);
m_SssProfileFilterVariance1 = serializedObject.FindProperty("m_SssProfileFilterVariance1");
m_SssProfileFilterVariance2 = serializedObject.FindProperty("m_SssProfileFilterVariance2");
m_SssProfileFilterLerpWeight = serializedObject.FindProperty("m_SssProfileFilterLerpWeight");
m_SssBilateralScale = serializedObject.FindProperty("m_SssBilateralScale");
m_SssProfileStdDev1 = serializedObject.FindProperty("m_SssProfileStdDev1");
m_SssProfileStdDev2 = serializedObject.FindProperty("m_SssProfileStdDev2");
m_SssProfileLerpWeight = serializedObject.FindProperty("m_SssProfileLerpWeight");
m_SssBilateralScale = serializedObject.FindProperty("m_SssBilateralScale");
}
void OnSkyInspectorGUI()

{
EditorGUILayout.LabelField(styles.sssCategory);
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(m_SssProfileFilterVariance1, styles.sssProfileFilterVariance1);
EditorGUILayout.PropertyField(m_SssProfileFilterVariance2, styles.sssProfileFilterVariance2);
EditorGUILayout.PropertyField(m_SssProfileFilterLerpWeight, styles.sssProfileFilterLerpWeight);
EditorGUILayout.PropertyField(m_SssBilateralScale, styles.sssBilateralScale);
EditorGUILayout.PropertyField(m_SssProfileStdDev1, styles.sssProfileStdDev1);
EditorGUILayout.PropertyField(m_SssProfileStdDev2, styles.sssProfileStdDev2);
EditorGUILayout.PropertyField(m_SssProfileLerpWeight, styles.sssProfileLerpWeight);
EditorGUILayout.PropertyField(m_SssBilateralScale, styles.sssBilateralScale);
EditorGUI.indentLevel--;
}

83
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/SubsurfaceScatteringParameters.cs


{
public const int numSamples = 7;
Color m_filterVariance1;
Color m_filterVariance2;
float m_filterLerpWeight;
Vector4[] m_filterKernel;
bool m_kernelNeedsUpdate;
Color m_StdDev1;
Color m_StdDev2;
float m_LerpWeight;
Vector4[] m_FilterKernel;
bool m_KernelNeedsUpdate;
public Color filterVariance1
public Color stdDev1
get { return m_filterVariance1; }
set { if (m_filterVariance1 != value) { m_filterVariance1 = value; m_kernelNeedsUpdate = true; } }
get { return m_StdDev1; }
set { if (m_StdDev1 != value) { m_StdDev1 = value; m_KernelNeedsUpdate = true; } }
public Color filterVariance2
public Color stdDev2
get { return m_filterVariance2; }
set { if (m_filterVariance2 != value) { m_filterVariance2 = value; m_kernelNeedsUpdate = true; } }
get { return m_StdDev2; }
set { if (m_StdDev2 != value) { m_StdDev2 = value; m_KernelNeedsUpdate = true; } }
public float filterLerpWeight
public float lerpWeight
get { return m_filterLerpWeight; }
set { if (m_filterLerpWeight != value) { m_filterLerpWeight = value; m_kernelNeedsUpdate = true; } }
get { return m_LerpWeight; }
set { if (m_LerpWeight != value) { m_LerpWeight = value; m_KernelNeedsUpdate = true; } }
get { if (m_kernelNeedsUpdate) ComputeKernel(); return m_filterKernel; }
get { if (m_KernelNeedsUpdate) ComputeKernel(); return m_FilterKernel; }
}
public static SubsurfaceScatteringProfile Default

SubsurfaceScatteringProfile profile = new SubsurfaceScatteringProfile();
profile.filterVariance1 = new Color(0.3f, 0.3f, 0.3f, 0.0f);
profile.filterVariance2 = new Color(1.0f, 1.0f, 1.0f, 0.0f);
profile.filterLerpWeight = 0.5f;
profile.stdDev1 = new Color(0.3f, 0.3f, 0.3f, 0.0f);
profile.stdDev2 = new Color(1.0f, 1.0f, 1.0f, 0.0f);
profile.lerpWeight = 0.5f;
static float Gaussian(float x, float variance)
static float Gaussian(float x, float stdDev)
float variance = stdDev * stdDev;
static float GaussianCombination(float x, float variance1, float variance2, float lerpWeight)
static float GaussianCombination(float x, float stdDev1, float stdDev2, float lerpWeight)
return Mathf.Lerp(Gaussian(x, variance1), Gaussian(x, variance2), lerpWeight);
return Mathf.Lerp(Gaussian(x, stdDev1), Gaussian(x, stdDev2), lerpWeight);
}
static float RationalApproximation(float t)

void ComputeKernel()
{
if (m_filterKernel == null)
if (m_FilterKernel == null)
m_filterKernel = new Vector4[numSamples];
m_FilterKernel = new Vector4[numSamples];
}
// Our goal is to blur the image using a filter which is represented

// It is separable by design, but generally not radially symmmetric.
// Find the widest Gaussian across 3 color channels.
float maxVariance1 = Mathf.Max(m_filterVariance1.r, m_filterVariance1.g, m_filterVariance1.b);
float maxVariance2 = Mathf.Max(m_filterVariance2.r, m_filterVariance2.g, m_filterVariance2.b);
float maxStdDev1 = Mathf.Max(m_StdDev1.r, m_StdDev1.g, m_StdDev1.b);
float maxStdDev2 = Mathf.Max(m_StdDev2.r, m_StdDev2.g, m_StdDev2.b);
float sd = Mathf.Lerp(Mathf.Sqrt(maxVariance1), Mathf.Sqrt(maxVariance2), m_filterLerpWeight);
float sd = Mathf.Lerp(maxStdDev1, maxStdDev2, m_LerpWeight);
Vector3 weightSum = new Vector3(0, 0, 0);

float pos = NormalCdfInverse(u, sd);
float pdf = Gaussian(pos, sd * sd);
float pdf = Gaussian(pos, sd);
val.x = GaussianCombination(pos, m_filterVariance1.r, m_filterVariance2.r, m_filterLerpWeight);
val.y = GaussianCombination(pos, m_filterVariance1.g, m_filterVariance2.g, m_filterLerpWeight);
val.z = GaussianCombination(pos, m_filterVariance1.b, m_filterVariance2.b, m_filterLerpWeight);
val.x = GaussianCombination(pos, m_StdDev1.r, m_StdDev2.r, m_LerpWeight);
val.y = GaussianCombination(pos, m_StdDev1.g, m_StdDev2.g, m_LerpWeight);
val.z = GaussianCombination(pos, m_StdDev1.b, m_StdDev2.b, m_LerpWeight);
m_filterKernel[i].x = val.x / (pdf * numSamples);
m_filterKernel[i].y = val.y / (pdf * numSamples);
m_filterKernel[i].z = val.z / (pdf * numSamples);
m_filterKernel[i].w = pos;
m_FilterKernel[i].x = val.x / (pdf * numSamples);
m_FilterKernel[i].y = val.y / (pdf * numSamples);
m_FilterKernel[i].z = val.z / (pdf * numSamples);
m_FilterKernel[i].w = pos;
weightSum.x += m_filterKernel[i].x;
weightSum.y += m_filterKernel[i].y;
weightSum.z += m_filterKernel[i].z;
weightSum.x += m_FilterKernel[i].x;
weightSum.y += m_FilterKernel[i].y;
weightSum.z += m_FilterKernel[i].z;
m_filterKernel[i].x *= 1.0f / weightSum.x;
m_filterKernel[i].y *= 1.0f / weightSum.y;
m_filterKernel[i].z *= 1.0f / weightSum.z;
m_FilterKernel[i].x *= 1.0f / weightSum.x;
m_FilterKernel[i].y *= 1.0f / weightSum.y;
m_FilterKernel[i].z *= 1.0f / weightSum.z;
m_kernelNeedsUpdate = false;
m_KernelNeedsUpdate = false;
}
}

正在加载...
取消
保存