如何在URP里面获取到额外光源光照?
感觉相对URP下灵活方便,代码也很简洁
之前流程都是固定的,比如前向渲染还得写 ForwadBase ForwadAdd之类的。。
流程如下:
1.确保管线配置开启
2.代码中处理
//多光源宏定义
#pragma shader_feature _AdditionalLights
//片段着色器
half4 frag(Varyings i) : SV_Target
{
#ifdef _AdditionalLights
//获取额外灯的数量
// 不超过 Lighing->PerObjectLimit
int addLightCount = GetAdditionalLightsCount();
for (int lightIndex = 0; lightIndex < addLightCount; ++lightIndex)
{
// 获取额外光源信息
Light addLight = GetAdditionalLight(lightIndex, i.positionWS);
...
}
#endif
}
代码实现如下:
LightingLambert
和 LightingSpecular
是内置方法如下:
//文件:
// Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl
///
// Lighting Functions //
///
half3 LightingLambert(half3 lightColor, half3 lightDir, half3 normal)
{
half NdotL = saturate(dot(normal, lightDir));
return lightColor * NdotL;
}
half3 LightingSpecular(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specular, half smoothness)
{
float3 halfVec = SafeNormalize(float3(lightDir) + float3(viewDir));
half NdotH = half(saturate(dot(normal, halfVec)));
half modifier = pow(NdotH, smoothness);
half3 specularReflection = specular.rgb * modifier;
return lightColor * specularReflection;
}
完整代码:
Shader "Custom/TA_URP/MultiLight"
{
Properties
{
_Color("Color", Color)= (1,1,1,1)
_BaseMap("BaseMap", 2D) = "white" {}
_SpecularColor("SpecularColor(RGB) Smoothness(A)", Color) = (1,1,1,1)
[HDR]_EmissionColor("EmissionColor", Color) = (0,0,0,1)
[Toggle(_AdditionalLights)] _AddLights ("AddLights", Float) = 1
}
SubShader
{
Tags
{
"RenderPipeline"="UniversalPipeline"
"RenderType"="Opaque"
"Queue"="Geometry"
}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
//多光源宏定义
#pragma shader_feature _AdditionalLights
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float3 positionOS : POSITION;
float2 uv : TEXCOORD0;
float3 normalOS : NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float3 positionWS : TEXCOORD2;
};
CBUFFER_START(UnityPerMaterial)
half4 _Color;
float4 _BaseMap_ST;
half4 _SpecularColor;
half4 _EmissionColor;
CBUFFER_END
SAMPLER(sampler_BaseMap);
TEXTURE2D(_BaseMap);
Varyings vert(Attributes v)
{
Varyings o;
o.positionCS = TransformObjectToHClip(v.positionOS);
o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
o.normalWS = TransformObjectToWorldNormal(v.normalOS);
o.positionWS = TransformObjectToWorld(v.positionOS);
return o;
}
half4 frag(Varyings i) : SV_Target
{
half3 baseCol = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv).rgb;
half3 albedo = baseCol * _Color.rgb;
half3 ambient = _GlossyEnvironmentColor.rgb;
Light mainLight = GetMainLight();
half3 mainLightCol = mainLight.color;
half3 mainLightDir = mainLight.direction;
half3 normalWS = normalize(i.normalWS);
half3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.positionWS);
half3 diffuse = LightingLambert(mainLightCol, mainLightDir, normalWS);
// 计算其他光源
#ifdef _AdditionalLights
//获取额外灯的数量
// 不超过 Lighing->PerObjectLimit
int addLightCount = GetAdditionalLightsCount();
for (int lightIndex = 0; lightIndex < addLightCount; ++lightIndex)
{
Light addLight = GetAdditionalLight(lightIndex, i.positionWS);
//处理衰减
half3 addLightColAtten = addLight.color * addLight.distanceAttenuation;
// 叠加光照
diffuse += LightingLambert(addLightColAtten, addLight.direction, normalWS);
}
#endif
//把0-1 映射到一定范围
half smoothness = exp(10 * _SpecularColor.a + 1);
half3 specular = LightingSpecular(mainLightCol, mainLightDir, normalWS,
viewDir, _SpecularColor, smoothness);
//emission
half3 emission = _EmissionColor.rgb;
return half4(albedo * (ambient + diffuse + specular) + emission, 1);
}
ENDHLSL
}
}
FallBack "Hidden/Shader Graph/FallbackError"
}
效果如图: