如何使用 OpenGL 正确投影和扭曲 3d 点

Posted

技术标签:

【中文标题】如何使用 OpenGL 正确投影和扭曲 3d 点【英文标题】:How to properly project and distort 3d points with OpenGL 【发布时间】:2020-04-21 14:49:05 【问题描述】:

我正在编写一个 GLSL 着色器来使用模型、视图和投影矩阵进行 3D 顶点的投影。

我将This 用于投影矩阵。 但是我没有得到扭曲的图像。 为了扭曲我使用的观点:

  vec4 distort(vec4 pos)
    // normalize
    float z = pos[2];
    float z_inv = 1 / z;
    float x1 = pos[0] * z_inv;
    float y1 = pos[1] * z_inv;
    // precalculations
    float x1_2 = x1 * x1;
    float y1_2 = y1 * y1;
    float x1_y1 = x1 * y1;
    float r2 = x1_2 + y1_2;
    float r4 = r2 * r2;
    float r6 = r4 * r2;
    // rational distortion factor
    float r_dist = (1 + k1 * r2 + k2 * r4 + k3 * r6)
     / (1 + k4 * r2 + k5 * r4 + k6 * r6);
    // full (rational + tangential) distortion
    float x2 = x1 * r_dist + 2 * p1 * x1_y1 + p2 * (r2 + 2 * x1_2);
    float y2 = y1 * r_dist + 2 * p2 * x1_y1 + p1 * (r2 + 2 * y1_2);
    // denormalize for projection (which is a linear operation)
    return vec4(x2*z, y2*z, z, pos[3]);

投影如下:

    vec4 view_pos = modelView * vec4(aPos, 1.0);
    vec4 dist_pos = distort(view_pos);
    gl_Position = projection * dist_pos;

问题是当相机靠近物体时,我得到的 3d 点投影非常糟糕。 有没有办法检查该点是否可失真,我正在使用的失真函数是否有问题(我正在尝试使用 OpenCV 失真)?

【问题讨论】:

这能回答你的问题吗? Camera lens distortion in OpenGL 我实际上是从那里得到方程式的。问题是当我离物体太近时,它的统计数据会变得非常糟糕。所以这些方程有一些限制,我想知道我是否可以预测在投影之前删除顶点什么时候会出错。 【参考方案1】:

不要扭曲单个顶点,因为正如您所提到的,它不能很好地工作。原因是无论你如何扭曲你的顶点,OpenGL 仍然会光栅化带有直边的三角形。然而,镜头畸变会导致直线出现弯曲。您可以通过将几何体细分为更小的三角形来缓解这种情况……但这永远无法完全解决问题。

相反,将您的场景渲染为屏幕外纹理,完成后渲染一个全屏四边形,该四边形对具有扭曲纹理坐标的纹理进行采样。此失真步骤可以与其他后期处理效果(例如色调映射)结合使用,使其成为一个相当便宜的选择。

【讨论】:

它不工作不是因为OpenGL,它不工作是因为当相机太近时我实现的失真模型不起作用(如果我可以说一些顶点远离失真域那)

以上是关于如何使用 OpenGL 正确投影和扭曲 3d 点的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenGL,如何正确使用 gluOrtho2D 和默认投影?

在 iOS 上使用 OpenGL-ES 2.0 设置横向正交投影的正确方法是啥?

如何在opengl中计算给定3D点及其2D屏幕位置的投影/模型视图矩阵

在 C++ 中的 OpenGL 中将坐标从 3D 透视投影映射到 2D 正交投影

OpenGL投影缩放

OpenGL 3+,具有定向光的正交投影