包含此页的版本:
不含此页的版本:
编写一个渲染循环,循环访问 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"
在着色器通道中,添加以下内容multi_compile指令,使着色器与 Forward+ 渲染路径兼容:
#pragma multi_compile _ _CLUSTER_LIGHT_LOOP
在 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);
使用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
使用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
}
}
}