GameTech/URP 渲染实战
源码 / Ch18/Ch18Common.hlsl
Ch18/Ch18Common.hlsl
// 第 18 章公共函数:一个够用的“简易光照”,以及菲涅尔、哈希等小工具。
// 本章重点是效果本身,光照只用主光 + 阴影 + 球谐环境光 + Blinn-Phong 高光,
// 完整 PBR 见第 10、11 章;需要时可以把 SimpleLighting 换成 UniversalFragmentPBR。
#ifndef COOKBOOK_CH18_COMMON_INCLUDED
#define COOKBOOK_CH18_COMMON_INCLUDED

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

half3 SimpleLighting(half3 albedo, float3 positionWS, half3 normalWS, half smoothness)
{
    float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
    Light mainLight = GetMainLight(shadowCoord);
    half3 viewWS = GetWorldSpaceNormalizeViewDir(positionWS);

    half NdotL = saturate(dot(normalWS, mainLight.direction));
    half3 halfDir = SafeNormalize(mainLight.direction + viewWS);
    // 光滑度 0~1 映射到高光指数 2~2048,乘 smoothness 让粗糙表面的高光更暗
    half specPow = exp2(10.0 * smoothness + 1.0);
    half spec = pow(saturate(dot(normalWS, halfDir)), specPow) * smoothness * NdotL;

    half atten = mainLight.distanceAttenuation * mainLight.shadowAttenuation;
    half3 direct = (albedo * NdotL + spec) * mainLight.color * atten;
    half3 ambient = SampleSH(normalWS) * albedo;
    return direct + ambient;
}

// 经验菲涅尔:视线与法线越垂直(轮廓处)值越大。power 越大,亮边越窄。
half FresnelRim(half3 normalWS, half3 viewWS, half power)
{
    return pow(1.0h - saturate(dot(normalWS, viewWS)), power);
}

// 简单的 1D/2D 哈希,用来做闪烁、故障条等随机数
float Hash11(float p)
{
    p = frac(p * 0.1031);
    p *= p + 33.33;
    p *= p + p;
    return frac(p);
}

float Hash21(float2 p)
{
    float3 p3 = frac(float3(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return frac((p3.x + p3.y) * p3.z);
}

#endif