GameTech/URP 渲染实战
源码 / shaders/Ch11/MyPBR_Input.glsl
shaders/Ch11/MyPBR_Input.glsl
// MyPBR 的材质输入:属性 CBUFFER、贴图声明、从贴图读出“表面参数”。
// 这里只做“读数据”,不做任何光照计算。(GLSL 版,对应 Ch11/MyPBR_Input.hlsl)
#ifndef COOKBOOK_MYPBR_INPUT_INCLUDED
#define COOKBOOK_MYPBR_INPUT_INCLUDED

// 所有材质属性(贴图除外)都放进 UnityPerMaterial,且每个 Pass 看到的布局完全一致,
// 这是 SRP Batcher 兼容的硬条件。贴图本身不进 CBUFFER,但 _ST 要进。
// (WebGL 没有 SRP Batcher,这里都是普通 uniform)
uniform vec4  _BaseMap_ST;
uniform vec4  _BaseColor;
uniform float _Metallic;
uniform float _Smoothness;
uniform float _OcclusionStrength;
uniform float _BumpScale;
uniform vec4  _EmissionColor;
uniform float _Cutoff;
uniform float _EnergyCompensation;   // 0 = 只算单次散射,1 = 加多次散射能量补偿
uniform float _SpecularOcclusion;    // 0 = 关,1 = 用 AO 推算镜面遮蔽

uniform sampler2D _BaseMap;
uniform sampler2D _MaskMap;      // R 金属度  G AO  A 光滑度(与配套贴图约定一致)
uniform sampler2D _BumpMap;
uniform sampler2D _EmissionMap;
uniform sampler2D _DFGLut;       // 程序生成的环境 BRDF 查找表(RG = A, B),贴图自身是双线性 + Clamp
// HLSL 版里 Mask 与自发光借用 _BaseMap 的采样器以节省采样器槽位;GLSL 的 sampler2D 自带采样状态,没有这个问题。

// 表面参数:全部在“线性空间、物理含义明确”的单位下
struct MySurface
{
    vec3  albedo;               // 基础色(金属时就是 F0 的颜色)
    float alpha;
    float metallic;
    float perceptualRoughness;  // 感知粗糙度 = 1 - smoothness,美术直接调的那个值
    float occlusion;            // 材质 AO(只影响间接光)
    vec3  normalTS;             // 切线空间法线
    vec3  emission;
};

#ifdef FRAGMENT
MySurface MySampleSurface(vec2 uv)
{
    MySurface s;
    vec4 base = texture(_BaseMap, uv) * _BaseColor;
    s.albedo = base.rgb;
    s.alpha  = base.a;
#if defined(_ALPHATEST_ON)
    if (s.alpha - _Cutoff < 0.0) discard;
#endif

#if defined(_MASKMAP)
    vec4 mask = texture(_MaskMap, uv);
    // (smooth 是 GLSL 的关键字(插值限定符),变量改名为 smoothness)
    s.metallic   = mask.r;                       // 有 Mask 时金属度完全由贴图决定(与 URP Lit 一致)
    float smoothness = mask.a * _Smoothness;         // 光滑度 = 贴图 × 滑条,滑条当总强度用
    s.occlusion  = LerpWhiteTo(mask.g, _OcclusionStrength);
#else
    s.metallic   = _Metallic;
    float smoothness = _Smoothness;
    s.occlusion  = 1.0;
#endif
    s.perceptualRoughness = 1.0 - smoothness;

#if defined(_NORMALMAP)
    s.normalTS = UnpackNormalScale(texture(_BumpMap, uv), _BumpScale);
#else
    s.normalTS = vec3(0, 0, 1);
#endif

#if defined(_EMISSION)
    s.emission = texture(_EmissionMap, uv).rgb * _EmissionColor.rgb;
#else
    s.emission = vec3(0.0);
#endif
    return s;
}
#endif

#endif