文章目录
- CPU数据搜集
- GPU数据使用
- 光照计算
CPU数据搜集
我们只能支持有限数量的其他灯。并将这些灯光数据(位置、颜色、阴影强度、方向光光源、灯光遮蔽Probe、灯光层级Mask)发送到GPU以供场景中所有物体渲染使用。
//ForwardLights.cs
额外光源数量与使用的平台以及API有关
- 如果是移动端 并且 使用OpenGLES2、OpenGLES3(小于OpenGLES30版本),则最大额外光源数为16
- 否则,如果是移动端 或着 PC端使用OpenGLCore、OpenGLES2、OpenGLES3,则最大额外光源数为32
- 否则,最大额外光源数为256(即PC端使用OpenGL3.0以上版本、或其他API)
//UniversalRenderPipeline.cs
遍历场景获取所有光源数据
// ForwardLights.cs
//Setup() > SetupShaderLightConstants() > SetupAdditionalLightConstants()
循环遍历所有光源
InitializeLightConstants() > InitializeLightConstants_Common()
处理单个光源数据,获取数据保存到LightConstantBuffer中
关于SpotLight的衰减值,定义在
//UniversalRenderPipelineCore.cs
最终,将Buffer发送到GPU
GPU数据使用
输入的光线信息变量保存在Input.hlsl
获取这些信息的函数保存在realtimeLights.hlsl
// Fills a light struct given a perObjectLightIndex
Light GetAdditionalPerObjectLight(int perObjectLightIndex, float3 positionWS)
因为我们计算逐个对象需要的并不是所有光源,而是对该对象贡献最大的几个光源(Unity中一般设置为4个),因此,需要告诉管线我们需要这些数据。
在drawingSettings 中设置
perObjectData |= PerObjectData.LightData | PerObjectData.LightIndices;
即可得到Unity定义在UnityInput中的数据
// Light Indices block feature
// These are set internally by the engine upon request by RendererConfiguration.
half4 unity_LightData;
half4 unity_LightIndices[2];
half4 unity_LightData;
- x : GetPerObjectLightIndexOffset(),一般为0
- y:影响单个物体灯光的数量保存在
unity_LightData.y
。GetAdditionalLightsCount(),该数量可能超过最大渲染灯光数。 - z:
light.distanceAttenuation = unity_LightData.z;
// unity_LightData.z is 1 when not culled by the culling mask, otherwise 0.
half4 unity_LightIndices[2];
每个需要计算的灯光下标保存在half4 unity_LightIndices[2]
中,共8个int,因此最大支持每个物体8个光源。
该下标通过RealtimeLights.hlsl中的GetPerObjectLightIndex()获得
int GetPerObjectLightIndex(uint index)
{
//一般情况
float4 tmp = unity_LightIndices[index / 4];
return int(tmp[index % 4]);
}
额外光源信息获取,全套使用流程:
#if defined(_ADDITIONAL_LIGHTS)
uint pixelLightCount = GetAdditionalLightsCount();
LIGHT_LOOP_BEGIN(pixelLightCount)// lightIndex
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
{
lightingData.additionalLightsColor += LightingPhysicallyBased(brdfData, brdfDataClearCoat, light,
inputData.normalWS, inputData.viewDirectionWS,
surfaceData.clearCoatMask, specularHighlightsOff);
}
LIGHT_LOOP_END
#endif
其中使用的函数:
- 获取额外光源数量(_AdditionalLightsCount.x为我们设置的对象可接受的最大额外光源数)
int GetAdditionalLightsCount()
{
#if USE_CLUSTERED_LIGHTING
// Counting the number of lights in clustered requires traversing the bit list, and is not needed up front.
return 0;
#else
// TODO: we need to expose in SRP api an ability for the pipeline cap the amount of lights
// in the culling. This way we could do the loop branch with an uniform
// This would be helpful to support baking exceeding lights in SH as well
return int(min(_AdditionalLightsCount.x, unity_LightData.y));
#endif
}
- 获取光源下标后,获取光照信息
Light GetAdditionalLight(uint i, float3 positionWS)
{
#if USE_CLUSTERED_LIGHTING
int lightIndex = i;
#else
int lightIndex = GetPerObjectLightIndex(i);
#endif
return GetAdditionalPerObjectLight(lightIndex, positionWS);
}
光照计算
此处便不再说明光照计算
unity会根据是否添加额外光照,添加关键字_ADDITIONAL_LIGHTS