浏览代码

Merge pull request #287 from EvgeniiG/master

Replace wrapped lighting with Fresnel
/RenderPassXR_Sandbox
GitHub 7 年前
当前提交
6c04469e
共有 8 个文件被更改,包括 89 次插入83 次删除
  1. 3
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  2. 43
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  3. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  4. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  5. 94
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  6. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawSssProfile.shader
  7. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/SceneSettings/Resources/DrawTransmittanceGraph.shader
  8. 6
      Assets/ScriptableRenderPipeline/ShaderLibrary/CommonMaterial.hlsl

3
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


Shader.SetGlobalInt( "_TexturingModeFlags", (int)sssParameters.texturingModeFlags);
Shader.SetGlobalInt( "_TransmissionFlags", (int)sssParameters.transmissionFlags);
cmd.SetGlobalFloatArray( "_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray("_ShapeParameters", sssParameters.shapeParameters);
cmd.SetGlobalVectorArray("_VolumeShapeParams", sssParameters.volumeShapeParams);
cmd.SetGlobalVectorArray("_VolumeAlbedos", sssParameters.volumeAlbedos);
renderContext.ExecuteCommandBuffer(cmd);

var cmd = new CommandBuffer() { name = "Subsurface Scattering" };
cmd.SetGlobalTexture("_IrradianceSource", m_CameraSubsurfaceBufferRT); // Cannot set a RT on a material
m_FilterAndCombineSubsurfaceScattering.SetVectorArray("_SurfaceShapeParams", sssParameters.surfaceShapeParams);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_WorldScales", sssParameters.worldScales);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsNearField", sssParameters.filterKernelsNearField);
m_FilterAndCombineSubsurfaceScattering.SetFloatArray("_FilterKernelsFarField", sssParameters.filterKernelsFarField);

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


uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
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 _VolumeShapeParams[SSS_N_PROFILES]; // RGB = S = 1 / D; A = unused
float4 _VolumeAlbedos[SSS_N_PROFILES]; // RGB = color, A = unused
//-----------------------------------------------------------------------------

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

}
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
{
// Use 16 bits to encode the thickness, and up to 8 bits to encode the profile ID.
// We need a lot of precision to minimize banding of NdotV-weighted thickness.
outGBuffer2 = float4(surfaceData.subsurfaceRadius,
PackFloatToR8G8(surfaceData.thickness),
PackByte(surfaceData.subsurfaceProfile));
outGBuffer2 = float4(surfaceData.subsurfaceRadius, surfaceData.thickness, 0, PackByte(surfaceData.subsurfaceProfile));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{

}
else if (supportsSSS && bsdfData.materialId == MATERIALID_LIT_SSS)
{
// Use 16 bits to encode the thickness, and up to 8 bits to encode the profile ID.
// We need a lot of precision to minimize banding of NdotV-weighted thickness.
float thickness = UnpackFloatFromR8G8(inGBuffer2.yz);
float thickness = inGBuffer2.y;
int subsurfaceProfile = UnpackByte(inGBuffer2.w);
FillMaterialIdSSSData(baseColor, subsurfaceProfile, subsurfaceRadius, thickness, bsdfData);

[branch] if (bsdfData.enableTransmission)
{
// 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);
// Use the reversed normal from the front for the back of the object.
illuminance = F_Transm_Schlick(bsdfData.fresnel0, saturate(-NdotL));
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale * Lambert());
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
float3 transmittedLight = backLight * bsdfData.diffuseColor * bsdfData.transmittance;
float3 transmittedLight = backLight * (bsdfData.diffuseColor * bsdfData.transmittance);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;

[branch] if (bsdfData.enableTransmission)
{
// 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;
// Use the reversed normal from the front for the back of the object.
illuminance = F_Transm_Schlick(bsdfData.fresnel0, saturate(-NdotL)) * attenuation;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale * Lambert());
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
float3 transmittedLight = backLight * bsdfData.diffuseColor * bsdfData.transmittance;
float3 transmittedLight = backLight * (bsdfData.diffuseColor * bsdfData.transmittance);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;

[branch] if (bsdfData.enableTransmission)
{
// Reverse the normal + do some wrap lighting to have a nicer transition between regular lighting and transmittance
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * clipFactor;
// Use the reversed normal from the front for the back of the object.
illuminance = F_Transm_Schlick(bsdfData.fresnel0, saturate(-NdotL)) * clipFactor;
// The difference between the Disney Diffuse and the Lambertian BRDF for transmission is negligible.
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale * Lambert());
float3 backLight = (cookie.rgb * lightData.color) * (illuminance * lightData.diffuseScale);
float3 transmittedLight = backLight * bsdfData.diffuseColor * bsdfData.transmittance;
float3 transmittedLight = backLight * (bsdfData.diffuseColor * bsdfData.transmittance);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += transmittedLight;

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


surfaceData.thickness *= SAMPLE_UVMAPPING_TEXTURE2D(_ThicknessMap, sampler_ThicknessMap, layerTexCoord.base).r;
#endif
surfaceData.thickness = 1 - surfaceData.thickness; // Reverse for artists
surfaceData.specularColor = _SpecularColor.rgb;
#ifdef _SPECULARCOLORMAP
surfaceData.specularColor *= SAMPLE_UVMAPPING_TEXTURE2D(_SpecularColorMap, sampler_SpecularColorMap, layerTexCoord.base).rgb;

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


// Inputs & outputs
//-------------------------------------------------------------------------------------
float _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters
float _FilterKernelsNearField[SSS_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
float _FilterKernelsFarField[SSS_N_PROFILES][SSS_N_SAMPLES_FAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
float4 _SurfaceShapeParams[SSS_N_PROFILES]; // RGB = S = 1 / D, A = filter radius
float _WorldScales[SSS_N_PROFILES]; // Size of the world unit in meters
float _FilterKernelsNearField[SSS_N_PROFILES][SSS_N_SAMPLES_NEAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
float _FilterKernelsFarField[SSS_N_PROFILES][SSS_N_SAMPLES_FAR_FIELD][2]; // 0 = radius, 1 = reciprocal of the PDF
TEXTURE2D(_IrradianceSource); // Includes transmitted light
DECLARE_GBUFFER_TEXTURE(_GBufferTexture); // Contains the albedo and SSS parameters

float2 vec = r * float2(cos(phi), sin(phi)); \
\
float2 position = centerPosUnSS + vec * scaledPixPerMm; \
float rcpPdf = kernel[profileID][i][1]; \
float3 irradiance = LOAD_TEXTURE2D(_IrradianceSource, position).rgb; \
\
/* TODO: see if making this a [branch] improves performance. */ \

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); \
float p = kernel[profileID][i][1]; \
float3 w = ComputeBilateralWeight(shapeParam, r, t, rcpDistScale, p); \
\
totalIrradiance += w * irradiance; \
totalWeight += w; \

int profileID = bsdfData.subsurfaceProfile;
float distScale = bsdfData.subsurfaceRadius;
float3 shapeParam = _ShapeParameters[profileID].rgb;
float maxDistance = _ShapeParameters[profileID].a;
float3 shapeParam = _SurfaceShapeParams[profileID].rgb;
float maxDistance = _SurfaceShapeParams[profileID].a;
// Reconstruct the view-space position.
float2 centerPosSS = posInput.positionSS;

float2 scaledPixPerMm = distScale * rcp(millimPerUnit * unitsPerPixel);
// Take the first (central) sample.
// TODO: copy its neighborhood into LDS.
float2 centerPosition = posInput.unPositionSS;
float3 centerIrradiance = LOAD_TEXTURE2D(_IrradianceSource, centerPosition).rgb;

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


[HideInInspector]
public int settingsIndex; // SubsurfaceScatteringSettings.profiles[i]
[SerializeField]
Vector3 m_S; // RGB = shape parameter: S = 1 / D
Vector3 m_SurfaceShapeParam; // RGB = shape parameter: S = 1 / D
[SerializeField]
Vector3 m_VolumeShapeParam; // RGB = shape parameter: S = 1 / D
[SerializeField]
float m_ScatteringDistance; // Filter radius (in millimeters)
[SerializeField]

m_FilterKernelFarField = new Vector2[SssConstants.SSS_N_SAMPLES_FAR_FIELD];
}
m_S = new Vector3();
m_SurfaceShapeParam = new Vector3();
m_S.x = FindFitForS(surfaceAlbedo.r);
m_S.y = FindFitForS(surfaceAlbedo.g);
m_S.z = FindFitForS(surfaceAlbedo.b);
m_SurfaceShapeParam.x = FindFitForS(surfaceAlbedo.r);
m_SurfaceShapeParam.y = FindFitForS(surfaceAlbedo.g);
m_SurfaceShapeParam.z = FindFitForS(surfaceAlbedo.b);
m_VolumeShapeParam.x = FindFitForS(volumeAlbedo.r);
m_VolumeShapeParam.y = FindFitForS(volumeAlbedo.g);
m_VolumeShapeParam.z = FindFitForS(volumeAlbedo.b);
m_S.x *= 1.0f / lenVolMeanFreePath;
m_S.y *= 1.0f / lenVolMeanFreePath;
m_S.z *= 1.0f / lenVolMeanFreePath;
m_SurfaceShapeParam *= 1.0f / lenVolMeanFreePath;
m_VolumeShapeParam *= 1.0f / lenVolMeanFreePath;
float s = Mathf.Min(m_S.x, m_S.y, m_S.z);
float s = Mathf.Min(m_SurfaceShapeParam.x, m_SurfaceShapeParam.y, m_SurfaceShapeParam.z);
// Importance sample the normalized diffusion profile for the computed value of 's'.
// ------------------------------------------------------------------------------------

}
}
public Vector3 shapeParameter
public Vector3 surfaceShapeParameter
{
// Set in BuildKernel().
get { return m_SurfaceShapeParam; }
}
public Vector3 volumeShapeParameter
get { return m_S; }
get { return m_VolumeShapeParam; }
}
public float scatteringDistance

