Створення 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 GUI-рендерінгу в ньому. Я використовував чотири основні методи в моєму класі OpenGL-рендерів (OGLRender), з яких:

  • ready3D () для підготовки OpenGL до візуалізації світової сцени 3D.
  • ready2D () для підготовки OpenGL до візуалізації 2D GUI.
  • render3D () для фактичного малювання 3D сцени світу.
  • 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
}

Отже, те, що я роблю, це те, що я малюю спочатку свою світову сцену 3D, а потім я малюю свій графічний інтерфейс останнім, таким чином, щоб графічний інтерфейс завжди був на вершині світової сцени. Метод ready3D () отримує 3D-проекцію світу готовий до малювання на світовій сцені, а метод 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

Мені подобається ця відповідь свого роду, що я думав робити. Мені було просто цікаво, хоча чи можна це зробити краще, натиснувши на вас проекційну матрицю на кожному двовимірному рендері, потім вискочивши її після. Це означатиме, що ви можете точно встановити 3D однозначно? Тоді вам потрібно буде лише знову зателефонувати до налаштування 3D для зміни розміру вікна, якщо ви це впораєтеся.
Лампочка1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.