Java - how to use the vertex buffers object in LWJGL?

≯℡__Kan透↙ 提交于 2019-12-12 04:34:55

问题


I am trying to use the vertex buffers object.

At first there wasn't any problem until I got into this nasty situation:

glPointSize(2.0f);
glBegin(GL_POINTS);
for (Entity p : points) {
    glVertex3f(p.x, p.y, p.z);
}
glEnd();

How can I convert this into the Vertex Buffers Object render?

I mean as you can see, the data (x, y, z) are changed every time for each point (it's a loop ).

So how can i implement the Vertex Buffers Object render into this?


回答1:


Basically what you want it putting all the vertex data into a FloatBuffer, and then pass it to OpenGL. I've created a little example of a VBO storing Vertices and Colors for a Triangle and rendering it and also how to delete it!

Creating the VBO

This is the code where you create the actual Vertex and Color Buffer and bind them to the VBO.

int vertices = 3;

int vertex_size = 3; // X, Y, Z,
int color_size = 3; // R, G, B,

FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * vertex_size);
vertex_data.put(new float[] { -1f, -1f, 0f, });
vertex_data.put(new float[] { 1f, -1f, 0f, });
vertex_data.put(new float[] { 1f, 1f, 0f, });
vertex_data.flip();

FloatBuffer color_data = BufferUtils.createFloatBuffer(vertices * color_size);
color_data.put(new float[] { 1f, 0f, 0f, });
color_data.put(new float[] { 0f, 1f, 0f, });
color_data.put(new float[] { 0f, 0f, 1f, });
color_data.flip();

int vbo_vertex_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

int vbo_color_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
glBufferData(GL_ARRAY_BUFFER, color_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

You can of course add more Vertices and Colors to the vertex_data and color_data if you want to! But always remember that the amount of vertex data, need to match with the amount of color data and vice versa!

Important: Only create the VBO(s) once, and only update them when necessary! Don't create them for each frame, since them you will end up with a frame-rate worse than when using immediate mode for rendering!

Rendering the VBO

This is the code you need to call, to render the VBO.

glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
glVertexPointer(vertex_size, GL_FLOAT, 0, 0l);

glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
glColorPointer(color_size, GL_FLOAT, 0, 0l);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

glDrawArrays(GL_TRIANGLES, 0, vertices);

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

Deleting the VBO

Then when you're done with the VBO and you don't need it anymore, you can delete it by doing the following.

glDeleteBuffers(vbo_vertex_handle);
glDeleteBuffers(vbo_color_handle);



回答2:


Here are good tutorials on buffers:

  • Following the Data
  • https://www.opengl.org/wiki/Buffer_Object

Regarding your question:

I suggest creating a VBO for maximum number of points (or maybe num of points is constant). Then fill this buffer with NULL.

When you want to render points you need to map buffer and update its content.

float *data = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
update_points(data); // write new positions for all points
glUnmapBuffer(GL_ARRAY_BUFFER); 

Then you draw it via:

bind_and_set_your_buffer();
glDrawArrays(GL_POINTS, 0, VertexCount);
  • for updating you can consider using: glBufferSubData, or glMapBufferRange



回答3:


I had same trouble and Vallentin's answer is very satisfying. So, for sake of JOGL, I want to share whole code with public.

package alican_tuts.VBO;

import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.FloatBuffer;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.FPSAnimator;

public class VBO_Example extends GLCanvas implements GLEventListener {
    private static final long serialVersionUID = 1L;

    private static String TITLE = "AliCan VBO EXAMPLE";
    private static final int CANVAS_WIDTH = 800;
    private static final int CANVAS_HEIGHT = 600;
    private static final int FPS = 60;

    private GLU glu;

    // VBO related variables
    int vertices = 3; // Triangle vertices

    int vertex_size = 3; // X,Y,Z
    int color_size = 3; // R, G, B

    private FloatBuffer vertex_data;
    private FloatBuffer color_data;

    private int[] vbo_vertex_handle = new int[1];
    private int[] vbo_color_handle = new int[1];

    // ===========================================================
    // GUI creation and program's main function
    // ===========================================================
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GLCanvas canvas = new VBO_Example();
                canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));

                final FPSAnimator animator = new FPSAnimator(canvas, FPS, true);

                final JFrame frame = new JFrame();

                frame.getContentPane().add(canvas);
                frame.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosing(WindowEvent e) {

                        new Thread() {
                            @Override
                            public void run() {
                                if (animator.isStarted())
                                    animator.stop();
                                System.exit(0);
                            }
                        }.start();
                    }
                });
                frame.setTitle(TITLE);
                frame.pack();
                frame.setVisible(true);
                animator.start();
            }
        });
    }

    public VBO_Example() {
        this.addGLEventListener(this);
    }

    // ===========================================================
    // VBO Related Functions
    // ===========================================================

    private void initVBOs(GL2 gl) {
        vertex_data = Buffers.newDirectFloatBuffer(vertices * vertex_size);
        // vertex_data = FloatBuffer.allocate(vertices * vertex_size);
        vertex_data.put(new float[] { 0.0f, 1.0f, 0f });
        vertex_data.put(new float[] { -1.0f, -1.0f, 0f });
        vertex_data.put(new float[] { 1.0f, -1.0f, 0f });
        vertex_data.flip();

        color_data = Buffers.newDirectFloatBuffer(vertices * color_size);
        // color_data = FloatBuffer.allocate(vertices * color_size);
        color_data.put(new float[] { 1f, 0f, 0f });
        color_data.put(new float[] { 0f, 1f, 0f });
        color_data.put(new float[] { 0f, 0f, 1f });
        color_data.flip();

        gl.glGenBuffers(1, vbo_vertex_handle, 0);
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo_vertex_handle[0]);

        gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertices * vertex_size * Buffers.SIZEOF_FLOAT, vertex_data,
                GL2.GL_STATIC_DRAW);
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);

        gl.glGenBuffers(1, vbo_color_handle, 0);
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo_color_handle[0]);
        gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertices * vertex_size * Buffers.SIZEOF_FLOAT, color_data,
                GL2.GL_STATIC_DRAW);
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);

    }

    private void renderVBOs(GL2 gl) {
        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo_vertex_handle[0]);
        gl.glVertexPointer(vertex_size, GL2.GL_FLOAT, 0, 0l);

        gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo_color_handle[0]);
        gl.glColorPointer(color_size, GL2.GL_FLOAT, 0, 0l);

        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL2.GL_COLOR_ARRAY);

        gl.glDrawArrays(GL2.GL_TRIANGLES, 0, vertices);

        gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
        gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
    }

    // ===========================================================
    // OpenGL Callback Functions
    // ===========================================================
    @Override
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        glu = new GLU();
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        gl.glClearDepth(1.0f);
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glDepthFunc(GL2.GL_LEQUAL);
        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);

        gl.glShadeModel(GL2.GL_SMOOTH);

        initVBOs(gl);
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        GL2 gl = drawable.getGL().getGL2();

        if (height == 0)
            height = 1;
        float aspect = (float) width / height;

        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(45.0, aspect, 0.1, 100.0);

        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    @Override
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

        gl.glLoadIdentity();

        gl.glTranslatef(0.0f, 0.0f, -6.0f);
        renderVBOs(gl);
    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
    }

}


来源:https://stackoverflow.com/questions/19346343/java-how-to-use-the-vertex-buffers-object-in-lwjgl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!