浏览代码

Moved bias and normalBias to caster side. Applying frustum size scale on cascade bias and texelSize scale in normal bias.

/feature-ReflectionProbeFit
Felipe Lira 7 年前
当前提交
b5dfd1ee
共有 4 个文件被更改,包括 100 次插入63 次删除
  1. 115
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  2. 22
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassShadow.hlsl
  3. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Lighting.hlsl
  4. 24
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl

115
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private bool m_RequiredDepth;
private MixedLightingSetup m_MixedLightingSetup;
private const int kShadowDepthBufferBits = 16;
private const int kCameraDepthBufferBits = 32;
private const int kDepthStencilBufferBits = 32;
private Vector4[] m_DirectionalShadowSplitDistances = new Vector4[kMaxCascades];
private ShadowSettings m_ShadowSettings = ShadowSettings.Default;

if (m_RequiredDepth)
{
RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(rtWidth, rtHeight, RenderTextureFormat.Depth, kCameraDepthBufferBits);
RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(rtWidth, rtHeight, RenderTextureFormat.Depth, kDepthStencilBufferBits);
cmd.GetTemporaryRT(CameraRenderTargetID.depth, depthRTDesc, FilterMode.Bilinear);
if (LightweightUtils.HasFlag(renderingConfig, FrameRenderingConfiguration.DepthCopy))

RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(rtWidth, rtHeight, m_ColorFormat, kCameraDepthBufferBits);
RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(rtWidth, rtHeight, m_ColorFormat, kDepthStencilBufferBits);
colorRTDesc.msaaSamples = msaaSamples;
colorRTDesc.enableRandomWrite = false;

// Lightweight pipeline also supports only a single shadow light, if available it will be the main light.
SetupMainLightConstants(cmd, lights, lightData.mainLightIndex);
if (lightData.shadowMapSampleType != LightShadows.None)
SetupShadowShaderConstants(cmd, ref lights[lightData.mainLightIndex], m_ShadowCasterCascadesCount);
SetupShadowReceiverConstants(cmd, ref lights[lightData.mainLightIndex], m_ShadowCasterCascadesCount);
if (lightData.totalAdditionalLightsCount > 0)
SetupAdditionalListConstants(cmd, lights, ref lightData);

cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightSpotAttenuation, m_LightSpotAttenuations);
}
private void SetupShadowShaderConstants(CommandBuffer cmd, ref VisibleLight shadowLight, int cascadeCount)
private void SetupShadowCasterConstants(CommandBuffer cmd, ref VisibleLight visibleLight, Matrix4x4 proj, float cascadeResolution)
{
Light light = visibleLight.light;
float bias = 0.0f;
float normalBias = 0.0f;
if (visibleLight.lightType == LightType.Directional)
{
// Scale bias by cascade depth.
// Directional has orthogonal projection so proj.m22 = -2 / (far - near)
// if reversed z buffer we don't need to flip sign as proj.m22 sign is already negative
float sign = (SystemInfo.usesReversedZBuffer) ? 1.0f : -1.0f;
bias = light.shadowBias * proj.m22 * 0.5f * sign;
// Currently only square pot cascades resolutions are used.
float texelSizeX = proj.m00 * 0.5f / cascadeResolution;
float texelSizeY = proj.m11 * 0.5f / cascadeResolution;
float texelSize = Mathf.Max(texelSizeX, texelSizeY);
// Since we are applying normal bias on caster side we want an inset normal offset
// thus we keep the negative bias
normalBias = light.shadowNormalBias * texelSize;
}
else if (visibleLight.lightType == LightType.Spot)
{
float sign = (SystemInfo.usesReversedZBuffer) ? -1.0f : 1.0f;
bias = light.shadowBias * sign;
normalBias = 0.0f;
}
else
{
Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline");
}
cmd.SetGlobalVector("_ShadowBias", new Vector4(bias, normalBias, 0.0f, 0.0f));
}
private void SetupShadowReceiverConstants(CommandBuffer cmd, ref VisibleLight shadowLight, int cascadeCount)
float bias = light.shadowBias * 0.1f;
float normalBias = light.shadowNormalBias;
float nearPlane = light.shadowNearPlane;
float shadowResolution = m_ShadowSlices[0].shadowResolution;
const int maxShadowCascades = 4;

