本项目为games 101结课项目/This project is driven from games101 course.
三维包围盒,将图元包围到与坐标轴平行的包围盒,快速判断求交
boundary volume hierarchy, 基于模型而非空间.
构建:
- 找出所有对象包围盒的并
- 按最长的维度排序,从中间划分成两个子集(包围盒可能相交)
- 递归构建子集
- 当对象数量到达一定限制时停止,并将对象存在叶子上
求交:
- 与包围盒求交,如果失败则返回
- 如果是叶子,则与对象求交
- 递归与左右儿子求交,返回t(交点时间)最小的.
材质实现了漫反射和光滑表面(颜色与法向量夹角和高光项相关)
漫反射: 在单位球面上随机取一点
光滑:
根据入射和出射方向算贡献
漫反射:
出射,入射方向和法向量算概率密度函数
BRDF(Bidirectional Reflectance Distribution Function)双向反射分布函数
其中f是BRDF,l是入射光方向,v是观察方向,也就是想要的反射光方向
反射方程: 针对一个着色点,积分所有方向的输入源的BRDF
渲染方程: 反射方程+物体本身发光
求解:
蒙特卡洛积分
但求和复杂度依旧很大,且为递归函数难以求解,采用俄罗斯轮盘赌,只以一定概率射出一条光线,结果除以概率.
期望是正确的但会出现噪声.
定义在material中
对光源采样:
光源较小时,随机射出光线很难击中光线,直接在光源上采样,看能否击中物体.
shadeOnLight: ray
interset(ray)
if (!hit)
return backgroundColor
if (hitLight)
return lightColor
// calculate direct light
light,pdf_light = sampleLight()
if (light can hit obj)
L_dir = L_i * f_r * cos(theta) * cos(theta') / |x' - p|^2 / pdf_light
else
no direct light Color
// contribution from other reflectors
Test Russian Roulette with probability P_RR
wi = sample(Obj)
interset(wi)
if (hit a non-emitting object at q)
L_indir = shadeOnLight(-wi) * eval() * cos(theta) / pdf() / P_RR
return L_dir + L_indir
对BRDF采样:
对于一些特殊的材质(粗糙),对BRDF更能显示它的性质(粗糙表面对于光源采样时,噪点会比较多,因为就算光线照到表面,也会因为pdf低而不明显,采样BRDF能在物体表面得到充分采样,不会产生大量噪点)
shadeOnBRDF: ray
interset(ray)
if (!hit)
return backgroundColor
if (hitLight)
return lightColor
Test Russian Roulette with probability P_RR
wi = sample(Obj)
interset(wi)
if (hit light) {
Lo = lightColor
} else if (hit something) {
Lo = shadeOnBRDF(wi)
}
Lo = Lo * eval() * cos(theta) / P_RR / pdf()
return Lo
怎样混合?
估算对方的概率(通过面积)
BRDF: pdf() / obj.area()
Light:
more about mis