使用OpenGL(LWJGL)制作HUD / GUI


15

我处于游戏开发阶段,需要制作HUD或GUI。我从来没有涉及到这一部分,所以我不知道它是如何完成的。我尝试在屏幕上的固定位置渲染一个简单的四边形,但是有一个问题。为了使我的相机与正交摄影配合使用,我使用以下方法:

public void lookThrough()
{
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glOrtho(position.x, position.x + Display.getDisplayMode().getWidth()/zoom, position.y + Display.getDisplayMode().getHeight()/zoom, position.y, -1, 1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
}

我看不到如何使用这种方法将某些东西固定在屏幕上?可以解决吗?谢谢 :)


我不会回答,因为这是从Direct3D角度来看的,但是如果您使用不([0...1], [0...1], 0, 1)带投影,视图或世界矩阵的坐标,它们将始终落在屏幕空间中。
乔纳森·迪金森

Answers:


13

这来自大约七年前我试图用C ++编写的基于OpenGL的旧游戏引擎,当我试图解释如何处理其中的3D世界和2D GUI渲染操作时,对我几乎一无所知。我在OpenGL渲染器类(OGLRender)中使用了四种主要方法,它们是:

  • ready3D(),用于准备OpenGL以渲染3D世界场景。
  • ready2D(),用于准备OpenGL以渲染2D GUI。
  • 实际3D世界场景绘制的render3D()
  • 实际2D GUI绘图的render2D()

    void OGLRender::ready3D()
    {
        glViewport(0, 0, m_Setup.width, m_Setup.height);
        glMatrixMode(GL_PROJECTION);
    
        glLoadIdentity();
        gluPerspective(45, (float) m_Setup.width / m_Setup.height, 0.1, 5000.0);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
    }
    
    void OGLRender::ready2D()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        gluOrtho2D(0.0f, m_Setup.width, m_Setup.height, 0.0f);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.375, 0.375, 0.0);
    
        glDisable(GL_DEPTH_TEST);
    }
    
    void OGLRender::render3D()
    {
        this->ready3D();
    
        // ... draw 3D world scene here ...
    }
    
    void OGLRender::render2D()
    {
        this->ready2D();
    
        // ... draw GUI here ...
    }

然后在主线程循环中,我基本上只会按以下顺序调用方法:

while(m_drawFrame)
{
    gm_Render->render3D(); // draw 3D scene
    gm_Render->render2D(); // draw GUI

    SDL_GL_SwapBuffers(); // make drawn frame visible
}

因此,我要做的是先绘制3D世界场景,然后最后绘制GUI,以使GUI始终位于世界场景的顶部。ready3D()方法获取准备好用于世界场景绘制的3D世界投影,ready2D()方法获取准备好用于GUI绘制的2D正交场景。m_Setup.widthm_Setup.height仅仅是视口的屏幕尺寸。

ready2D()方法的特殊之处gluOrtho2D()在于调用了带有参数的函数,这些参数告诉我们绘制GUI基元时,将它们绘制在指定的屏幕坐标中以匹配Windows,Mac和其他桌面屏幕坐标系。例如,左上角是(X,Y)格式的(0,0)而右下角是(ViewportWidth-1, ViewportHeight-1)。并glTranslatef()用于校正每个像素的精确定位。因此,当我们从(0,0)到(0,9)绘制一条线时,该线实际上将从左上角开始绘制,并向下垂直向下绘制总长度为10个像素和一个像素为1个像素的宽度。

总的来说,您最有可能只是对ready2D()方法的作用感兴趣。我提供了其他方法的源代码示例,以使您大致了解大多数游戏如何执行3D世界场景和GUI绘制顺序。


谢谢,我只是不知道在正交和透视之间切换是否会对性能造成不良影响,因为对我来说,这似乎是一个很大的操作(当然,我几乎不知道OpenGL的工作原理……仍在学习!),但是到处都是看过了,以及您说的话,建议您这样做。所以我想我会:)
smoth190

我喜欢这个答案,有点像我在想什么。我只是想知道是否可以通过在每个2D渲染上推动投影矩阵然后将其弹出来更好地完成它。那意味着您可以确定只设置一次3D吗?然后,如果您处理了窗口大小的更改,则只需再次调用3D设置即可。
灯泡2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.