OpenGL Java VBO

4
我正在使用 LWJGL 绘制立方体,使用的是 glBegin/glEnd 方法,但我听说这种方法非常低效,我应该开始使用 VBOs。但是我不知道它是如何工作的。
我想绘制不同大小和位置(无旋转)的立方体,我认为我应该使用 VBO 进行操作。
是否有人可以给我一些示例代码或洞察如何在 Java 中使用 VBO,甚至是否 VBO 是最好的选择?

1
为什么不在网上搜索呢?我相信那里有很多关于VBO的教程(甚至是针对Java的)。从一个简短的回答和一些没有解释任何东西的示例代码中,你不会学到太多东西。然后明天你会问,如何更改此代码以实现不同的目标。 - Christian Rau
glBegin/glEnd 立即模式的命令比VBO慢,但总体上仍然相当快 - 除非您真的每帧绘制了大量对象,否则您可能不会注意到差异..... - mikera
3个回答

8
这是我用Java编写的测试VBO的代码。它使用JOGL而不是LWJGL,但这只是小事情。
除了glVertexPointer外,您还可以使用glTexCoordPointer和glNormalPointer来指定纹理坐标和法线的数据,并使用glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY)和glEnableClientState(GL.GL_NORMAL_ARRAY)启用它们。
import com.sun.opengl.util.*;

import javax.media.opengl.*;
import javax.swing.*;
import java.nio.*;


public class VBOTest implements GLEventListener {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        GLCanvas canvas = new GLCanvas();
        canvas.addGLEventListener(new VBOTest());
        frame.add(canvas);
        frame.setSize(640, 480);
        frame.setVisible(true);
    }

    private FloatBuffer vertices;
    private ShortBuffer indices;
    private int VBOVertices;
    private int VBOIndices;

    public void init(GLAutoDrawable drawable) {
        float[] vertexArray = {-0.5f,  0.5f, 0,
                                0.5f,  0.5f, 0,
                                0.5f, -0.5f, 0,
                               -0.5f, -0.5f, 0};
        vertices = BufferUtil.newFloatBuffer(vertexArray.length);
        vertices.put(vertexArray);
        vertices.flip();

        short[] indexArray = {0, 1, 2, 0, 2, 3};
        indices = BufferUtil.newShortBuffer(indexArray.length);
        indices.put(indexArray);
        indices.flip();

        GL gl = drawable.getGL();
        int[] temp = new int[2];
        gl.glGenBuffers(2, temp, 0);

        VBOVertices = temp[0];
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBOVertices);
        gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices.capacity() * BufferUtil.SIZEOF_FLOAT,
                            vertices, GL.GL_STATIC_DRAW);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);

        VBOIndices = temp[1];
        gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, VBOIndices);
        gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * BufferUtil.SIZEOF_SHORT,
                            indices, GL.GL_STATIC_DRAW);
        gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    public void display(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();

        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBOVertices);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
        gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, VBOIndices);
        gl.glDrawElements(GL.GL_TRIANGLES, indices.capacity(), GL.GL_UNSIGNED_SHORT, 0);

        gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
    }

    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}

我认为你的术语存在一些混淆。VAO是VBO和属性绑定状态的集合,在你的代码中根本没有使用。你所使用的VBO回退仅依赖于固定功能顶点处理,并将顶点数组(只是在活动时存储在VBO中的数据集合)存储在客户端内存中。我不知道是否有一个名称,但它不是VAO。 另外,所有固定功能处理,包括将客户端内存用作属性位置的目标,都已在OpenGL 3+中被弃用。 - Nicolas Lefebvre
@Bethor:感谢您指出这一点。我编辑了答案,删除了这个错误信息。 - msell
这是一个非常好的例子,可以快速地在JOGL中启用和运行VBOs。非常感谢! - Mapsy

0

在谷歌上搜索OpenGL VBO会得到一些有用的结果,比如this one


0

Jzy3d允许在基于JOGL的Java中轻松绘制VBO。

这里是一个示例,展示了如何创建一个VBO散点图。这个散点图基于一个通用的DrawableVBO,可以扩展以设置自己的几何/网格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接