SRP——聚光灯的阴影

https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/spotlight-shadows/
https://zhuanlan.zhihu.com/p/83499311?from_voters_page=true

什么是texture sampler?
在老的GLSL代码中,我们使用sampler2D来定义texture和sampler state。但他们是不同的东西,两者都占用资源。
sampler state是独立于texture单独存在。 我们可以复用一个sampler state去采样不同的texture。
具体参考:
https://forum.unity.com/threads/sampler-count-limit-for-pixel-shader-in-shader-model-5-0.452957/
https://docs.unity3d.com/Manual/SL-SamplerStates.html

1、投射纹理的shader:
加入一个"LightMode" = "ShadowCaster"的pass
顶点着色器的计算方法:

float4 worldPos = mul(UNITY_MATRIX_M, float4(input.pos.xyz, 1.0));
output.clipPos = mul(unity_MatrixVP, worldPos); //齐次坐标

投射的时候,加上bias,让其有一定的影子偏移,这里是投射的时候,加在了深度上:

#if UNITY_REVERSED_Z
	output.clipPos.z -= _ShadowBias;
	output.clipPos.z = min(output.clipPos.z, output.clipPos.w * UNITY_NEAR_CLIP_VALUE);
#else

UNITY_REVERSED_Z近处为1,远处为0,减去_ShadowBias,说明要让其写入的参考值小一点,比如如说原先写入的是0.5,我们对于0.49的这个点的深度,那么经过比较,发现0.49这个点,在阴影中。
而此时如果加上bias,0.5-0.02=0.48,写参考值为0.48
那么0.49大于0.48,表示这个点,不在阴影中,所以使得那些出现影子游泳的点,现在全都是被照亮的。

#if defined(UNITY_REVERSED_Z)
	#define UNITY_NEAR_CLIP_VALUE (1.0)
#else
	#define UNITY_NEAR_CLIP_VALUE (-1.0)
#endif

片段着色器,则直接返回0即可。

float4 ShadowCasterPassFragment (VertexOutput input) : SV_TARGET 
{
	return 0;
}

2、影子的绘制
判断当前有个多少个影响物体的灯光。

CullResults.Cull(ref cullingParameters, context, ref cull);
if (cull.visibleLights.Count > 0)
{
	……
}

这个当前场景可见的灯光总数。

for (int i = 0; i < cull.visibleLights.Count; i++)
{
	if (light.lightType == LightType.Spot)
	{}
}

初始化灯光。

判断灯光照射的区域,是否物体,如果没有则这个灯是无效的。

 if (shadowLight.shadows != LightShadows.None &&cull.GetShadowCasterBounds(i, out shadowBounds))

设置好灯光之后。

把不同的灯光,绘制的map放在不同的位置。
有效的灯光,加入有4个,那么需要将整个rt分为2行2列。

float tileOffsetX = tileIndex % split;
float tileOffsetY = tileIndex / split;
tileViewport.x = tileOffsetX * tileSize;
tileViewport.y = tileOffsetY * tileSize;
if (split > 1)
{
    shadowBuffer.SetViewport(tileViewport);
    shadowBuffer.EnableScissorRect(new Rect(tileViewport.x + 4f, tileViewport.y + 4f,tileSize - 8f, tileSize - 8f));
}

+4的偏移,详见原文。
得到灯光的矩阵:

if (!cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData))
{
    ……
}
shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[i].light.shadowBias);
context.ExecuteCommandBuffer(shadowBuffer);
shadowBuffer.Clear();
发布了646 篇原创文章 · 获赞 107 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/wodownload2/article/details/104899495