【个人学习记录-GPU实例化草地渲染多光源支持】

下文是URP的Light.hlsl文件中用于计算Forward Add光的代码片段,和build-in不同的是,前向渲染的额外光照不再需要写进第二个Pass里了。

概括来说的话,代码中首先使用GetAdditionalLightsCount获取片元额外光的数量,LIGHT_LOOP_BEGIN……LIGHT_LOOP_END遍历每个额外光,GetAdditionalLight获取额外光对象,并将光加进片元中。

#if defined(_ADDITIONAL_LIGHTS)
    uint pixelLightCount = GetAdditionalLightsCount();

    #if USE_FORWARD_PLUS
    for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
    {
        FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK

        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);

#ifdef _LIGHT_LAYERS
        if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
        {
            lightingData.additionalLightsColor += LightingPhysicallyBased(brdfData, brdfDataClearCoat, light,
                                                                          inputData.normalWS, inputData.viewDirectionWS,
                                                                          surfaceData.clearCoatMask, specularHighlightsOff);
        }
    }
    #endif

    LIGHT_LOOP_BEGIN(pixelLightCount)
        Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);

#ifdef _LIGHT_LAYERS
        if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
#endif
        {
            lightingData.additionalLightsColor += LightingPhysicallyBased(brdfData, brdfDataClearCoat, light,
                                                                          inputData.normalWS, inputData.viewDirectionWS,
                                                                          surfaceData.clearCoatMask, specularHighlightsOff);
        }
    LIGHT_LOOP_END
    #endif

我预想按照这个大致流程给GPU实例化草地加入额外光照即可,但实际因为GPU实例化的特殊性,渲染管线无法知道具体的每棵草是否受到额外的光,即USE_FORWARD_PLUS这个宏是否开启,可以看到下文中如果USE_FORWARD_PLUS未开启,那GetAdditionalLight和GetAdditionalLightsCount就无法输出正确的数据:

int GetAdditionalLightsCount()
{
#if USE_FORWARD_PLUS
    return 0;
#else
    return int(min(_AdditionalLightsCount.x, unity_LightData.y));
#endif
}
Light GetAdditionalLight(uint i, float3 positionWS)
{
#if USE_FORWARD_PLUS
    int lightIndex = i;
#else
    int lightIndex = GetPerObjectLightIndex(i);
#endif
    return GetAdditionalPerObjectLight(lightIndex, positionWS);
}

还有一个不能忽略的点是GetAdditionalLightsCount中的unity_LightData.y也不是正确的数字,gpu实例草中的位置信息管线本身是不知道的,因此这个值可以替换成我们自定的一个数字或者让脚本计算额外光数量_AddLightCount,避免额外光数量一直识别为0,也避免shader中额外光的遍历循环产生过多空转,这样一来,GPU实例化中的多光源支持就可以正常工作了:

#if _ADDITIONAL_LIGHTS
    uint pixelLightCount = int(min(_AdditionalLightsCount.x, _AddLightCount));
    half3 viewDir = normalize(_WorldSpaceCameraPos - input.positionWS);
LIGHT_LOOP_BEGIN(pixelLightCount)
    Light light = GetAdditionalPerObjectLight(lightIndex, input.positionWS);
    color.rgb += ApplySingleDirectLight(light, normalWS, viewDir, diffuseColor.xyz, input.positionOS.y);
LIGHT_LOOP_END
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值