代码之家  ›  专栏  ›  技术社区  ›  Sam

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

  •  1
  • Sam  · 技术社区  · 16 年前

    我有一个256x256纹理在我的视图截锥,我需要移动到一个z位置,在那里纹理复制屏幕上的实际大小。

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

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

    其中itemsize是世界空间中纹理的大小(2.0个单位)。这是为了计算当itemsize/2(相反)为1.0时z(相邻)是什么。我以为这样行。

    这个公式显示了一个纹理总是太小,无论我使用什么FOV,大约10%。

    谢谢

    编辑:我正在三维空间中移动图像,需要无缝过渡到正确的Z距离。我不能用正投影,它必须是在一个截锥视图中。

    4 回复  |  直到 16 年前
        1
  •  6
  •   Goz    16 年前

    你可以做的稍微容易一些,而不是混乱的视场,因为你需要的信息直接保存在投影矩阵中。

    因此,假设您的投影矩阵如下所示:

    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将返回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
    

    viewport转换转换这些值,使-1、1为0、0和1,-1为1024768

    所以我们可以通过做((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/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
    

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

        2
  •  2
  •   Pike65    16 年前

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

        3
  •  0
  •   Drew Hall    16 年前

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

    …但是,如果它是性能关键的话,就不是了!

        4
  •  0
  •   Bahbar    16 年前

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

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

    我也同意Pike65的观点,我不知道*2是从哪里来的。