1. 程式人生 > >從零開始Java遊戲引擎[LWJGL](3)-使用VAO和VBO繪製圖形

從零開始Java遊戲引擎[LWJGL](3)-使用VAO和VBO繪製圖形

本節介紹如何使用VAO和VBO進行圖形繪製。

先看效果:

本系列文章關注的重點是遊戲引擎的開發,關於OpenGL的基礎知識,這裡就不再詳細講了,否則篇幅篇幅就太長了。這裡的相關概念我只簡單講下我自己的理解,如果各位不瞭解話,請查閱相關的OpenGL書籍。

VBO:頂點快取物件,其中儲存著頂點的相關資訊(包括:頂點座標、頂點顏色、頂點法線、紋理座標等,這些也就是常說的頂點屬性)。每個VBO只能儲存一個頂點屬性,如:儲存頂點位置的VBO,儲存頂點顏色的VBO…

VAO:頂點陣列物件,內部維護多個頂點屬性列表,而頂點屬性儲存在VBO中,即VAO中儲存著VBO中有關頂點屬性配置的資訊。

程式碼部分:

  1. 建立RawModel類,儲存實體資料

  2. 建立Loader類,載入實體資料

  3. 建立ShaderProgram類,編譯、連結著色器

  4. 建立Render類,渲染實體

// RawModel.java

// 主要準備要繪製的實體對應的VAO和頂點數目,用來繪製。VAO中儲存著各頂點屬性的配置。讓opengl可以按照VAO的配置解析傳遞的頂點資料。

package models;

public class RawModel {

    private int vaoID;
    private int vertexCount;

    public RawModel(int vaoID,int
vertexCount){ this.vaoID = vaoID; this.vertexCount = vertexCount; } public int getVaoID() { return vaoID; } public void setVaoID(int vaoID) { this.vaoID = vaoID; } public int getVertexCount() { return vertexCount; } }
// Loader.java
// 主要用來載入實體資料到VAO,即主要對實體資料進行相關配置, 最有返回一個RawModel物件,儲存著配置好的VAO用於繪製。 package renderEngine; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import models.RawModel; /** * 載入VBO */ public class Loader { private List<Integer> vaos = new ArrayList<Integer>(); private List<Integer> vbos = new ArrayList<Integer>(); public RawModel loadToVAO(float[] positions){ int vaoID = createVAO(); //配置vao storeDataInAttributesList(0, 3,positions); unbindVAO(); return new RawModel(vaoID, positions.length/3); } public void cleanUp(){ for(int vao:vaos){ GL30.glDeleteVertexArrays(vao); } for(int vbo:vbos){ GL15.glDeleteBuffers(vbo); } } private int createVAO(){ int vaoID = GL30.glGenVertexArrays(); vaos.add(vaoID); GL30.glBindVertexArray(vaoID); return vaoID; } private void storeDataInAttributesList(int attributeNumber,int coordinateSize,float[] data){ int vboID = GL15.glGenBuffers(); vbos.add(vboID); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID); FloatBuffer buffer = storeDataInFloatBuffer(data); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false,0,0); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } private void unbindVAO(){ GL30.glBindVertexArray(0); } //將int[]轉換為IntBuffer private IntBuffer storeDataInIntBuffer(int[] data){ IntBuffer buffer = BufferUtils.createIntBuffer(data.length); buffer.put(data); buffer.flip(); return buffer; } //將float[]轉換為FloatBuffer private FloatBuffer storeDataInFloatBuffer(float[]data){ FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length); buffer.put(data); buffer.flip(); return buffer; } }
// Renderer.java
// 根據配置好的VAO進行繪製。
package renderEngine;

import models.RawModel;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

public class Renderer {

    public void prepare(){
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    }

    public void render(RawModel model){
        GL30.glBindVertexArray(model.getVaoID());
        GL20.glEnableVertexAttribArray(0);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }
}
// MainGameLoop.java
// 測試程式碼

package engineTester;


import models.RawModel;

import org.lwjgl.opengl.Display;
import renderEngine.DisplayManager;
import renderEngine.Loader;
import renderEngine.Renderer;

public class MainGameLoop {

    public static void main(String[] args) {

        DisplayManager.createDisplay();

        Loader loader = new Loader();

        float[] positions = {
                -0.5f,0.5f,0.0f,
                -0.5f,-0.5f,0.0f,
                0.5f,-0.5f,0.0f,

                0.5f,-0.5f,0.0f,
                0.5f,0.5f,0.0f,
                -0.5f,0.5f,0.0f,
        };

        RawModel model =  loader.loadToVAO(positions);

        Renderer render = new Renderer();
        render.render(model);


        while(!Display.isCloseRequested()){

            render.prepare();

            // game logic

            // render
            render.render(model);

            DisplayManager.updateDisplay();
        }

        loader.cleanUp();       
        DisplayManager.closeDisplay();

    }
}

ok. 結束。

原始碼下載

下篇預告:使用索引快取。