2010-01-20 83 views
1

我的视图中有一个256x256的纹理,我需要移动到z位置,纹理在屏幕上以实际大小复制。OpenGL:计算1:1像素比率的z值

我至今是:

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

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

无论我使用何种FOV,该公式显示的纹理一直过小约10%。

感谢

编辑:我走动的图像在三维空间中,需要正确的z距离的无缝过渡。我不能使用正交投影,它必须处于视锥体中。

回答

6

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

因此给你的投影矩阵看起来就像这样:

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

其中Z-远(ZF)和z近(ZN),xScale等和yScale是已知的。

要选择正确的Z-Depth,我们首先确保w结束为1.这样,当我们通过w进行除法时,它不会改变任何东西。

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

我们假定您使用的分辨率为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 

对于右下:

​​

因此你可以看到,我们在屏幕中心的768x768像素的图片。很显然,获得256x256我们需要得到的w为3,所以后w分割我们有这些坐标的三分之一的大小((xScale * 1024)/ 256应该等于(yScale * 768)/ 256得到一个正方形。投影

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

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

,我们会得到下面的输出(W-分后):

-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 

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

+0

哇,很好的答案,谢谢 – Sam 2010-01-21 10:19:19

2

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

+0

不,我四处移动图像3D空间,并需要无缝过渡到正确的z距离。我不能使用正交投影,它必须是3D。 – Sam 2010-01-20 11:43:01

+1

好的。对不起 - 误解了。在这种情况下:我的触发器非常生锈,但最终需要乘法运算吗? – Pike65 2010-01-20 12:11:47

0

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

...不,如果它是性能的关键,但!

0

你的framebuffer是否正方形?

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

我也同意派克65,我没有得到* 2来自哪里。

+0

* 2是因为trig使用相反的长度(半个项目宽度),然后在最后我将它乘以返回以获得全长。我可能刚开始时没有将项目宽度减半,但当时对我来说读起来更好。 无论如何,我的问题是,“我如何考虑视口并从中恢复视口”。我的framebuffer是方形的。 – Sam 2010-01-20 16:47:09

+0

我发现通过将13.5/FOV添加到最终结果中,可以为任何FOV提供足够精确的结果..但我不明白13.5来自哪里,这只是我目前代码中的一个可怕的幻数。 – Sam 2010-01-20 16:50:32

+0

对于trig:/ 2有意义得到项目宽度的一半。但是tan()是半项/ z。那里没有* 2参与。 什么是您的视图/ proj矩阵看起来像在绘制时?你通过什么样的方法来绘制纹理? – Bahbar 2010-01-20 17:47:34