在模型空间,世界空间,相机空间和剪裁空间中三角面上的纹理坐标与空间坐标是线性关系,按空间坐标进行线性插值即可求得纹理坐标。
但在透视投影模式下在归一化设备空间和视口空间中纹理坐标与空间坐标就不再是线性关系了,要在归一化设备空间或视口空间插值计算纹理坐标,需要进行非线性插值。
其原因就在于透视投影模式下由剪裁空间到归一化设备空间进行了一步透视除法。
在光栅化过程中,我们通常都是要在视口空间进行纹理插值,所以我们这里重点推导视口空间中纹理坐标的插值方法。
设相机空间中的坐标为(x,y,z),其变换到剪裁空间中的坐标为(xc,yc,zc),经过透视除法变换到归一化设备空间(xd,yd,zd),然后再经过视口变换变换到视口空间(xv,yv,zv)。
有关系:(参考:http://user.qzone.qq.com/350479720/blog/1310060277)
(根据透视投影矩阵:)
xc=x*(cot(fovy/2)/aspect)
yc=y*cot(fovy/2)
zc=-(f+n)/(f-n)*z-2fn/(f-n)
wc=-z
(根据透视除法:)
xd=xc/wc
yd=yc/wc
zd=zc/wc
wd=1
(根据视口矩阵:)
xv=0.5*width*xd+vx+0.5*width (vx,vy为视口左下角坐标)
yv=0.5*height*yd+vy+0.5*height
zv=0.5*zd+0.5
根据相机空间中三角面上的x,y,z为线性关系,有:
Ax+By+Cz+D=0
两边除以z得:A(x/z)+B(x/z)+C+D/z=0 (1)
由于
xd=xc/wc=-x/z*(cot(fovy/2)/aspect)
yd=yc/wc=-y/z*cot(fovy/2)
zd=zc/wc=(f+n)/(f-n)+2fn/(f-n)*(1/z)
代入(1)式得:
A(-xd*aspect/cot(fovy/2))+B(-yd/cot(fovy/2))+C+D(zd-(f+n)/(f-n))(f-n)/(2fn)=0
合并一下常数项得:
A'*xd+B'*yd+C'+D'*zd=0,其中A',B',C',D'均为常数。
可见xd,yd,zd是线性关系。
又由于xv与xd是线性关系,yv与yd是线性关系,zv与zd是线性关系,所以xv,yv,zv是线性关系,即:
zv=L(xv,yv) -----(结论1)
所以视口空间里深度值可以能过线性插值计算。
再来看纹理坐标:
由于三角面在相机空间中纹理坐标与空间坐标是线性关系,所以有:
s=Ax+By+Cz+D。
两边除以z得:
s/z=A(x/z)+B(y/z)+C+D/z (2)
由于
xd=xc/wc=-x/z*(cot(fovy/2)/aspect)
yd=yc/wc=-y/z*cot(fovy/2)
zd=zc/wc=(f+n)/(f-n)+2fn/(f-n)*(1/z)
代入(2)式得:
s/z=A(-xd*aspect/cot(fovy/2))+B(-yd/cot(fovy/2))+C+D(zd-(f+n)/(f-n))(f-n)/(2fn)
合并一下常数项得:
s/z=A'*xd+B'*yd+C'+D'*zd,其中A',B',C',D'均为常数。
即s/z=L(xd,yd,zd)
由于xv与xd是线性关系,yv与yd是线性关系,zv与zd是线性关系,所以
s/z=L(xv,yv,zv)
由于zv=L(xv,yv),所以
s/z=L(xv,yv)
由于zd=(f+n)/(f-n)+2fn/(f-n)*(1/z)及zv=0.5*zd+0.5,所以1/z=((zv-0.5)*2-(f+n)/(f-n))*(f-n)/(2fn),代入上式得:
s*((zv-0.5)*2-(f+n)/(f-n))*(f-n)/(2fn)=L(xv,yv)
上式可简化为:s*(zv-f/(f-n))=L(xv,yv)
类似有:t*(zv-f/(f-n))=L(xv,yv)
----(结论2)
根据结论1和结论2就可以得到透视投影模式下在视口空间插值计算纹理坐标的方法了:
首先通过线性插值计算zv,然后通过线性插值计算s*(zv-f/(f-n))和t*(zv-f/(f-n)),设结果为S和T,则
s=S/(zv-f/(f-n))
t=T/(zv-f/(f-n))
这样就得到了透视正确的纹理坐标(s,t)。
----
参考:http://blog.csdn.net/popy007/article/details/5570803#reply