[NonSerialized] public uint texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[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[] surfaceShapeParams; // RGB = S = 1 / D, A = filter radius
[NonSerialized] public Vector4[] volumeShapeParams; // RGB = S = 1 / D, 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

texturingModeFlags = 0;
transmissionFlags = 0;
thicknessRemaps = null;
shapeParameters = null;
surfaceShapeParams = null;
volumeShapeParams = null;
filterKernelsNearField = null;
filterKernelsFarField = null;

thicknessRemaps = new float[thicknessRemapsLen];
}
const int worldScalesLen = SssConstants.SSS_N_PROFILES;
if (worldScales == null || worldScales.Length != worldScalesLen)
if (worldScales == null || worldScales.Length != SssConstants.SSS_N_PROFILES)
worldScales = new float[worldScalesLen];
worldScales = new float[SssConstants.SSS_N_PROFILES];
const int shapeParametersLen = SssConstants.SSS_N_PROFILES;
if (shapeParameters == null || shapeParameters.Length != shapeParametersLen)
if (surfaceShapeParams == null || surfaceShapeParams.Length != SssConstants.SSS_N_PROFILES)
shapeParameters = new Vector4[shapeParametersLen];
surfaceShapeParams = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (volumeShapeParams == null || volumeShapeParams.Length != SssConstants.SSS_N_PROFILES)
{
volumeShapeParams = new Vector4[SssConstants.SSS_N_PROFILES];
const int volumeAlbedosLen = SssConstants.SSS_N_PROFILES;
if (volumeAlbedos == null || volumeAlbedos.Length != volumeAlbedosLen)
if (volumeAlbedos == null || volumeAlbedos.Length != SssConstants.SSS_N_PROFILES)
volumeAlbedos = new Vector4[volumeAlbedosLen];
volumeAlbedos = new Vector4[SssConstants.SSS_N_PROFILES];
}
const int filterKernelsNearFieldLen = 2 * SssConstants.SSS_N_PROFILES * SssConstants.SSS_N_SAMPLES_NEAR_FIELD;

