3D图形学学习总结(十)—纹理映射透视矫正

    原文链接:http://www.nicemxp.com/articles/27

    之前的总结中介绍过仿射纹理映射,仿射纹理映射中纹理坐标是根据三角形屏幕坐标线性插值得到的,但是三角形在3d空间中映射到屏幕坐标时是与三角形的z轴分量相关的。所以直接直接通过屏幕坐标线性插值得到的纹理坐标是有误差的。

    我们可以看一下仿射纹理映射:

3D图形学学习总结(十)—纹理映射透视矫正_第1张图片

    这是将一个纹理图直接根据平面坐标线性插值得出纹理坐标的效果图,使用的纹理图:

3D图形学学习总结(十)—纹理映射透视矫正_第2张图片

    我们可以明显看出效果图中的纹理映射很扭曲,这就是仿射纹理映射的问题,在于线性插值不能计算在屏幕空间中不呈线性变化的量。因此它不适用于纹理坐标,甚至颜色强度。投影到视平面时使用的是透视变换,这扭曲了这些数据。

3D图形学学习总结(十)—纹理映射透视矫正_第3张图片

    图中我们可以看出在屏幕空间中通过线性插值计算得到的纹理坐标值是错误的。

    经过透视变换进入屏幕空间后,纹理坐标不再是线性变化的,要让它继续是线性的,必须除以z.  

    如图:

3D图形学学习总结(十)—纹理映射透视矫正_第4张图片

图中是视景体的侧视图,我们看到视景体中的线段AB映射到视平面上ab,然而AB是3d空间中的,而ab却是2d空间中的。

我们可以进行下推导:点A(y1, z1),B(y2, z2)

线段AB可以表示为:a*y + b*z = c

在透视变换时,我们转换为视平面时有

yper = (y * d) / z

d是视距我们可以看为一个常数,所以有:

y = yper * z * (1/d)

将y带入线段AB的公式中有:

a*(yper * z * (1/d)) + b*z = c 

=> z = c / (a*yper*(1/d) + b)

=>1/z = a * (1/d) * (1/c) * yper + b/c

所以我们可以看出顶点视平面中的透视坐标是与1/z成线性关系的,这样意味着计算3D空间中的纹理坐标u,v等,必须先将他们除以z,通过线性插值计算除以z后的值,然后再除以1/z得到3d空间中的纹理坐标,这样得到的结果才是最终正确的纹理坐标。

下面是透视矫正后的效果图:

3D图形学学习总结(十)—纹理映射透视矫正_第5张图片

我们可以看出比上面未经过透视矫正的效果好多了。

你可能感兴趣的:(C/C++)