参数曲面把参数曲线从一个参数推广到两个参数 ( u , v ) (u,v) ( u , v ) ,由少量控制点定义,运行时细分成任意多个三角形,是质量与速度之间的天然权衡:三角形多则着色和轮廓更好。矩形定义域的是贝塞尔面片(张量积曲面),三角形定义域的是贝塞尔三角形,后者是 PN 三角形和 Phong 细分的基础。
为什么用参数曲面(17.2 节)
细分 (tessellation):在若干参数位置求值并连成三角形逼近曲面,因为硬件擅长渲染三角形。
可以只动画控制点再细分,比直接动画大三角网格便宜。
贝塞尔面片(17.2.1 节)
从双线性插值出发:四点 a , b , c , d \mathbf{a},\mathbf{b},\mathbf{c},\mathbf{d} a , b , c , d ,
p ( u , v ) = ( 1 − u ) ( 1 − v ) a + u ( 1 − v ) b + ( 1 − u ) v c + u v d \mathbf{p}(u,v)=(1-u)(1-v)\mathbf{a}+u(1-v)\mathbf{b}+(1-u)v\mathbf{c}+uv\mathbf{d} p ( u , v ) = ( 1 − u ) ( 1 − v ) a + u ( 1 − v ) b + ( 1 − u ) v c + uv d
与纹理双线性过滤同型,是最简单的非平面参数曲面;定义域为 [ 0 , 1 ] × [ 0 , 1 ] [0,1]\times[0,1] [ 0 , 1 ] × [ 0 , 1 ] 的曲面称为面片 (patch)。
n n n 次面片有 ( n + 1 ) 2 (n+1)^2 ( n + 1 ) 2 个控制点 p i , j \mathbf{p}_{i,j} p i , j ,de Casteljau 推广为反复双线性插值;Bernstein 形式
p ( u , v ) = ∑ i = 0 m ∑ j = 0 n B i m ( u ) B j n ( v ) p i , j \mathbf{p}(u,v)=\sum_{i=0}^{m}\sum_{j=0}^{n}B_i^m(u)B_j^n(v)\,\mathbf{p}_{i,j} p ( u , v ) = ∑ i = 0 m ∑ j = 0 n B i m ( u ) B j n ( v ) p i , j
两方向次数可以不同(m × n m\times n m × n )。固定 v v v 时它就是一条贝塞尔曲线。
性质:插值四个角控制点;每条边界是由边界控制点决定的 n n n 次贝塞尔曲线,角点处的两条切线由边界曲线给出;位于控制点凸包内;先变换控制点再求值等价且更快;移动一个控制点主要影响其附近。
偏导数次数在求导方向降一:
∂ p ∂ u = m ∑ j = 0 n ∑ i = 0 m − 1 B i m − 1 ( u ) B j n ( v ) [ p i + 1 , j − p i , j ] \frac{\partial\mathbf{p}}{\partial u}=m\sum_{j=0}^{n}\sum_{i=0}^{m-1}B_i^{m-1}(u)B_j^n(v)[\mathbf{p}_{i+1,j}-\mathbf{p}_{i,j}] ∂ u ∂ p = m ∑ j = 0 n ∑ i = 0 m − 1 B i m − 1 ( u ) B j n ( v ) [ p i + 1 , j − p i , j ]
v v v 方向同理;未归一化法线 n = ∂ p ∂ u × ∂ p ∂ v \mathbf{n}=\dfrac{\partial\mathbf{p}}{\partial u}\times\dfrac{\partial\mathbf{p}}{\partial v} n = ∂ u ∂ p × ∂ v ∂ p 。
有理贝塞尔面片在分子分母中各加权重 w i , j w_{i,j} w i , j ,增加自由度。
贝塞尔三角形(17.2.2 节)
三角形定义域反而比矩形复杂。n n n 次三角形每边 n + 1 n+1 n + 1 个控制点 p i j k \mathbf{p}_{ijk} p ij k (i + j + k = n i+j+k=n i + j + k = n ),总数 ( n + 1 ) ( n + 2 ) 2 \dfrac{(n+1)(n+2)}{2} 2 ( n + 1 ) ( n + 2 ) 。
用重心坐标 ( u , v ) (u,v) ( u , v ) ,w = 1 − u − v w=1-u-v w = 1 − u − v 。de Casteljau:
p i , j , k l = u p i + 1 , j , k l − 1 + v p i , j + 1 , k l − 1 + ( 1 − u − v ) p i , j , k + 1 l − 1 \mathbf{p}^l_{i,j,k}=u\,\mathbf{p}^{l-1}_{i+1,j,k}+v\,\mathbf{p}^{l-1}_{i,j+1,k}+(1-u-v)\,\mathbf{p}^{l-1}_{i,j,k+1} p i , j , k l = u p i + 1 , j , k l − 1 + v p i , j + 1 , k l − 1 + ( 1 − u − v ) p i , j , k + 1 l − 1
Bernstein 形式 p ( u , v ) = ∑ i + j + k = n B i j k n ( u , v ) p i j k \mathbf{p}(u,v)=\sum_{i+j+k=n}B^n_{ijk}(u,v)\mathbf{p}_{ijk} p ( u , v ) = ∑ i + j + k = n B ij k n ( u , v ) p ij k ,其中
B i j k n ( u , v ) = n ! i ! j ! k ! u i v j ( 1 − u − v ) k B^n_{ijk}(u,v)=\frac{n!}{i!\,j!\,k!}u^iv^j(1-u-v)^k B ij k n ( u , v ) = i ! j ! k ! n ! u i v j ( 1 − u − v ) k
插值三个角点,每条边界是贝塞尔曲线,位于凸包内。Unreal、Unity、Lumberyard 等引擎支持基于它的 Phong 细分和 PN 三角形。
面片拼接的连续性(17.2.3 节)
两个双三次面片(各 4×4 控制点 a i j a_{ij} a ij 、b i j b_{ij} b ij ):
C 0 C^0 C 0 :共享边界控制点 a 3 j = b 0 j a_{3j}=b_{0j} a 3 j = b 0 j 。
C 1 C^1 C 1 :对每个 j j j ,a 2 j a_{2j} a 2 j 、b 0 j b_{0j} b 0 j 、b 1 j b_{1j} b 1 j 共线,且比例相同 ∥ a 2 j − b 0 j ∥ = k ∥ b 0 j − b 1 j ∥ \lVert a_{2j}-b_{0j}\rVert=k\lVert b_{0j}-b_{1j}\rVert ∥ a 2 j − b 0 j ∥ = k ∥ b 0 j − b 1 j ∥ ,k k k 对所有 j j j 相同。
四片共享一个角时,角点周围九个控制点必须共面并构成双线性面片;只要求角点处 G 1 G^1 G 1 时共面即可,占用更少自由度。
取舍:C 1 C^1 C 1 是跨边界纹理好看的必要条件;反射和着色有 G 1 G^1 G 1 即可接受,C 1 C^1 C 1 以上更好。由大量贝塞尔曲面构造复杂物体时很难保证所有边界的连续性,这是转向 细分曲线与细分曲面 的原因之一。
B 样条曲面(17.2.6 节)
s n ( u , v ) = ∑ k ∑ l c k , l β n ( u − k ) β n ( v − l ) s^n(u,v)=\sum_k\sum_l c_{k,l}\,\beta^n(u-k)\,\beta^n(v-l) s n ( u , v ) = ∑ k ∑ l c k , l β n ( u − k ) β n ( v − l )
双三次 B 样条面片需要 4×4 控制点,实际曲面位于最内侧 2×2 控制点之内。用于纹理过滤时它是高度场,c k , l c_{k,l} c k , l 是一维高度。双三次 B 样条面片是 Catmull-Clark 细分曲面的基础。
GEA 的视角:场景几何的三种表示(卷 II 11.3.5)
广义表面 :光的有趣行为大多发生在不同材质的边界上,包括实体表面和不同透光介质的界面,GEA 统称为广义表面,游戏开发者叫"场景几何"。场景可描述为一组表面加上每个表面所围子体积的材质;烟、雾这类没有明确边界的参与介质也能建模为有边界的体积,让材质属性在体积内变化(表面透明、越往里越浑浊)(卷 II 11.3.5,见 参与介质与体积散射 )。
解析曲面 :曲面是嵌入三维空间的二维流形,有时可解析表示,如球面 ( x − c ) ⋅ ( x − c ) = r 2 (\mathbf{x}-\mathbf{c})\cdot(\mathbf{x}-\mathbf{c})=r^2 ( x − c ) ⋅ ( x − c ) = r 2 。可渲染几何大多无法解析描述,但解析球和平面在引擎中用途很多:碰撞体、包围体、触发区,以及光线追踪引擎的简单测试用例(卷 II 11.3.5.1,见 几何图元的表示 )。
参数曲面 :影视行业常用由少量控制点定义的二维样条矩形面片表示曲面,包括贝塞尔曲面(如三次面片)、NURBS、贝塞尔三角形和 N-patch(法线面片);GEA 把用面片建模比作用小块布或纸浆糊雕像(卷 II 11.3.5.2)。
细分曲面 :Pixar 的 RenderMan 等高端影视渲染器用细分曲面定义形状,控制多边形可用 Catmull-Clark 算法不断细分,通常细分到每个多边形小于一个像素;最大好处是无论相机多近都能继续细分,轮廓边永远不会显得有棱角(见 细分曲线与细分曲面 )。
游戏传统上用三角网格 ,原因见 三角形带、扇与索引网格 中的 GEA 部分。
PBRT 的视角:双线性面片与曲面微分几何(PBRT 4e 6.2、6.6)
双线性面片
四个顶点不必共面:f ( u , v ) = ( 1 − u ) ( 1 − v ) p 00 + u ( 1 − v ) p 10 + ( 1 − u ) v p 01 + u v p 11 f(u,v)=(1-u)(1-v)\mathbf p_{00}+u(1-v)\mathbf p_{10}+(1-u)v\mathbf p_{01}+uv\mathbf p_{11} f ( u , v ) = ( 1 − u ) ( 1 − v ) p 00 + u ( 1 − v ) p 10 + ( 1 − u ) v p 01 + uv p 11 (式 6.11)。固定 u u u 或 v v v 都得到直线,所以是双直纹曲面 。它能表示平面四边形和简单的弯曲面,适合作为高阶参数曲面转换后可直接求交的目标形状。偏导数为
∂ p ∂ u = ( 1 − v ) ( p 10 − p 00 ) + v ( p 11 − p 01 ) , ∂ p ∂ v = ( 1 − u ) ( p 01 − p 00 ) + u ( p 11 − p 10 ) ( 式 6.13 ) \frac{\partial p}{\partial u}=(1-v)(\mathbf p_{10}-\mathbf p_{00})+v(\mathbf p_{11}-\mathbf p_{01}),\qquad\frac{\partial p}{\partial v}=(1-u)(\mathbf p_{01}-\mathbf p_{00})+u(\mathbf p_{11}-\mathbf p_{10})\quad(\text{式 6.13}) ∂ u ∂ p = ( 1 − v ) ( p 10 − p 00 ) + v ( p 11 − p 01 ) , ∂ v ∂ p = ( 1 − u ) ( p 01 − p 00 ) + u ( p 11 − p 10 ) ( 式 6.13 )
面积 ∫ 0 1 ∫ 0 1 ∥ ∂ u p × ∂ v p ∥ d u d v \int_0^1\!\int_0^1\|\partial_u p\times\partial_v p\|\,du\,dv ∫ 0 1 ∫ 0 1 ∥ ∂ u p × ∂ v p ∥ d u d v (式 6.12)一般没有闭式:矩形直接用边长乘积,否则用 3×3 点的黎曼和近似并缓存。IsRectangle() 依次检查相邻顶点重合、四点共面,以及四点到质心距离相等(用相对误差,与尺度无关)。法线方向锥取四角法线的平均方向和最大夹角。求交见 光线求交测试 ,采样见 形状采样 。
法线的导数:Weingarten 方程
纹理抗锯齿需要知道法线随 ( u , v ) (u,v) ( u , v ) 怎样变化。第一基本形式 E = ∣ ∂ u p ∣ 2 , F = ∂ u p ⋅ ∂ v p , G = ∣ ∂ v p ∣ 2 E=|\partial_u p|^2,\ F=\partial_u p\cdot\partial_v p,\ G=|\partial_v p|^2 E = ∣ ∂ u p ∣ 2 , F = ∂ u p ⋅ ∂ v p , G = ∣ ∂ v p ∣ 2 ,第二基本形式 e = n ⋅ ∂ u u p , f = n ⋅ ∂ u v p , g = n ⋅ ∂ v v p e=\mathbf n\cdot\partial_{uu}p,\ f=\mathbf n\cdot\partial_{uv}p,\ g=\mathbf n\cdot\partial_{vv}p e = n ⋅ ∂ uu p , f = n ⋅ ∂ uv p , g = n ⋅ ∂ v v p ,则
∂ n ∂ u = f F − e G E G − F 2 ∂ p ∂ u + e F − f E E G − F 2 ∂ p ∂ v , ∂ n ∂ v = g F − f G E G − F 2 ∂ p ∂ u + f F − g E E G − F 2 ∂ p ∂ v \frac{\partial\mathbf n}{\partial u}=\frac{fF-eG}{EG-F^2}\frac{\partial p}{\partial u}+\frac{eF-fE}{EG-F^2}\frac{\partial p}{\partial v},\qquad\frac{\partial\mathbf n}{\partial v}=\frac{gF-fG}{EG-F^2}\frac{\partial p}{\partial u}+\frac{fF-gE}{EG-F^2}\frac{\partial p}{\partial v} ∂ u ∂ n = E G − F 2 f F − e G ∂ u ∂ p + E G − F 2 e F − f E ∂ v ∂ p , ∂ v ∂ n = E G − F 2 g F − f G ∂ u ∂ p + E G − F 2 f F − g E ∂ v ∂ p
E G − F 2 EG-F^2 E G − F 2 用 DifferenceOfProducts() 计算以提高精度,为 0 时要避免除零产生 NaN。双线性面片只有 ∂ u v p \partial_{uv}p ∂ uv p 非零;三角形和圆盘法线导数为 0。参考 Gray (1993) 14.3 节。
旋转曲面的面积
曲线 y = f ( x ) y=f(x) y = f ( x ) 绕轴旋转 ϕ m a x \phi_{max} ϕ ma x 角得到的曲面面积为 ϕ m a x ∫ a b f ( x ) 1 + f ′ ( x ) 2 d x \phi_{max}\int_a^b f(x)\sqrt{1+f'(x)^2}\,dx ϕ ma x ∫ a b f ( x ) 1 + f ′ ( x ) 2 d x 。对球 f ( z ) = r 2 − z 2 f(z)=\sqrt{r^2-z^2} f ( z ) = r 2 − z 2 ,被积函数化简为常数 r r r ,于是部分球面积 A = ϕ m a x r ( z m a x − z m i n ) A=\phi_{max}r(z_{max}-z_{min}) A = ϕ ma x r ( z ma x − z min ) ,完整球为 4 π r 2 4\pi r^2 4 π r 2 ;圆柱 A = ( z m a x − z m i n ) r ϕ m a x A=(z_{max}-z_{min})r\phi_{max} A = ( z ma x − z min ) r ϕ ma x ,圆盘(圆环)A = ϕ m a x 2 ( r 2 − r i 2 ) A=\frac{\phi_{max}}2(r^2-r_i^2) A = 2 ϕ ma x ( r 2 − r i 2 ) 。
纹理坐标与参数坐标分离
双线性面片若带每顶点纹理坐标 ( s , t ) (s,t) ( s , t ) ,就要把 ∂ p / ∂ u \partial p/\partial u ∂ p / ∂ u 换成 ∂ p / ∂ s = ∂ p ∂ u ∂ u ∂ s + ∂ p ∂ v ∂ v ∂ s \partial p/\partial s=\frac{\partial p}{\partial u}\frac{\partial u}{\partial s}+\frac{\partial p}{\partial v}\frac{\partial v}{\partial s} ∂ p / ∂ s = ∂ u ∂ p ∂ s ∂ u + ∂ v ∂ p ∂ s ∂ v 等;纹理映射退化时保留原偏导(至少叉积给出正确法线),并保证新法线与原法线同侧。