透视投影,标准观看量

时间:2020-05-06 06:29:41

标签: opengl perspective frustum

Vector3d nearC(0,0,0 -w);
Vector3d farC(0,0,0-x);
double width = y/2;
double height = z/2;
double angleOfHeight = atan(height/w);
double angleOfWidth = atan(width/w);
double adjustedHeight = tan(angleOfHeight) * x;
double adjustedWidth = tan(angleOfWidth) * x;

nearC[0] - width, nearC[1] - height, nearC[2]
nearC[0] - width, nearC[1] + height, nearC[2]
nearC[0] + width, nearC[1] + height, nearC[2]
nearC[0] + width, nearC[1] - height, nearC[2]
farC[0] - adjustedWidth, farC[1] - adjustedHeight, farC[2]
farC[0] - adjustedWidth, farC[1] + adjustedHeight, farC[2]
farC[0] + adjustedWidth, farC[1] + adjustedHeight, farC[2]
farC[0] + adjustedWidth, farC[1] - adjustedHeight, farC[2]

以上是我在视点坐标中的视锥。视图矩阵为:

 0   0  -1   0
 0   1   0  -1
 1   0   0 -10
 0   0   0   1

全部正确,我们有一张纸。

我无法为我的生活弄清楚如何在标准的观看量中获得平截头体。我已经遍历了所有可以找到的透视图。当前是这样:

        s,        0,                      0,                     0,
        0,        s,                      0,                     0,
        0,        0,             -(f+ne)/(f-ne),            2*f*ne/(f-ne),
        0,        0,                      1,                     0;

double s = 1 / tan(angleOfView * 0.5 * M_PI / 180);

我错过了某个步骤,对吧?还是几个步骤?

很抱歉,现在听起来这么没希望了,为此转了一段时间。

任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:2)

最好从透视投影开始。旧版GL中的常见方式是使用gluPerspective

为此,我们需要znear,zfar,FOV和视图的纵横比。有关更多信息,请参见:

  • Calculating the perspective projection matrix according to the view plane

    我习惯使用 FOVx x轴上的视角)。要计算您需要从上方(在摄影机空间中)查看xz平面来查看您的视锥体:

    frustrum XY plane

    如此:

    tan(FOVx/2) = znear_width / 2*focal_length
    FOVx = 2*atan(znear_width / 2*focal_length)
    
    焦距可以通过计算截锥体边缘线的交点来计算。或通过使用三角形相似度。第二个更容易编写:

    zfar_width/2*(|zfar-znear|+focal_length) = znear_width/2*(focal_length)
    zfar_width/(|zfar-znear|+focal_length) = znear_width/(focal_length)
    focal_length = (|zfar-znear|+focal_length)*znear_width/zfar_width
    focal_length - focal_length*znear_width/zfar_width = |zfar-znear|*znear_width/zfar_width 
    focal_length*(1-(znear_width/zfar_width)) = |zfar-znear|*znear_width/zfar_width 
    focal_length = (|zfar-znear|*znear_width/zfar_width) / (1-(znear_width/zfar_width))
    

    这就是我们所需要的:

    focal_length = (|zfar-znear|*znear_width/zfar_width) / (1-(znear_width/zfar_width))
    FOVx = 2*atan(znear_width / 2*focal_length)        
    FOVx*=180.0/M_PI; // convert to degrees
    aspect=znear_width/znear_height;
    gluPerspective(FOVx/aspect,aspect,znear,zfar);
    

    请注意,|zfar-znear|是平面之间的垂直距离!因此,如果没有轴对齐的轴,则需要使用点积和法线...