การสร้าง 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)ไม่มีการฉายมุมมองหรือเมทริกซ์โลกพวกมันจะลงจอดในพื้นที่หน้าจอเสมอ
Jonathan Dickinson

คำตอบ:


13

นี่เป็นเกมเอ็นจิ้นพื้นฐานจาก OpenGL ที่ฉันพยายามเขียนเมื่อประมาณเจ็ดปีก่อนที่เขียนใน C ++ เปลือยกับฉันขณะที่ฉันพยายามอธิบายว่าฉันจัดการกับโลก 3 มิติและ 2D GUI ในการแสดงผลได้อย่างไร ฉันใช้สี่วิธีหลักภายใน OpenGL renderer class (OGLRender) ของฉันซึ่ง ได้แก่ :

  • ready3D ()สำหรับการเตรียม OpenGL เพื่อแสดงฉากโลก 3 มิติ
  • ready2D ()สำหรับการเตรียม OpenGL เพื่อแสดง 2D GUI
  • render3D ()สำหรับการวาดฉากโลก 3 มิติจริง
  • 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
}

ดังนั้นสิ่งที่ฉันทำคือฉันวาดฉากโลก 3 มิติของฉันก่อนแล้วจึงวาด GUI ของฉันครั้งสุดท้ายเพื่อให้ GUI อยู่ด้านบนของฉากโลกเสมอ วิธี Ready3D ()ทำให้การฉายภาพ 3 มิติของโลกพร้อมสำหรับการวาดฉากโลกและวิธีการready2D ()ทำให้ฉาก Ortho 2D พร้อมสำหรับการวาด GUI 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 ()กำลังทำอยู่ ฉันได้ให้ตัวอย่างซอร์สโค้ดของเมธอดอื่นเพื่อให้แนวคิดแก่คุณเกี่ยวกับวิธีที่เกมส่วนใหญ่ทำฉากโลก 3 มิติและลำดับการวาด GUI


ขอบคุณฉันไม่ทราบว่าการสลับระหว่าง ortho และเปอร์สเปคทีฟจะไม่ดีต่อการแสดงหรือไม่เพราะสำหรับฉันดูเหมือนว่าเป็นเรื่องใหญ่ (แน่นอนว่าฉันแทบไม่รู้ว่า OpenGL ทำงานอย่างไร ... ยังคงเรียนรู้อยู่!) เห็นและสิ่งที่คุณพูดแนะนำให้ทำ ดังนั้นฉันเดาว่าฉันจะ :)
smoth190

ฉันชอบคำตอบนี้มันเป็นสิ่งที่ฉันคิดว่าจะทำ ฉันแค่สงสัยว่าถ้าทำได้ดีกว่าโดยกดเมทริกซ์ฉายภาพของคุณในการเรนเดอร์ 2D แต่ละอันจากนั้นก็โผล่มันออกมา นั่นหมายความว่าคุณสามารถติดตั้ง 3D ได้หรือไม่ จากนั้นคุณจะต้องเรียกการตั้งค่า 3 มิติของคุณอีกครั้งเพื่อเปลี่ยนขนาดหน้าต่างหากคุณจัดการสิ่งนั้น
Lightbulb1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.