thicknessRemaps[2 * i] = profiles[i].thicknessRemap.x;
thicknessRemaps[2 * i + 1] = profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x;
worldScales[i] = profiles[i].worldScale;
shapeParameters[i] = profiles[i].shapeParameter;
shapeParameters[i].w = profiles[i].scatteringDistance;
surfaceShapeParams[i] = profiles[i].surfaceShapeParameter;
surfaceShapeParams[i].w = profiles[i].scatteringDistance;
volumeShapeParams[i] = profiles[i].volumeShapeParameter;
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;
volumeAlbedos[i] = Vector4.zero;
worldScales[i] = 1.0f;
surfaceShapeParams[i] = Vector4.zero;
volumeShapeParams[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++)
{

private RenderTexture m_ProfileImage, m_TransmittanceImage;
private Material m_ProfileMaterial, m_TransmittanceMaterial;
private SerializedProperty m_LenVolMeanFreePath, m_ScatteringDistance, m_SurfaceAlbedo, m_VolumeAlbedo, m_S,
private SerializedProperty m_LenVolMeanFreePath, m_ScatteringDistance, m_SurfaceAlbedo, m_VolumeAlbedo, m_SurfaceShapeParam, m_VolumeShapeParam,
m_TexturingMode, m_TransmissionMode, m_ThicknessRemap, m_WorldScale;
void OnEnable()

m_LenVolMeanFreePath = serializedObject.FindProperty("lenVolMeanFreePath");
m_ScatteringDistance = serializedObject.FindProperty("m_ScatteringDistance");
m_S = serializedObject.FindProperty("m_S");
m_SurfaceShapeParam = serializedObject.FindProperty("m_SurfaceShapeParam");
m_VolumeShapeParam = serializedObject.FindProperty("m_VolumeShapeParam");
m_TexturingMode = serializedObject.FindProperty("texturingMode");
m_TransmissionMode = serializedObject.FindProperty("transmissionMode");
m_ThicknessRemap = serializedObject.FindProperty("thicknessRemap");

EditorGUILayout.Space();
}
float d = m_ScatteringDistance.floatValue;
Vector4 A = m_SurfaceAlbedo.colorValue;
Vector4 V = m_VolumeAlbedo.colorValue;
Vector3 S = m_S.vector3Value;
Vector2 R = m_ThicknessRemap.vector2Value;
float d = m_ScatteringDistance.floatValue;
Vector4 aS = m_SurfaceAlbedo.colorValue;
Vector4 aV = m_VolumeAlbedo.colorValue;
Vector3 sS = m_SurfaceShapeParam.vector3Value;
Vector3 sV = m_VolumeShapeParam.vector3Value;
Vector2 R = m_ThicknessRemap.vector2Value;
m_ProfileMaterial.SetVector("_SurfaceAlbedo", A);
m_ProfileMaterial.SetVector("_ShapeParameter", S);
m_ProfileMaterial.SetVector("_SurfaceAlbedo", aS);
m_ProfileMaterial.SetVector("_SurfaceShapeParam", sS);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256, 256), m_ProfileImage, m_ProfileMaterial, ScaleMode.ScaleToFit, 1.0f);
EditorGUILayout.Space();

// Draw the transmittance graph.
m_TransmittanceMaterial.SetFloat("_ScatteringDistance", d);
m_TransmittanceMaterial.SetVector("_VolumeAlbedo", transmissionEnabled ? V : Vector4.zero);
m_TransmittanceMaterial.SetVector("_ShapeParameter", S);
m_TransmittanceMaterial.SetVector("_VolumeAlbedo", transmissionEnabled ? aV : Vector4.zero);
m_TransmittanceMaterial.SetVector("_VolumeShapeParam", sV);
m_TransmittanceMaterial.SetVector("_ThicknessRemap", R);
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(16, 16), m_TransmittanceImage, m_TransmittanceMaterial, ScaleMode.ScaleToFit, 16.0f);

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


// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _SurfaceAlbedo, _ShapeParameter;
float4 _SurfaceAlbedo, _SurfaceShapeParam;
float _ScatteringDistance; // See 'SubsurfaceScatteringProfile'
//-------------------------------------------------------------------------------------

float4 Frag(Varyings input) : SV_Target
{
float r = (2 * length(input.texcoord - 0.5)) * _ScatteringDistance;
float3 S = _ShapeParameter.rgb;
float3 S = _SurfaceShapeParam.rgb;
float3 M = S * (exp(-r * S) + exp(-r * S * (1.0 / 3.0))) / (8 * PI * r);
// N.b.: we multiply by the surface albedo of the actual geometry during shading.

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


// Inputs & outputs
//-------------------------------------------------------------------------------------
float4 _VolumeAlbedo, _ShapeParameter, _ThicknessRemap;
float4 _VolumeAlbedo, _VolumeShapeParam, _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, float3(1, 1, 1), d, 1);
float3 T = ComputeTransmittance(_VolumeShapeParam.rgb, float3(1, 1, 1), d, 1);
// Apply gamma for visualization only. Do not apply gamma to the color.
return float4(pow(T, 1.0 / 3) * _VolumeAlbedo.rgb, 1);

6
Assets/ScriptableRenderPipeline/ShaderLibrary/CommonMaterial.hlsl


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
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex, name) ((tex.xy) * name##_ST.xy + name##_ST.zw)

正在加载...
取消
保存