3.2.3 以前属于Shader部分,Shader部分不进行讲解。
这里只涉及Unity内部管线的设置问题。
在UniversalRenderPipeline.cs > RenderSingleCamera()
下调用函数renderer.Execute()
该函数走向ScriptableRenderer.cs>Execute()
函数,该函数调用了SetupLights()
函数
SetupLights()
函数为一个虚函数
具体实现在UniversalRenderer.cs>SetupLights()
中
该方法调用了m_ForwardLights实例下的_ForwardLights.Setup(context, ref renderingData);
方法
URP中关于前向渲染的灯光设置,即在ForwardLights.cs中
SetUp()
函数将来自于ref RenderingData renderingData
中的灯光数据发送到GPU。
public void Setup(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(null, m_ProfilingSampler))
{
// 设置ClusteredRendering(Forward+)属性参数
if (useClusteredRendering){
...
}
// 设置Shader常量属性
SetupShaderLightConstants(cmd, ref renderingData);
// 设置Shader关键字
bool lightCountCheck = (renderingData.cameraData.renderer.stripAdditionalLightOffVariants && renderingData.lightData.supportsAdditionalLights) || additionalLightsCount > 0;
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightsVertex,
lightCountCheck && additionalLightsPerVertex && !useClusteredRendering);
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightsPixel,
lightCountCheck && !additionalLightsPerVertex && !useClusteredRendering);
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.ClusteredRendering,
useClusteredRendering);
...
// 设置LightCookie(灯光遮罩)
m_LightCookieManager.Setup(context, cmd, ref renderingData.lightData);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
其中,关键字【ShaderKeywordStrings.AdditionalLightsVertex】 在 UniversalRenderPipelineCore中定义
注意:这里使用引用传递传递RenderingData ,因为RenderingData 结构的数据量很大。
void SetupShaderLightConstants(CommandBuffer cmd, ref RenderingData renderingData)
{
m_MixedLightingSetup = MixedLightingSetup.None;
// 主光源有一个优化的主光源着色器路径。这将有利于那些只关心单一光线的游戏。
// 通用管道也只支持单个阴影光,如果可用,它将是主光源。
SetupMainLightConstants(cmd, ref renderingData.lightData);
SetupAdditionalLightConstants(cmd, ref renderingData);
}
void SetupMainLightConstants(CommandBuffer cmd, ref LightData lightData)
{
Vector4 lightPos, lightColor, lightAttenuation, lightSpotDir, lightOcclusionChannel;
uint lightLayerMask;
// 根据visibleLights[mainLightIndex]数据,获取out的如下数据
InitializeLightConstants(lightData.visibleLights, lightData.mainLightIndex,
out lightPos, out lightColor, out lightAttenuation,
out lightSpotDir, out lightOcclusionChannel, out lightLayerMask);
// 将数据
cmd.SetGlobalVector(LightConstantBuffer._MainLightPosition, lightPos);
cmd.SetGlobalVector(LightConstantBuffer._MainLightColor, lightColor);
cmd.SetGlobalVector(LightConstantBuffer._MainLightOcclusionProbesChannel, lightOcclusionChannel);
cmd.SetGlobalInt(LightConstantBuffer._MainLightLayerMask, (int)lightLayerMask);
}
其中,InitializeLightConstants函数如下
void InitializeLightConstants(NativeArray<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightAttenuation, out Vector4 lightSpotDir, out Vector4 lightOcclusionProbeChannel, out uint lightLayerMask)
{
// 得到前5个数据
UniversalRenderPipeline.InitializeLightConstants_Common(lights, lightIndex, out lightPos, out lightColor, out lightAttenuation, out lightSpotDir, out lightOcclusionProbeChannel);
// 得到lightLayerMask
lightLayerMask = 0;
...
lightLayerMask = (uint)additionalLightData.lightLayerMask;
}
额外光源与主光源相同,只是传入的数据是一个数组,数组长度与最大额外光源数相同。
核心函数:
InitializeLightConstants(lights, i,
out m_AdditionalLightPositions[lightIter],
out m_AdditionalLightColors[lightIter],
out m_AdditionalLightAttenuations[lightIter],
out m_AdditionalLightSpotDirections[lightIter],
out m_AdditionalLightOcclusionProbeChannels[lightIter],
out lightLayerMask);
之后便可以用这些光照数据计算着色~~~