漫反射光照符合兰伯特定律(Lambert's law),基本光照模型中漫反射计算公式:
\(C_{diffuse}=(C_{light} \cdot M_{diffuse})max(0,\hat{N} \cdot \hat{I} )\)
其中,\(C_{light}\) 是光源的颜色,\(M_{diffuse}\) 是材质的漫反射颜色,\(\hat{N}\) 是单位化的表面法线,\(\hat{I}\) 是指向光源的单位向量。需要注意的是,需要防止法线和光源方向点乘的结果为负值,为此,使用取最大值函数来将其截取到0,这可以防止物体被从后面的光源照亮。
HLSL:
Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level" {
Properties {
_BaseColor ("BaseColor", Color) = (1, 1, 1, 1)
}
SubShader {
Tags {
"RenderType"="Opaque"
"RenderPipeline"="UniversalPipeline"
}
Pass {
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _BaseColor;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
half3 normal:NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
half3 color:COLOR;
};
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
half3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
float3 worldNormal = TransformObjectToWorldNormal(input.normal);
Light mainLight = GetMainLight();
half3 diffuse = mainLight.color * _BaseColor.rgb * saturate(dot(worldNormal, mainLight.direction));
// 也可以直接使用LightingLambert方法
//half3 diffuse = _BaseColor.rgb * LightingLambert(mainLight.color, mainLight.direction, worldNormal);
output.color = ambient + diffuse;
return output;
}
half4 frag(Varyings input): SV_Target
{
return half4(input.color, 1.0);
}
ENDHLSL
}
}
}