Создание HUD / GUI с OpenGL (LWJGL)


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)без проекции, вида или матрицы мира, они всегда окажутся в пространстве экрана.
Джонатан Дикинсон

Ответы:


13

Это от старого игрового движка на основе OpenGL, который я пытался написать около семи лет назад, написанного на C ++, настолько обнаженного, как я, пытаясь объяснить, как я справляюсь с операциями рендеринга 3D-мира и 2D-интерфейса в нем. В моем классе визуализации OpenGL (OGLRender) я использовал четыре основных метода:

  • ready3D () для подготовки OpenGL для рендеринга трехмерной сцены мира.
  • ready2D () для подготовки OpenGL для визуализации 2D GUI.
  • render3D () для реального трехмерного рисования сцены мира.
  • render2D () для фактического чертежа 2D GUI.

    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
}

Итак, что я делаю, так это сначала рисую свою трехмерную мировую сцену, а затем в последний раз рисую свой графический интерфейс таким образом, чтобы графический интерфейс всегда был на вершине мировой сцены. Метод ready3D () готовит трехмерную проекцию мира к рисованию мировой сцены, а метод ready2D () готовит орто-сцену 2D для рисования в графическом интерфейсе. m_Setup.widthи m_Setup.heightтолько размеры экрана просмотра порта.

Что особенного в методе ready2D (), так это то, что gluOrtho2D()функция вызывается с аргументами, которые сообщают ей, когда мы рисуем примитивы GUI, мы рисуем их в координатах экрана, указанных для соответствия Windows, Mac и другим системам координат экрана рабочего стола. Например, верхний левый - (0,0) в формате (X, Y), а нижний правый - (ViewportWidth-1, ViewportHeight-1). И glTranslatef()используется для коррекции точного позиционирования на пиксель. Таким образом, когда мы рисуем линию от (0,0) до (0,9), тогда линия на самом деле будет рисоваться из верхнего левого и прямого вниз десяти пикселей общей длины и одного пикселя шириной.

В целом вам, скорее всего, просто интересно, что делает метод ready2D () . Я предоставил примеры исходного кода других методов, чтобы дать вам общее представление о том, как большинство игр выполняют сцену в 3D мире и порядок отрисовки графического интерфейса.


Спасибо, я просто не знал, будет ли переключение между орто и перспективой плохим для производительности, потому что мне кажется, что это большая операция (конечно, я едва знаю, как работает OpenGL ... все еще учусь!), Но везде я видел, и то, что вы сказали, предложите сделать это. Так что я думаю, я буду :)
smoth190

Мне нравится этот ответ, своего рода, что я думал делать. Мне было просто интересно, если бы это можно было сделать лучше, нажимая матрицу проекции на каждом 2D-рендере, а затем добавляя ее после. Это значит, что вы можете просто установить 3D один раз? Тогда вам нужно будет снова вызвать вашу настройку 3D для изменения размера окна, если вы справитесь с этим.
Lightbulb1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.