Version: 6000.3
语言: 中文
URP中的自定义光照简介
在URP中使用光衰减更改光源淡入淡出的方式

在URP的着色器中渲染其他光源

编写一个渲染循环,循环访问 Forward+ 和 Forward 中的其他光源渲染路径渲染管道用于渲染图形的技术。选择不同的渲染路径会影响照明和着色的计算方式。某些渲染路径比其他路径更适合不同的平台和硬件。更多信息
请参阅术语表
在 URP 中着色器在 GPU 上运行的程序。更多信息
请参阅术语表
.

本页上的着色器示例与 Forward+ 和前向渲染一种渲染路径,用于在一个或多个通道中渲染每个对象,具体取决于影响对象的光源。光源本身也因前向渲染而异,具体取决于其设置和强度。更多信息
请参阅术语表
路径。Unity 在 Forward+ 和 Forward 渲染路径中以不同的方式处理其他光源和非主定向光。Forward+ 渲染路径对每个对象的实时光源没有限制。有关渲染路径的比较,请参阅在 URP 中选择渲染路径

将包含指令添加到着色器文件

HLSLPROGRAM块:

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"

实现光循环

  1. 在着色器通道中,添加以下内容multi_compile指令,使着色器与 Forward+ 渲染路径兼容:

    #pragma multi_compile _ _CLUSTER_LIGHT_LOOP
    
  2. 在 Forward+ 渲染路径中,LIGHT_LOOP_BEGIN宏需要InputData结构。在片段着色器中声明结构。

    InputData inputData = (InputData)0;
    inputData.positionWS = input.positionWS;
    inputData.normalWS = input.normalWS;
    inputData.viewDirectionWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
    inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
    
  3. 使用UNITY_LOOP宏来实现 Forward+ 渲染路径中非主定向光源的附加光循环:

    #if USE_CLUSTER_LIGHT_LOOP
    UNITY_LOOP for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
    {
        Light additionalLight = GetAdditionalLight(lightIndex, inputData.positionWS, half4(1,1,1,1));
        lighting += MyLightingFunction(inputData.normalWS, additionalLight);
    }
    #endif
    
  4. 使用LIGHT_LOOP_BEGINmacro 来迭代光源:

    // Additional light loop.
    uint pixelLightCount = GetAdditionalLightsCount();
    LIGHT_LOOP_BEGIN(pixelLightCount)
        Light additionalLight = GetAdditionalLight(lightIndex, inputData.positionWS, half4(1,1,1,1));
        lighting += MyLightingFunction(inputData.normalWS, additionalLight);
    LIGHT_LOOP_END
    

以下URP着色器迭代其他光源,包括非主定向光源,并在自定义光照函数中使用它们。

着色器与 Forward+ 和 Forward 渲染路径兼容。

Shader "Custom/AdditionalLights"
{
    Properties
    { 
    }
    
    SubShader
    {
        Tags 
        { 
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
        }
        
        Cull Off
        ZWrite On
        Pass
        {
            // The LightMode tag matches the ShaderPassName set in UniversalRenderPipeline.cs.
            // The SRPDefaultUnlit pass and passes without the LightMode tag are also rendered by URP
            Name "ForwardLit"
            Tags
            {
                "LightMode" = "UniversalForward"
            }
            
            HLSLPROGRAM
                        
            #pragma vertex vert
            #pragma fragment frag

            // This multi_compile declaration is required for the Forward rendering path
            #pragma multi_compile _ _ADDITIONAL_LIGHTS
            
            // This multi_compile declaration is required for the Forward+ rendering path
            #pragma multi_compile _ _CLUSTER_LIGHT_LOOP
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
            
            struct Attributes
            {
                float4 positionOS   : POSITION;
                float3 normalOS     : NORMAL;
            };
            
            struct Varyings
            {
                float4 positionCS  : SV_POSITION;
                float3 positionWS  : TEXCOORD1;
                float3 normalWS    : TEXCOORD2;
            };
            
            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.positionCS = TransformWorldToHClip(OUT.positionWS);
                OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS);
                
                return OUT;
            }
            
            float3 MyLightingFunction(float3 normalWS, Light light)
            {
                float NdotL = dot(normalWS, normalize(light.direction));
                NdotL = (NdotL + 1) * 0.5;
                return saturate(NdotL) * light.color * light.distanceAttenuation * light.shadowAttenuation;
            }
            
            // This function loops through the lights in the scene
            float3 MyLightLoop(float3 color, InputData inputData)
            {
                float3 lighting = 0;
                
                // Get the main light
                Light mainLight = GetMainLight();
                lighting += MyLightingFunction(inputData.normalWS, mainLight);
                
                // Get additional lights
                #if defined(_ADDITIONAL_LIGHTS)

                // Additional light loop for non-main directional lights. This block is specific to Forward+.
                #if USE_CLUSTER_LIGHT_LOOP
                UNITY_LOOP for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
                {
                    Light additionalLight = GetAdditionalLight(lightIndex, inputData.positionWS, half4(1,1,1,1));
                    lighting += MyLightingFunction(inputData.normalWS, additionalLight);
                }
                #endif
                
                // Additional light loop.
                uint pixelLightCount = GetAdditionalLightsCount();
                LIGHT_LOOP_BEGIN(pixelLightCount)
                    Light additionalLight = GetAdditionalLight(lightIndex, inputData.positionWS, half4(1,1,1,1));
                    lighting += MyLightingFunction(inputData.normalWS, additionalLight);
                LIGHT_LOOP_END
                
                #endif
                
                return color * lighting;
            }
            
            half4 frag(Varyings input) : SV_Target0
            {
                // The Forward+ light loop (LIGHT_LOOP_BEGIN) requires the InputData struct to be in its scope.
                InputData inputData = (InputData)0;
                inputData.positionWS = input.positionWS;
                inputData.normalWS = input.normalWS;
                inputData.viewDirectionWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
                inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
                
                float3 surfaceColor = float3(1, 1, 1);
                float3 lighting = MyLightLoop(surfaceColor, inputData);
                
                half4 finalColor = half4(lighting, 1);
                
                return finalColor;
            }
            
            ENDHLSL
        }
    }
}

其他资源

URP中的自定义光照简介
在URP中使用光衰减更改光源淡入淡出的方式