float invShadowResolution = 0.5f / shadowResolution;
cmd.SetGlobalMatrixArray("_WorldToShadow", shadowMatrices);
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_ShadowData", new Vector4(strength, bias, normalBias, nearPlane));
cmd.SetGlobalVector("_ShadowData", new Vector4(strength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset0", new Vector4(-invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset1", new Vector4(invShadowResolution, -invShadowResolution, 0.0f, 0.0f));
cmd.SetGlobalVector("_ShadowOffset2", new Vector4(-invShadowResolution, invShadowResolution, 0.0f, 0.0f));

if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds))
return false;
var cmd = CommandBufferPool.Get();
cmd.name = "Render packed shadows";
cmd.GetTemporaryRT(m_ShadowMapRTID, m_ShadowSettings.shadowAtlasWidth,
m_ShadowSettings.shadowAtlasHeight, kShadowDepthBufferBits, FilterMode.Bilinear, m_ShadowSettings.renderTextureFormat);
SetRenderTarget(cmd, m_ShadowMapRT, ClearFlag.All);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
Vector3 splitRatio = m_ShadowSettings.directionalLightCascades;
bool needRendering = false;
bool success = false;
var cmd = CommandBufferPool.Get("Render Shadowmap");
cmd.GetTemporaryRT(m_ShadowMapRTID, m_ShadowSettings.shadowAtlasWidth,
m_ShadowSettings.shadowAtlasHeight, kDepthStencilBufferBits, FilterMode.Bilinear, m_ShadowSettings.renderTextureFormat);
SetRenderTarget(cmd, m_ShadowMapRT, ClearFlag.All);
needRendering = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj,
success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj,
if (!needRendering)
return false;
SetupShadowSliceTransform(0, shadowResolution, proj, view);
RenderShadowSlice(ref context, 0, proj, view, settings);
if (success)
{
SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
SetupShadowSliceTransform(0, shadowResolution, proj, view);
RenderShadowSlice(cmd, ref context, 0, proj, view, settings);
}
needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
cascadeIdx, m_ShadowCasterCascadesCount, splitRatio, shadowResolution, shadowNearPlane, out view, out proj,
success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
cascadeIdx, m_ShadowCasterCascadesCount, m_ShadowSettings.directionalLightCascades, shadowResolution, shadowNearPlane, out view, out proj,
if (!needRendering)
return false;
if (!success)
break;
SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
RenderShadowSlice(ref context, cascadeIdx, proj, view, settings);
RenderShadowSlice(cmd, ref context, cascadeIdx, proj, view, settings);
return false;
return true;
CommandBufferPool.Release(cmd);
return success;
// Assumes MAX_CASCADES = 4
if (cascadeIndex >= 4)
{
Debug.LogError(String.Format("{0} is an invalid cascade index. Maximum of 4 cascades"));
return;
}
m_ShadowSlices[cascadeIndex].atlasX = (cascadeIndex % 2) * shadowResolution;
m_ShadowSlices[cascadeIndex].atlasY = (cascadeIndex / 2) * shadowResolution;
m_ShadowSlices[cascadeIndex].shadowResolution = shadowResolution;

m_ShadowSlices[cascadeIndex].shadowTransform = matTile * matScaleBias * proj * view;
}
private void RenderShadowSlice(ref ScriptableRenderContext context, int cascadeIndex,
private void RenderShadowSlice(CommandBuffer cmd, ref ScriptableRenderContext context, int cascadeIndex,
var buffer = CommandBufferPool.Get("Prepare Shadowmap Slice");
buffer.SetViewport(new Rect(m_ShadowSlices[cascadeIndex].atlasX, m_ShadowSlices[cascadeIndex].atlasY,
cmd.SetViewport(new Rect(m_ShadowSlices[cascadeIndex].atlasX, m_ShadowSlices[cascadeIndex].atlasY,
buffer.SetViewProjectionMatrices(view, proj);
context.ExecuteCommandBuffer(buffer);
cmd.SetViewProjectionMatrices(view, proj);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(buffer);
cmd.Clear();
}
private int GetMaxTileResolutionInAtlas(int atlasWidth, int atlasHeight, int tileCount)

22
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightPassShadow.hlsl


#include "LightweightShaderLibrary/Core.hlsl"
float4 ShadowPassVertex(float4 pos : POSITION) : SV_POSITION
// x: global clip space bias, y: normal world space bias
float4 _ShadowBias;
struct VertexInput
float4 clipPos = TransformObjectToHClip(pos.xyz);
float4 position : POSITION;
float3 normal : NORMAL;
};
float4 ShadowPassVertex(VertexInput v) : SV_POSITION
{
float3 positionWS = TransformObjectToWorld(v.position.xyz);
float3 normalWS = TransformObjectToWorldDir(v.normal);
// normal bias is negative since we want to apply an inset normal offset
positionWS = normalWS * _ShadowBias.yyy + positionWS;
float4 clipPos = TransformWorldToHClip(positionWS);
// _ShadowBias.x sign depens on if platform has reversed z buffer
clipPos.z += _ShadowBias.x;
#if defined(UNITY_REVERSED_Z)
clipPos.z = min(clipPos.z, UNITY_NEAR_CLIP_VALUE);
#else

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Lighting.hlsl


// Cookies and shadows are only computed for main light
attenuation *= CookieAttenuation(positionWS);
attenuation *= RealtimeShadowAttenuation(positionWS, normalWS, lightDirection);
attenuation *= RealtimeShadowAttenuation(positionWS);
return attenuation;
}

24
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightShaderLibrary/Shadows.hlsl


half4 _ShadowOffset1;
half4 _ShadowOffset2;
half4 _ShadowOffset3;
half4 _ShadowData; // (x: 1.0 - shadowStrength, y: bias, z: normal bias, w: near plane offset)
half4 _ShadowData; // (x: 1.0 - shadowStrength)
float ApplyDepthBias(float clipZ)
{
#ifdef UNITY_REVERSED_Z
return clipZ + _ShadowData.y;
#endif
return clipZ - _ShadowData.y;
}
inline half SampleShadowmap(float4 shadowCoord)
{
#if defined(_SHADOWS_PERSPECTIVE)

#endif
coord.z = saturate(ApplyDepthBias(coord.z));
coord.z = saturate(coord.z);
if (coord.x <= 0 || coord.x >= 1 || coord.y <= 0 || coord.y >= 1)
return 1;

return 4 - dot(weights, half4(4, 3, 2, 1));
}
inline half RealtimeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir)
inline half RealtimeShadowAttenuation(float3 posWorld)
half NdotL = dot(vertexNormal, shadowDir);
half bias = saturate(1.0 - NdotL) * _ShadowData.z;
float3 posWorldOffsetNormal = posWorld + vertexNormal * bias;
cascadeIndex = ComputeCascadeIndex(posWorldOffsetNormal);
cascadeIndex = ComputeCascadeIndex(posWorld);
float4 shadowCoord = mul(_WorldToShadow[cascadeIndex], float4(posWorldOffsetNormal, 1.0));
float4 shadowCoord = mul(_WorldToShadow[cascadeIndex], float4(posWorld, 1.0));
return SampleShadowmap(shadowCoord);
}

正在加载...
取消
保存