我正在尝试使用OpenGL(LWJGL)中的vbo渲染模型

时间:2018-02-23 22:27:57

标签: java opengl lwjgl wavefront

我正在尝试通过导入.obj文件来渲染模型。我成功导入和准备要在FloatBuffers / IntegerBuffers中呈现的数据,但无法设法呈现它。有人能帮助我吗?

这是渲染和初始化VBO的类

private int vertexBufferID;
private int indexBufferID;
private int numberIndices;

public void init() {
    try{
        InputStream objInputStream = new FileInputStream("./res/obj/Terrain.obj");
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);
//      FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
//      FloatBuffer normals = ObjData.getNormals(obj);

        vertexBufferID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);

        indexBufferID = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    }catch(IOException e)
    {
        e.printStackTrace();
    }
}

public void render() {
    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    GL11.glDrawElements(GL11.GL_TRIANGLES, numberIndices, GL11.GL_UNSIGNED_INT, 0);
}

我没有得到错误代码,只是没有渲染对象。我可以使用显示列表渲染对象。

1 个答案:

答案 0 :(得分:3)

我现在已经解决了问题,现在可以导入.obj-Files并使用vbo / vao渲染它们。我使用"Obj - a simple Wavefront OBJ file loader and writer"来准备要呈现的数据。

加载和准备.obj文件的代码

        InputStream objInputStream = new FileInputStream(pathTObjFile);
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);

现在数据存储在2个VBO中,顶点的VBO存储在VAO中:

        vaoId = GL30.glGenVertexArrays();

顶点数组对象ID(vaoID)是一个在调用VAO时调用的Integer。

        GL30.glBindVertexArray(vaoId);

为了能够对我们必须绑定的VAO做任何事情,或者选择"它

        vboId = GL15.glGenBuffers();

VBO也有一个要调用的ID。我们在这里创建顶点缓冲区对象ID(vboId)

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);

现在我们选择VBO并将顶点存储在其中。

        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);

首先我们将VBO放在VAO的第一个属性列表中(VAO有16个列表),然后我们取消绑定VAO和VBO。

        vboiId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);

        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); 


        indicesCount = indices.capacity();

在初始化结束时,我们为索引创建了vbo,因此Vertices可以相互连接以正确的方式创建面。因此,我们绑定vboiId并将索引数据存储在其中。然后我们再次取消绑定VBO并保存存储在VBO中的Indices数量,因为我们必须告诉它OpenGL能够在以后渲染它。

渲染对象:

    GL30.glBindVertexArray(vaoId);
    GL20.glEnableVertexAttribArray(0);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);

要渲染对象,我们必须将VAO和VBO绑定在里面。我们还必须为指数选择VBO。这是由上面的代码片段完成的。

    GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);

现在我们绘制对象和

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);

再次取消选择VBO和VAO。

以下是整个代码组合

private int vboiId;
private int vaoId;
private int vboId;
private int indicesCount;

public void init() {

    try{

        InputStream objInputStream = 
            new FileInputStream("./res/obj/Terrain.obj");
        Obj obj = ObjReader.read(objInputStream);

        obj = ObjUtils.convertToRenderable(obj);

        IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
        FloatBuffer vertices = ObjData.getVertices(obj);
        FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
        FloatBuffer normals = ObjData.getNormals(obj);



        indicesCount = indices.capacity();


        vaoId = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoId);


        vboId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);

        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);


        GL30.glBindVertexArray(0);


        vboiId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
        GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);

        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    }catch(IOException e)
    {
        e.printStackTrace();
    }


}

public void render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);


    GL30.glBindVertexArray(vaoId);
    GL20.glEnableVertexAttribArray(0);


    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);


    GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);


    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

有关更多详细信息,我强烈建议您阅读The quad with Draw ArrayThe Quad with Draw Elements,如果您想更详细地查看Main Page上的OpenGL 3.2及以上教程LWJGL维基百科。 有关如何使用我使用的Obj加载器的信息,请查看The sample projects using this loader

我的代码基本上由这些网站上的代码组成。

编辑:如果您尝试渲染多个对象,则必须在渲染第一个对象之前清除颜色(渲染方法的第一行)