【问题标题】:OpenGL: How to optimize 2d rendering with multiple layers overlapping each other in 3d mode?OpenGL:如何在 3d 模式下优化多层相互重叠的 2d 渲染?
【发布时间】:2011-06-06 12:36:31
【问题描述】:

我知道如何通过简单地首先渲染最近的平面来加速 3d 渲染。

但是我如何在 2d 模式下利用这种方法呢?我不能使用深度测试,因为它们都在同一个 z 级别。

所以我在想当我不需要渲染“下面”图层的不可见部分时是否可以加快速度。这可能吗?

请注意,我在 3d 模式下渲染,可能同时存在 3d 对象和 2d 对象。所以我不能只切换到 2d 渲染,我总是对所有东西使用 3d 坐标。而且我可以随心所欲地旋转相机,因此不能接受特定于相机的技巧。

编辑: 我尝试了 Ville 建议的方法:

(http://img815.imageshack.us/img815/7857/zfighting.png)

但正如你所见,它会导致 z-fighting。

我用来渲染的代码在这里:

glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_POLYGON_OFFSET_FILL);

glColor4f(1,0,0,1);
DrawQuad(0, 0, 10, 10);

glColor4f(0,0,1,1);
DrawQuad(5, 5, 15, 15);

glDepthFunc(GL_LEQUAL);

【问题讨论】:

  • 深度测试(使用默认模式 GL_LESS)即使您的所有 2d 对象都在同一个 z 水平上,仍然可以工作。像素不会更新两次。
  • @Ville,这会导致 z-fight。查看我发布的图片。
  • 你说得对,我以为你的意思是 2d 对象 HUD 样式,但不明白你也打算围绕 2d 对象旋转相机。为此,我会首先像 derkyjadex 建议的那样以正交模式渲染纹理。
  • @Ville,渲染到纹理不会是矫枉过正...?我特别想找到比我使用 atm 的方法更快的方法:只是禁用深度测试。但我希望我可以优化一下,因为它确实绘制了一些永远不可见的无用像素......

标签: c++ opengl 3d rendering 2d


【解决方案1】:

听起来您在同一平面上渲染所有“2D”对象。您可以使用正交投影将 2D 部件渲染到屏幕外帧缓冲区中,并按照 datenwolf 的建议为它们提供不同的 Z 值。然后将帧缓冲区纹理渲染到您的主 3D 场景中。

【讨论】:

  • 或者只是清除深度缓冲区并使用 2D 平面过度绘制。
  • 渲染到帧缓冲区比仅仅禁用深度测试更快?
  • 可能没有,datenwolf 或许有更好的建议。但是您并没有禁用深度测试,而是清除了深度缓冲区,以便 OpenGL“忘记”已经渲染的 3D 对象。使用单独的帧缓冲区有效地做同样的事情,但如果某些 3D 对象应该出现在 2D 对象的前面,则您可以保留 3D 深度缓冲区。
【解决方案2】:

您对 2D 模式的理解是什么?你是说正交投影吗?然后我有一个好消息:深度测试也可以完美地工作。 gluOrtho2D 与 glOrtho(..., -1, 1); 基本相同。即你有 Z 范围 -1 ... 1 可以花费。

因评论而编辑:

完全可以在一帧中组合渲染多个投影:

void render_perspective_scene(void);

void render_ortho_scene(void);

void render_HUD();

void display()
{
    float const aspect = (float)win_width/(float)win_height;

    glViewport(0,0,win_width,win_height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-aspect*near/lens, aspect*near/lens, -near/lens, near/lens, near, far);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    render_perspective_scene();

    // just clear the depth buffer, so that everything that's
    // drawn next will overlay the previously rendered scene.
    glClear(GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-aspect*scale, aspect*scale, -scale, scale, 0, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    render_ortho_scene();

    // Same for the HUD, only that we render
    // that one in pixel coordinates.
    glClear(GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, win_width, 0, win_height, 0, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    render_HUD();
}

当然,如果您喜欢那些将投影矩阵设置放置在重塑处理程序中的糟糕教程,那么您当然会心烦意乱,无法看到明显的解决方案。

【讨论】:

  • “请注意,我在 3d 模式下渲染,可能同时存在 3d 对象和 2d 对象。所以我不能切换到仅 2d 渲染”你读了吗?
  • 当然可以切换。你认为游戏 HUD 是如何渲染的?
  • HUD 不是我想要在这里实现的。想象一下,你有一个普通的 3d 世界,然后你以 2d 模式从上往下渲染 3d 世界,然后旋转相机,你看到世界变平了。
  • 好吧,你有一些严重的误解:OpenGL 不是场景图。一旦您将一些几何图形发送到 OpenGL,只需将其栅格化为像素,然后忘记几何图形。所以去正交,渲染一些东西,然后旋转/切换投影不会改变你已经绘制到帧缓冲区的任何东西。因此,您实际上需要做的是渲染纹理,然后绘制这些四边形,或者使用一些着色器魔法将几何平面投影到这些平面上,但仍然传递可用于深度测试的深度值。
  • 我尝试过使用着色器,但它也需要关闭深度测试......我想那时没有解决方案,我也不是真的需要它,但作为一个优化怪胎,我想知道每一个技巧:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 2019-07-02
  • 2011-08-08
  • 2013-03-25
  • 2018-01-28
  • 1970-01-01
相关资源
最近更新 更多