OpenGL:计算1:1像素比的z值

时间:2010-01-20 11:19:21

标签: math opengl graphics trigonometry

我的视锥体中有一个256x256的纹理,我需要移动到一个z位置,在这个位置,纹理在ACTUAL大小的屏幕上复制。

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

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

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

无论我使用何种FOV,这个公式都显示纹理一直太小了约10%。

由于

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

4 个答案:

答案 0 :(得分: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-Depth,我们将首先确保w最终为1.这样当我们除以w时,它不会改变任何东西。

幸运的是,很容易搞定。它只是输入z的负数。因此,输入-1到z将返回w为1。

我们假设您使用的分辨率为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 w divide我们将那些坐标设置为大小的第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

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

虽然速度很慢,但您可以使用glDrawPixels()并完成它。

......不过,如果它的性能至关重要,那就不行了!

答案 3 :(得分:0)

你的帧缓冲区是否正方形?

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

我同意Pike65的说法,我没有得到* 2的来源。