1. LUT需要求解什么
首先我们将镜面反射部分的积分分割为两个部分。
L
o
(
p
,
ω
o
)
=
∫
Ω
L
i
(
p
,
ω
i
)
d
ω
i
∗
∫
Ω
f
r
(
p
,
ω
i
,
ω
o
)
n
⋅
ω
i
d
ω
i
L_{o}\left(p, \omega_{o}\right)=\int_{\Omega} L_{i}\left(p, \omega_{i}\right) d \omega_{i} * \int_{\Omega} f_{r}\left(p, \omega_{i}, \omega_{o}\right) n \cdot \omega_{i} d \omega_{i}
Lo(p,ωo)=∫ΩLi(p,ωi)dωi∗∫Ωfr(p,ωi,ωo)n⋅ωidωi
第一部分的积分即为预滤波,将所有照到该像素点的光照求积分。
∫
Ω
L
i
(
p
,
ω
i
)
d
ω
i
\int_{\Omega} L_{i}\left(p, \omega_{i}\right) d \omega_{i}
∫ΩLi(p,ωi)dωi
第二部分需要我们知道,这个半球的光线照过来之后,有多少反射到了
ω
i
\omega_{i}
ωi 所在的方向。
L
U
T
LUT
LUT 求解的便是,在夹角
c
o
s
θ
=
N
⋅
ω
i
cos\theta = N\cdot \omega_{i}
cosθ=N⋅ωi,粗糙度为
r
o
u
g
h
n
e
s
s
roughness
roughness 下,
B
R
D
F
BRDF
BRDF 的积分是多少。
即,输入为
(
N
⋅
V
,
r
o
u
g
h
n
e
s
s
)
(N\cdot V , roughness)
(N⋅V,roughness)
输出为
∫
Ω
f
r
(
p
,
ω
i
,
ω
o
)
n
⋅
ω
i
d
ω
i
\int_{\Omega} f_{r}\left(p, \omega_{i}, \omega_{o}\right) n \cdot \omega_{i} d \omega_{i}
∫Ωfr(p,ωi,ωo)n⋅ωidωi
= ∫ Ω D F G 4 ( ω o ⋅ n ) ( ω i ⋅ n ) n ⋅ ω i d ω i = \int_{\Omega} \frac{D F G}{4\left(\omega_{o} \cdot n\right)\left(\omega_{i} \cdot n\right)} n \cdot \omega_{i} d \omega_{i} =∫Ω4(ωo⋅n)(ωi⋅n)DFGn⋅ωidωi
= ∫ Ω D G 4 ( ω o ⋅ n ) ( ω i ⋅ n ) ( F 0 + ( 1 − F 0 ) ( 1 − ω o ⋅ h ) 5 ) n ⋅ ω i d ω i =\int_{\Omega} \frac{D G}{4\left(\omega_{o} \cdot n\right)\left(\omega_{i} \cdot n\right)} \left(F_{0}+\left(1-F_{0}\right)\left(1-\omega_{o} \cdot h\right)^{5}\right) n \cdot \omega_{i} d \omega_{i} =∫Ω4(ωo⋅n)(ωi⋅n)DG(F0+(1−F0)(1−ωo⋅h)5)n⋅ωidωi
= F 0 ∫ Ω D G 4 ( ω o ⋅ n ) ( ω i ⋅ n ) ( 1 − ( 1 − ω o ⋅ h ) 5 ) n ⋅ ω i d ω i + ∫ Ω D G 4 ( ω o ⋅ n ) ( ω i ⋅ n ) ( 1 − ω o ⋅ h ) 5 n ⋅ ω i d ω i = F_{0} \int_{\Omega} \frac{D G}{4\left(\omega_{o} \cdot n\right)\left(\omega_{i} \cdot n\right)} \left(1-\left(1-\omega_{o} \cdot h\right)^{5}\right) n \cdot \omega_{i} d \omega_{i} \\ \quad\\ + \int_{\Omega} \frac{D G}{4\left(\omega_{o} \cdot n\right)\left(\omega_{i} \cdot n\right)} \left(1-\omega_{o} \cdot h\right)^{5} n \cdot \omega_{i} d \omega_{i} =F0∫Ω4(ωo⋅n)(ωi⋅n)DG(1−(1−ωo⋅h)5)n⋅ωidωi+∫Ω4(ωo⋅n)(ωi⋅n)DG(1−ωo⋅h)5n⋅ωidωi
离散化,采样根据法线分布函数D
选择路线,其中法线n
在单条路径中,法线为h
(如下函数为个人理解,与教材中的方程不符)
=
F
0
∑
c
o
u
n
t
G
(
ω
o
⋅
h
)
(
ω
i
⋅
h
)
(
1
−
(
1
−
ω
o
⋅
h
)
5
)
h
⋅
ω
i
c
o
u
n
t
+
∑
c
o
u
n
t
G
(
ω
o
⋅
h
)
(
ω
i
⋅
h
)
(
1
−
ω
o
⋅
h
)
5
h
⋅
ω
i
c
o
u
n
t
= F_{0} \frac{ \sum_{count} \frac{G}{\left(\omega_{o} \cdot h\right)\left(\omega_{i} \cdot h\right)} \left(1-\left(1-\omega_{o} \cdot h\right)^{5}\right) h \cdot \omega_{i} } { count } \\ \quad\\ + \frac{ \sum_{count} \frac{G}{\left(\omega_{o} \cdot h\right)\left(\omega_{i} \cdot h\right)} \left(1-\omega_{o} \cdot h\right)^{5} h \cdot \omega_{i} } { count }
=F0count∑count(ωo⋅h)(ωi⋅h)G(1−(1−ωo⋅h)5)h⋅ωi+count∑count(ωo⋅h)(ωi⋅h)G(1−ωo⋅h)5h⋅ωi
可以看出公式中主要需要考虑到数据有:
- G ( ω o ⋅ h ) ( ω i ⋅ h ) h ⋅ ω i = G ( ω o ⋅ h ) \frac{G}{\left(\omega_{o} \cdot h\right)\left(\omega_{i} \cdot h\right)} h \cdot \omega_{i} = \frac{G}{\left(\omega_{o} \cdot h\right)} (ωo⋅h)(ωi⋅h)Gh⋅ωi=(ωo⋅h)G
- ( 1 − ω o ⋅ h ) 5 \left(1-\omega_{o} \cdot h\right)^{5} (1−ωo⋅h)5
- 如何进行采样 如何进行采样 如何进行采样
- 如何积分 如何积分 如何积分
问题1
代码如下
这里因为H
为L
和V
的中间向量,因此GeometrySmith
可以被优化处理
// ----------------------------------------------------------------------------
float GeometrySchlickGGX(float NdotV, float roughness)
{
// note that we use a different k for IBL
float a = roughness;
float k = (a * a) / 2.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
// ----------------------------------------------------------------------------
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx1;
}
int main(){
for(i : count){
float G = GeometrySmith(H, V, L, roughness);//教材中的 H 为宏观法线 N,这里设为微观法线H
float G_Vis = G / VdotH;
}
}
问题2
float Fc = pow(1.0 - VdotH, 5.0);
问题3:如何进行采样
我们已知光线输出方向为
V
=
ω
o
V = \omega_o
V=ωo,采光防线为
L
=
ω
i
L = \omega_i
L=ωi
采光方向的计算采用在预过滤篇使用的采样方式,在以N
为周边的法线区域采样的得到H
,在通过反射计算得到L
。
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
问题4 : 如何积分
按照公式,得到每个所有采样方向积分的综合
A += (1.0 - Fc) * G_Vis;
B += Fc * G_Vis;
之后对积分求平均,返回。
A /= float(SAMPLE_COUNT);
B /= float(SAMPLE_COUNT);
return vec2(A, B);
问题5:为什么分两段存储
第二部分卷积主要求解:当入射角度为 V ⋅ N V \cdot N V⋅N ,粗糙度为 r o u g h n e s s roughness roughness 时, B R D F BRDF BRDF的平均值。
然而,不同材质应该拥有不同的反射性质,即不同的反射系数以及BRDF,但在实时渲染中,这里做了简化。
实时渲染中不同的材质的参数只包括:粗糙度,基础反射系数
因为不同材质的拥有不同的
F
0
F_0
F0,基础反射系数与材质基础颜色与金属度有关。
而反射率
F
F
F 与粗糙度
r
o
u
g
h
n
e
s
s
roughness
roughness 有关。
因此 L U T LUT LUT 表的构建不需要任何参数的输入,即与环境贴图,材质纹理,观察角度都无关,一个贴图适用于任何场景。因此在实际使用中,只需要保存该表,每次程序运行时加载就好,不需要计算得到。