我正在尝试使用顶点缓冲区对象。
起初,在我遇到这种令人讨厌的情况之前没有任何问题:
glPointSize(2.0f);
glBegin(GL_POINTS);
for (Entity p : points) {
glVertex3f(p.x, p.y, p.z);
}
glEnd();
如何将其转换为Vertex缓冲区对象渲染?
我的意思是,你可以看到,数据(x,y,z)每次都为每个点改变(它是一个循环)。
那么如何实现Vertex Buffers Object渲染呢?
答案 0 :(得分:8)
基本上你想要它将所有顶点数据放入FloatBuffer
,然后将它传递给OpenGL。我创建了一个VBO的小例子,它存储三角形的顶点和颜色并渲染它,以及如何删除它!
这是您创建实际的顶点和颜色缓冲区并将它们绑定到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);
如果您愿意,您当然可以向vertex_data
和color_data
添加更多顶点和颜色!但要始终记住顶点数据量,需要与颜色数据量相匹配,反之亦然!
重要事项:只创建一次VBO,并且只在必要时更新它们!不要为每个帧创建它们,因为它们的帧速率会比使用立即模式渲染时更差!
这是您需要调用的代码,用于渲染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);
然后,当您完成VBO并且不再需要它时,您可以通过执行以下操作将其删除。
glDeleteBuffers(vbo_vertex_handle);
glDeleteBuffers(vbo_color_handle);
答案 1 :(得分:1)
以下是关于缓冲区的好教程:
关于你的问题:
我建议创建一个最大点数的VBO(或者可能的点数是常数)。然后用NULL填充此缓冲区。
如果要渲染点,则需要map
缓冲并更新其内容。
float *data = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
update_points(data); // write new positions for all points
glUnmapBuffer(GL_ARRAY_BUFFER);
然后通过以下方式绘制:
bind_and_set_your_buffer();
glDrawArrays(GL_POINTS, 0, VertexCount);
答案 2 :(得分:1)
我遇到了同样的麻烦,Vallentin的回答非常令人满意。因此,为了JOGL,我想与公众分享整个代码。
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) {
}
}