1

我的视锥中有一个 256x256 纹理,我需要移动到 z 位置,在该位置上,纹理以实际尺寸在屏幕上复制。

到目前为止,我所拥有的是:

    const float zForTrueScale = -((itemSize/2) / tanf(DEGREES_TO_RADIANS(fieldOfView/2)) ) * 2;     

其中 itemSize 是我的纹理在世界空间中的大小(2.0 单位)。这是为了计算当 itemSize/2(相反)为 1.0 时 Z(相邻)是多少。我以为这会奏效。

无论我使用什么 FOV,这个公式都显示纹理始终太小约 10%。

谢谢

编辑:我在 3D 空间中移动图像,需要无缝过渡到正确的 z 距离。我不能使用正交投影,它必须在视锥中。

4

4 回答 4

6

由于您需要的信息直接保存在投影矩阵中,因此您可以比弄乱视场更容易做到这一点。

因此,鉴于您的投影矩阵将如下所示:

xScale     0               0                     0
0        yScale            0                     0
0          0     -(zf + zn)/(zf - zn)  -(2 * zf) / (zf-zn) 
0          0              -1                     0

其中 z-Far (zf) 和 z-Near (zn)、xScale 和 yScale 是已知的。

要选择正确的 Z 深度,我们首先要确保 w 最终为 1。这样,当我们除以 w 时,它不会改变任何东西。

幸运的是 w 很容易得到。它只是输入 z 的负数。因此,在 z 中输入 -1 将返回 1 的 aw。

我们假设您使用的分辨率为 1024x768,并且您想要的正确比例的纹理为 256x256。

我们还将进一步假设您的矩形设置为左上角的位置为 -1, 1,右下角的位置为 1, -1。

因此,让我们将这些插入并计算出 z。

如果我们使用以下内容:

-1, 1, -1, 1
1, -1, -1, 1

我们将得到如下内容。

1 / xScale, -1 / yScale, someZThatIsn'tImportant, 1
-1 / xScale, 1 / yScale, someZThatIsn'tImportant, 1

视口变换对这些值进行变换,使得 -1、1 为 0、0 和 1,-1 为 1024,768

所以我们可以通过 ((x + 1) / 2) * 1024 和 ((1 - y) / 2) * 768 看到它的工作原理

因此,如果我们假设 xScale 为 3/4,yScale 为 1,我们可以看到,通过将其插入,我们将得到以下结果:

对于左上角:

x = -3/4
=> ((-3/4 + 1) / 2) * 1024
=> 128
y = 1
=> ((1 - 1) / 2) * 768
=> 0

对于右下角:

x = 3/4
=> ((3/4 + 1) / 2) * 1024
=> 896
y = -1
=> ((1 + 1) / 2) * 768
=> 768

因此,您可以看到我们在屏幕中央有一个 768x768 像素的图像。显然,要获得 256x256,我们需要将 w 设置为 3,以便在 w 除之后,我们将这些坐标设为大小的 3((xScale * 1024)/256 应该等于(yScale * 768)/256 以获得正方形投影。

所以如果我们的最终坐标如下:

-1, 1, -3, 1
and
1, -1, -3, 1

我们将得到以下结果(在 w-divide 之后):

-0.25, 0.333, unimportantZ, 1
and
0.25, -0.333, unimportantZ, 1

通过上面的屏幕方程运行它们,我们得到

对于左上角:

x = -0.25
=> ((-0.25 + 1) / 2) * 1024
=> 384
y = 0.3333
=> ((1 - 0.3333) / 2) * 768
=> 256

对于右下角:

x = 0.25
=> ((0.25 + 1) / 2) * 1024
=> 640
y = -0.333
=> ((1 + 0.33333) / 2) * 768
=> 512

640 - 384 = 256
512 - 256 = 256

因此,我们现在拥有正确像素大小的最终矩形......

于 2010-01-21T09:55:27.723 回答
2

在不太了解您的情况的情况下,将正交投影推送到投影矩阵堆栈上,绘制纹理然后再次弹出它几乎肯定更容易。

于 2010-01-20T11:39:13.487 回答
0

虽然它会很慢,但你可以使用glDrawPixels()它并完成它。

...不过,如果它对性能至关重要,那就不是!

于 2010-01-20T11:40:26.883 回答
0

你的帧缓冲是正方形的吗?

如果没有,那么你有一个水平的视野和一个垂直的视野。你使用的是正确的吗?另外,你怎么确定你希望它在世界坐标中是 2.0 单位?如果您的最终目标是将其映射到像素,那么您需要将视口考虑在内,然后从那里开始工作。

我也同意 Pike65 的观点,即我不知道 *2 的来源。

于 2010-01-20T12:28:40.860 回答