【基于物理的渲染(3)】基于图片的渲染

本文最后更新于 2025年5月8日 晚上

【基于物理的渲染(3)】基于图片的渲染

上述 CookTorrance 公式中还缺少环境光的处理,在 PBR 中环境光是用 IBL 实现的。

IBL 中由于光来自一个完整的球面,因此需要对球面积分计算,但这样工作量太大了。考虑到物体表面受到的环境光不会改变,因此可以提前预处理,将部分光照提前计算存放到环境贴图中。因此对于间接光,不能直接使用直接光的反射率方程。

在Unity中:预计算的漫射光使用SH存储;镜射光使用立方体纹理存储,并根据不同粗糙度存储了多份放在了mipmap中。

漫射光最简单,从SH中取出的就是辐射率,直接乘上漫射的反射率即可。镜射光则需要根据不同的粗糙度采样不同mipmap的立方体贴图来获得进行一定处理后的辐射率,然后乘上反射衰减和高光颜色(反射光)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
float3 GlobalIlluminationDiffuse_Unity(float3 n, float3 diffuse)
{
half3 radiance = SampleSH(n);

return diffuse * radiance;
}

float3 GlobalIlluminationSpecular_Unity(float3 n, float3 v, float3 specular, float metallic, float smoothness)
{
float perceptualRoughness = 1 - smoothness;
float roughness = max(pow(1 - smoothness, 2),HALF_MIN_SQRT);
float roughness2 = roughness * roughness;

float3 radiance = GlossyEnvironmentReflection(reflect(-v, n), perceptualRoughness, 1);

//反射衰减(确保能量守恒)
float surfaceReduction = 1.0 / (roughness2 + 1.0);

//镜射光反射率
float fresnel = Pow4(1.0 - saturate(dot(n, v))); //菲涅尔效应导致光全反射
float ks = lerp(0.04, 1, metallic); //镜射率
float3 finalSpecular = lerp(specular, saturate(ks + smoothness), fresnel);

return finalSpecular * radiance * surfaceReduction;
}
HLSL

【基于物理的渲染(3)】基于图片的渲染
https://bdffzi-blog.pages.dev/posts/1910260985.html
作者
BDFFZI
发布于
2025年5月7日
许可协议