Direct3D中投影空间内的点坐标与屏幕上(或视口内)点的对应关系,

时间:2021-02-22 23:41:26

Direct3D中投影空间内的点坐标与屏幕上(或视口内)点的对应关系,
设屏幕大小为w×h,屏幕左上角像素的中心被定义为(0,0),整个屏幕是从(-0.5,-0.5)-(w-0.5,h-0.5),
像素将投影空间内的x轴上区间 (-1.0-1/w, 1.0-1/w]均匀分成w份,每份长度2/w,
将投影空间内的x轴上区间(-1.0-1/h, 1.0-1/h]均匀分成h份,每份长度2/h。
例如最左侧的像素点的对应的横坐标区间为(-1.0-1/w,-1.0+1/w],依次类推。
对于更一般的情况有
光栅化公式 投影空间坐标(x,y) -> 屏幕像素坐标(Sx,Sy)
Sx = x * (w/2) + (w/2)   [1]
Sy = y * (-h/2) + (h/2)  [2]

以上是光栅化时的规律,在纹理采样时,Direct3D使用如下公式
采样公式 纹理坐标(u,v) -> 图素坐标(Tx,Ty)
Tx = u*w - 0.5  [3]
Ty = v*h - 0.5  [4]

如果需要将一张图的左上角(最左上角图素的左上角)对应到屏幕的左上角
有些人可能会将左上角Vertex的投影空间坐标设置为(-1.0,1.0),其实这是不对的,我们可以用光栅化公式推导一下,
当(x,y) = (-1.0,1.0)时,
Sx = x * (w/2) + (w/2) = 0
Sy = y * (-h/2) + (h/2) = 0
而(Sx,Sy)=(0,0)并不是屏幕的左上角,而是屏幕左上角像素的中心,屏幕的左上角坐标应该是(-0.5,-0.5)

x * (w/2) + (w/2) = -0.5
y * (-h/2) + (h/2) = -0.5
可得,
x = -1 -1/w
y = 1 + 1/h
这才是正确的Vertex的投影空间坐标

结合光栅化公式和采样公式我们还可以推导一下ShadowMap中采样深度图的纹理坐标,首先明确问题:
即,已知深度图上一点是由投影空间坐标(x,y)光栅化成的,现在要采样该点,计算(u,v),用(x,y)表示。

解:只需将建立方程让纹理坐标对应的图素坐标=屏幕像素坐标(即深度图上的图素坐标)
Tx = Sx
Ty = Sy
将[1],[2],[3],[4]式代入可解得,
u = x * 0.5 + (0.5 + 0.5/w)
v = y * -0.5 + (0.5 + 0.5/h)

参考:http://www.gesoftfactory.com/developer/Textures.htm