Physically Based Rendering
Table of Contents
图形学一直是我最喜欢的方向之一(虽然研究热度早已不及当年),无论是从最后的视觉效果还是实现的加速过程,均满足我对 CS 学科的美学追求。目前许多声音表示 Graphics 的研究陷入瓶颈,我依然认为这是一个“没有死”的方向:针对特定的渲染场景设计相应的软硬件,应该还有可以挖的地方。pbrt 是渲染领域的经典教材,学习它一来了解一下相关算法(和相应的计算需求),二来学习面向对象的程序设计。
这本书作者很有开源精神,教材和代码均可以免费得到:
Introduction
Literate Programming
此节主要介绍文学编程,一种被广为吐槽的编程范式。它可以看作一种宏,把一段函数分成不同的逻辑单元,每个单元用文字描述其功能,其展开则是一段具体的代码块。可以预见的是写代码的工作量会加大,而且不带参数的话,感觉有支离破碎之感(在 <<Swap parameter values>>
中参数是怎么来的?)。
<<Function Definitions>>+= void complexFunc(int x, int y, double *values) { <<Check validity of arguments>> if (x < y) { <<Swap parameter values>> } <<Do precomputation before loop>> <<Loop through and update \mono{values} array>> }
Photorealistic Rendering and the Ray-Tracing Algorithm
这一章主要是用数学定义光线追踪这个问题,一个光线追踪系统建模如下内容:
- camera
- ray-object intersection
- light sources
距离光源越远接收到的光强越低,设距光源半径为 \(r\) ,则单位面片接受到的光强正比于 \(1/r^2\) 。
如果面片与光线到该位置有一定的夹角 \(\theta\) , 则单位面片的能量为:
\[ dE = \frac{\Psi \cos \theta}{4\pi r^2}\]
\(\Psi\) 为光源本身的强度。
- visibility
- surface scattering
光线遇到物体的表面可能会反射,如何计算反射的强度:
if light is not blocked: incident_light = light.L(point) amount_reflected = surface.BRDF(hit_point, camera_vector, light_vector) L += amount_reflected * incident_light
其中 BRDF 是 bidirectional reflectance distribution function 代表某一个位置 \(p\) 对于入射角 \(\omega_i\) 和反射角 \(\omega_o\) 的反射能量: \(f_r(p, \omega_i, \omega_o)\) 。 \(L\) 代表 radiance,描述光的一种单位。
BRDF 可以拓展到折射(BTDF),散射(BSDF,更通用)等情形。
- indirect light transport
渲染方程 \[ L_o(p, \omega_o) = L_e(p, \omega_o) + \int_{S^2} f(p, \omega_o, \omega_i) L_i(p, \omega_i) |\cos \theta_i | d \omega_i\]
其中 \(S_2\) 为 \(p\) 附近的一个球体,$Le$则表示 \(p\) 处发出的光。
- ray propagation
System design
pbrt 的执行顺序
- 第一阶段为解析场景,包括几何形状,材质,光照,相机位置,算法参数。
- 解析的结果是一个
Scene
类和一个Integrator
类。- Scene 包含场景的描述
- Integrator 实现渲染算法(计算上一节中提到的积分)。
- 第二阶段是渲染的循环,调用
Integrator::Render()
方法。SamplerIntegrator
使用蒙特卡洛方法。