我有一个呈现器,其中BxDF接口是Sample()、PDF()和Eval()。Lambertian运行良好,我相信我已经为基于另一个用户的问题的GGX正确地实现了Eval,但是我很难找到一个我能理解的资源,它解释了如何为GGX发行版生成样本,然后计算相应的PDF。
我已经找到了一些原始论文,但与Lambert不同的是,抽样和PDF似乎基于球面坐标(我并不真正理解-- 3D向量是关于我的数学极限的)。
我非常想知道如何将“一种简单、准确的可见范数GGX分布的抽样程序”转换成单独的Sample()和PDF()函数。
这是我为兰伯特准备的:
type Lambert struct {
R, G, B float64
}
func (l Lambert) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {
return normal.RandHemiCos(rnd)
}
func (l Lambert) PDF(in, normal geom.Direction) float64 {
return in.Dot(normal) * math.Pi
}
func (l Lambert) Eval(in, out, normal geom.Direction) rgb.Energy {
return rgb.Energy{l.R, l.G, l.B}.Scaled(math.Pi * in.Dot(normal))
}这是我正在为Microfacets所做的工作:
func (m Microfacet) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {
// TODO: better sampling
return normal.RandHemi(rnd)
}
func (m Microfacet) PDF(in, normal geom.Direction) float64 {
// TODO: PDF that matches a better sampling distribution
return 1 / (2 * math.Pi)
}
// https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong
// https://schuttejoe.github.io/post/ggximportancesamplingpart2/
func (m Microfacet) Eval(in, out, normal geom.Direction) rgb.Energy {
F := schlick2(in, normal, m.F0.Mean()) // The Fresnel function
D := ggx(in, out, normal, m.Roughness) // The NDF (Normal Distribution Function)
G := smithGGX(out, normal, m.Roughness) // The Geometric Shadowing function
r := (F * D * G) / (4 * normal.Dot(in) * normal.Dot(out))
return m.F0.Scaled(r)
}GGX BSDF依赖于我还实现的几个物理函数:
// Schlick's approximation of Fresnel
func schlick2(in, normal geom.Direction, f0 float64) float64 {
return f0 + (1-f0)*math.Pow(1-normal.Dot(in), 5)
}
// GGX Normal Distribution Function
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
func ggx(in, out, normal geom.Direction, roughness float64) float64 {
m := in.Half(out)
a := roughness * roughness
nm2 := math.Pow(normal.Dot(m), 2)
return (a * a) / (math.Pi * math.Pow(nm2*(a*a-1)+1, 2))
}
// Smith geometric shadowing for a GGX distribution
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
func smithGGX(out, normal geom.Direction, roughness float64) float64 {
a := roughness * roughness
nv := normal.Dot(out)
return (2 * nv) / (nv + math.Sqrt(a*a+(1-a*a)*nv*nv))
}发布于 2018-05-23 14:09:10
通过来自几个人的帮助&引用和重新引用评论的urls,我成功地获得了一个具有匹配PDF的抽样方案,它处理从完美的镜面到粗糙度= 1的所有东西。

// Cook-Torrance microfacet model
type Microfacet struct {
F0 rgb.Energy
Roughness float64
}
// https://schuttejoe.github.io/post/ggximportancesamplingpart1/
// https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/
func (m Microfacet) Sample(wo geom.Direction, rnd *rand.Rand) geom.Direction {
r0 := rnd.Float64()
r1 := rnd.Float64()
a := m.Roughness * m.Roughness
a2 := a * a
theta := math.Acos(math.Sqrt((1 - r0) / ((a2-1)*r0 + 1)))
phi := 2 * math.Pi * r1
x := math.Sin(theta) * math.Cos(phi)
y := math.Cos(theta)
z := math.Sin(theta) * math.Sin(phi)
wm := geom.Vector3{x, y, z}.Unit()
wi := wo.Reflect2(wm)
return wi
}
// https://schuttejoe.github.io/post/ggximportancesamplingpart1/
// https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/
// https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations#From_Cartesian_coordinates_2
func (m Microfacet) PDF(wi, wo geom.Direction) float64 {
wg := geom.Up
wm := wo.Half(wi)
a := m.Roughness * m.Roughness
a2 := a * a
cosTheta := wg.Dot(wm)
exp := (a2-1)*cosTheta*cosTheta + 1
D := a2 / (math.Pi * exp * exp)
return (D * wm.Dot(wg)) / (4 * wo.Dot(wm))
}
// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
func (m Microfacet) Eval(wi, wo geom.Direction) rgb.Energy {
wg := geom.Up
wm := wo.Half(wi)
if wi.Y <= 0 || wi.Dot(wm) <= 0 {
return rgb.Energy{0, 0, 0}
}
F := fresnelSchlick(wi, wg, m.F0.Mean()) // The Fresnel function
D := ggx(wi, wo, wg, m.Roughness) // The NDF (Normal Distribution Function)
G := smithGGX(wo, wg, m.Roughness) // The Geometric Shadowing function
r := (F * D * G) / (4 * wg.Dot(wi) * wg.Dot(wo))
return m.F0.Scaled(r)
}https://computergraphics.stackexchange.com/questions/7656
复制相似问题