Unity SRP 管线【第九讲:URP 点光源与聚光灯】

文章目录

  • CPU数据搜集
  • GPU数据使用
  • 光照计算

Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第1张图片

CPU数据搜集

我们只能支持有限数量的其他灯。并将这些灯光数据(位置、颜色、阴影强度、方向光光源、灯光遮蔽Probe、灯光层级Mask)发送到GPU以供场景中所有物体渲染使用。

//ForwardLights.cs
Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第2张图片
额外光源数量与使用的平台以及API有关

  • 如果是移动端 并且 使用OpenGLES2、OpenGLES3(小于OpenGLES30版本),则最大额外光源数为16
  • 否则,如果是移动端 或着 PC端使用OpenGLCore、OpenGLES2、OpenGLES3,则最大额外光源数为32
  • 否则,最大额外光源数为256(即PC端使用OpenGL3.0以上版本、或其他API)

//UniversalRenderPipeline.cs
Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第3张图片
遍历场景获取所有光源数据

// ForwardLights.cs
//Setup() > SetupShaderLightConstants() > SetupAdditionalLightConstants()
循环遍历所有光源
Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第4张图片
InitializeLightConstants() > InitializeLightConstants_Common()
处理单个光源数据,获取数据保存到LightConstantBuffer中

关于SpotLight的衰减值,定义在
//UniversalRenderPipelineCore.cs
Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第5张图片
最终,将Buffer发送到GPU
在这里插入图片描述

GPU数据使用

输入的光线信息变量保存在Input.hlsl
Unity SRP 管线【第九讲:URP 点光源与聚光灯】_第6张图片
获取这些信息的函数保存在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

其中使用的函数:

  1. 获取额外光源数量(_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
}

  1. 获取光源下标后,获取光照信息
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

你可能感兴趣的:(Unity图形,unity,图形渲染,点光源,聚光灯)