纹理映射与重心坐标公式
上一篇文章我们介绍了着色和基础着色模型。通过 Blinn-Phong 光照模型,我们可以使物体产生明暗层次、高光和立体感,但它还无法赋予物体真实的表面细节——比如木纹、砖墙、地球的大陆与海洋。
这篇文章将介绍纹理映射(Texture Mapping)以及支撑它的核心数学工具——重心坐标(Barycentric Coordinates)。
纹理映射
假设我们想渲染一个地球模型。我们已经生成了一个球体网格,也引入了光照模型,但渲染出的球体表面只是一颗带有光照效果的”石膏球”——没有大陆的形状、没有海洋的蓝色。
该怎么办?我们手上有一张世界地图(二维图片)。如果能将这张地图”贴”到球体表面,不就能渲染出地球的表面细节了吗?
在图形学中,这种方法就叫做纹理映射(Texture Mapping),这张世界地图就是纹理贴图(Texture Map)。我们要解决的核心问题是:如何建立纹理上的每个点与模型表面每个点的对应关系,使纹理完整、准确地呈现在模型上。
为了实现这种映射,图形学引入了 UV 坐标。
UV 坐标
UV 坐标是用于将二维纹理图像映射到三维模型表面的二维坐标系统。因为 3D 空间已经占用了 X、Y、Z 轴,所以使用字母 U 和 V 来表示纹理贴图上的水平和垂直坐标轴。
核心概念:
- U 和 V:U 代表图像的水平方向(相当于 X 轴),V 代表图像的竖直方向(相当于 Y 轴)。通过 UV 坐标,可以定位纹理贴图上任意一个点的颜色。
- 坐标范围:U 和 V 通常被归一化到
范围内。一般而言左下角是 ,右上角是 。实际工程中根据图形 API 的不同,原点位置可能有所差异(例如 DirectX 左上角为原点)。
因此,对于模型的每一个顶点,它不仅有
你可能会问:模型顶点的 UV 坐标从哪里来?
对于简单几何体,可以通过顶点位置计算得到;但对于复杂的不规则模型,UV 的展平和分配是美术工作者在建模软件中手动完成的。在这里我们只关心 UV 坐标的使用,不深究它的制作。
你又可能会问:我们只知道三角形三个顶点的 UV 坐标,三角形内部的点怎么办?
这就需要用到插值。而在三角形中,有一个非常强大的工具为插值提供了基础——重心坐标。
重心坐标公式
在讲解重心坐标之前,先要理解什么是插值。
插值(Interpolation) 是一种通过已知的离散数据点,在范围内推算新数据点的数学方法。
比如一条具有颜色的线段:左端点
当
那么三角形内的点呢?三角形有三个顶点,仅靠一个参数
这就是重心坐标的用武之地。假设:
是靠近顶点 的权重 是靠近顶点 的权重
那么
那么如何计算这三个权重呢?公式是:
其中
下面我们来推导这个公式。推导之前,需要先引入一个关键的数学工具——向量的叉乘。
向量的叉乘
向量叉乘(Cross Product,又称向量积、外积)和点乘一样,是向量的一种基本运算。点乘的结果是标量,而叉乘的结果是一个向量——同时垂直于两个相乘向量的新向量。
几何意义
对于叉乘运算
1. 方向:绝对垂直
新向量
在图形学中,这正是计算面法线(Face Normal)的最核心手段。有了法线,光照模型(如 Blinn-Phong)才能计算光线与表面的夹角。
2. 长度:平行四边形的面积
新向量
其中
特殊情况:如果
方向判定
既然
- 伸出右手,四指顺着第一个向量
的方向。 - 将四指向掌心弯曲,指向第二个向量
的方向(取夹角小于 的一侧)。 - 此时,大拇指所指的方向就是叉积结果
的方向。
注意顺序:
与 的方向恰好相反( ),因为右手要翻转过来。
代数计算
在代码实现中,我们不会真的去量角度、画右手,而是直接用向量的分量来算。给定两个三维向量:
它们的叉积可以通过以下公式逐分量计算:
这个公式可以借助三阶行列式来记忆:
其中
从代数公式可以直接验证叉乘的两个关键性质:
- 自身叉乘为零:
。这一性质在后续推导中会反复用到。 - 反交换律:
。
重心坐标推导
有了向量叉乘这个工具,我们就可以推导重心坐标公式了。
由
将
写成向量形式:
现在我们想要解出
等式两边同时取模:
因此:
根据叉乘的几何意义,模长等于两向量围成的平行四边形面积:
代入:
同理,将
最后:
至此,我们完成了重心坐标公式的完整推导。
重心坐标的使用
有了重心坐标,就能通过三角形三个顶点的属性,插值出三角形内部任意像素的属性值。
例如,已知三角形三个顶点的 UV 坐标分别为
同样的插值模式也适用于其他属性:
- 法向量:
- 颜色:
- 世界空间位置:
这正是光栅化阶段 GPU 硬件在屏幕空间上做的事:对三角形顶点的每一个属性,用重心坐标做线性插值,然后送入片元着色器。你在 Fragment Shader 里拿到的”插值后法线”和”插值后 UV”,背后就是重心坐标公式在运行。
总结
重心坐标是光栅化管线中的核心数学工具,它解决了”三角形内部的像素从哪里获得属性值”这个问题。通过面积比(即
这次的插图来自画师 Fangpeii
图片地址:https://www.pixiv.net/artworks/131700499