Tạo HUD / GUI bằng OpenGL (LWJGL)


15

Tôi đang ở giai đoạn phát triển trò chơi của mình, nơi tôi cần tạo HUD hoặc GUI. Tôi chưa bao giờ đến phần này, vì vậy tôi không biết nó đã được thực hiện như thế nào. Tôi đã thử kết xuất một hình tứ giác đơn giản tại một vị trí cố định trên màn hình, nhưng có một vấn đề. Để làm cho máy ảnh của tôi hoạt động với chỉnh hình, tôi sử dụng:

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);
}

Tôi không thấy làm thế nào tôi có thể làm cho một cái gì đó cố định trên màn hình bằng phương pháp này? Có cách nào khác không? Cảm ơn :)


Tôi sẽ không trả lời vì đây là từ phối cảnh Direct3D, nhưng nếu bạn sử dụng tọa độ ([0...1], [0...1], 0, 1)KHÔNG chiếu, ma trận hoặc ma trận thế giới, chúng sẽ luôn xuất hiện trong không gian màn hình.
Jonathan Dickinson

Câu trả lời:


13

Đây là từ một công cụ trò chơi dựa trên OpenGL cũ mà tôi đã cố gắng viết khoảng bảy năm trước được viết bằng C ++ khi tôi cố gắng giải thích cách tôi xử lý các hoạt động kết xuất đồ họa 3D và 2D trong thế giới 3D. Tôi đã sử dụng bốn phương thức chính trong lớp trình kết xuất OpenGL (OGLRender) của mình, đó là:

  • ready3D () để chuẩn bị OpenGL để hiển thị cảnh thế giới 3D.
  • ready2D () để chuẩn bị OpenGL để hiển thị GUI 2D.
  • render3D () để vẽ cảnh thế giới 3D thực tế.
  • render2D () cho bản vẽ GUI 2D thực tế.

    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 ...
    }

Và sau đó trong vòng lặp luồng chính, về cơ bản tôi sẽ chỉ gọi các phương thức theo thứ tự sau:

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

    SDL_GL_SwapBuffers(); // make drawn frame visible
}

Vì vậy, những gì tôi đang làm là tôi vẽ cảnh thế giới 3D của mình trước và sau đó tôi vẽ GUI của mình theo cách mà GUI luôn ở trên đỉnh của thế giới. Phương thức ready3D () giúp trình chiếu thế giới 3D sẵn sàng để vẽ cảnh thế giới và phương thức ready2D () sẵn sàng cho cảnh trực giao 2D sẵn sàng để vẽ GUI. m_Setup.widthm_Setup.height chỉ là kích thước màn hình cổng xem.

Điều đặc biệt ở phương thức ready2D ()gluOrtho2D()hàm được gọi với các đối số cho biết khi chúng ta vẽ các nguyên hàm GUI, chúng ta vẽ chúng trong tọa độ màn hình được chỉ định để khớp với Windows, Mac và các hệ tọa độ màn hình máy tính để bàn khác. Chẳng hạn như trên cùng bên trái là (0,0) ở định dạng (X, Y) trong khi dưới cùng bên phải là (ViewportWidth-1, ViewportHeight-1). VàglTranslatef() được sử dụng để sửa cho định vị chính xác trên mỗi pixel. Vì vậy, khi chúng ta vẽ một dòng từ (0,0) đến (0,9) thì dòng đó sẽ thực sự vẽ từ tổng chiều dài bên trái và thẳng xuống mười pixel và chiều rộng một pixel.

Nhìn chung, rất có thể bạn chỉ quan tâm đến phương thức ready2D () đang làm gì. Tôi đã cung cấp các ví dụ mã nguồn của các phương thức khác để cung cấp cho bạn một ý tưởng về cách nói chung hầu hết các trò chơi thực hiện cảnh vẽ thế giới 3D và thứ tự vẽ GUI.


Cảm ơn, tôi chỉ không biết nếu chuyển đổi giữa ortho và phối cảnh sẽ có hại cho hiệu suất, bởi vì đối với tôi nó có vẻ như là một hoạt động lớn (tất nhiên tôi hầu như không biết OpenGL hoạt động như thế nào ... vẫn học!) Nhưng ở mọi nơi tôi đã nhìn thấy, và những gì bạn nói, đề nghị làm điều này. Vì vậy, tôi đoán tôi sẽ :)
smoth190

Tôi thích câu trả lời này giống như những gì tôi đã nghĩ làm. Tôi chỉ tự hỏi liệu nó có thể được thực hiện tốt hơn bằng cách đẩy ma trận chiếu của bạn trên mỗi kết xuất 2D sau đó bật nó sau. Điều đó có nghĩa là bạn chỉ có thể thiết lập 3D một lần chắc chắn? Sau đó, bạn sẽ chỉ cần gọi lại thiết lập 3D của mình để thay đổi kích thước cửa sổ nếu bạn xử lý việc đó.
Lightbulb1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.