纹理映射是光栅化过程中重要的一步。由于众所周知的原因,透视投影是非线性变换,因此顶点原始的uv坐标在变换之后不可以直接使用线性插值计算新的uv坐标。例如,矩形四个顶点的uv坐标分别为(0,0),(0,1),(1,0),(1,1),矩形中点的uv坐标按照线性插值的话等于(0.5,0.5),但是若矩形不是正对观察点的话,透视变换后中点的uv坐标就不一定等于(0.5,0.5)。

例如:

纹理贴图:

线性插值结果->错误:

透视矫正插值结果->正确:

关于透视矫正的详细理论推导请参考这三篇文章[1][2][3],本文直接给出实现代码。

int u, v;
double zr = a*(1/p1w) + b*(1/p2w) + c*(1/p3w);
u = ((a*(u1/p1w) + b*(u2/p2w) + c*(u3/p3w)) / zr) * w;
v = ((a*(v1/p1w) + b*(v2/p2w) + c*(v3/p3w)) / zr) * h;

其中,p1w、p2w、p3w分别是三个顶点进行透视投影变换后[x,y,z,w]中的w值,u1、u2、u3和v1、v2、v3分别是三个顶点的原始uv坐标,a、b、c是使用Barycentric Coordinates算法计算出的三个系数[4],w、h是纹理贴图的宽度和高度像素值。

参考资料:
[1] 深入探索透视纹理映射(上)
[2] 深入探索透视纹理映射(下)
[3] 透视校正插值(Perspective-Correct Interpolation)
[4] 使用Barycentric Coordinates算法进行三角形光栅化

» 转载请注明来源及链接:未来代码研究所

Related Posts:

2 Responses to “纹理映射中透视矫正插值算法的实现”

  • Key says:

    楼主,最近我在做三维纹理隐射这部分!!!
    模型中读取的每个面都是三角形!三个顶点坐标对应三个纹理坐标!

    那么怎样通过三个顶点坐标算出面内的点坐标和纹理坐标呢???
    还有这个纹理投影矫正插值在哪里用?
    怎么个用法??
    望楼主不吝赐教!!
    非常非常感谢!!

    • 暗影吉他手 says:

      我上面已经给出了代码,通过那些参数算出u和v,对应纹理贴图中的横坐标和纵坐标,然后取出纹理贴图对应点的像素值,设置给屏幕缓冲区的对应像素(x,y)即可。这里的x,y是透视投影变换之后的值。
      透视矫正就在根据顶点uv值插值计算三角形内部点uv值的时候用,因为线性插值的结果是错的,所以必须用这个方法矫正。

Leave a Reply

World Line
Time Machine
Friendly Links
Online Tools