Login  Register

Re: VBO Performance Misunderstanding

Posted by alicana on Apr 20, 2015; 8:57pm
URL: https://forum.jogamp.org/VBO-Performance-Misunderstanding-tp4034319p4034346.html

I still have problems with the code that I share below. First of all, my achievement is drawing 1M points on the screen (by accumulating points in vbo). I tried to add some points in time by using glMapBufferRange(), I guess I have a trouble with usage of the buffer offset, position whatever...

1) I allocated a buffer for 1M points.  Is this ok? -> (10e6 * FLOAT_SIZE* 3) 3 Stands for XYZ
2) I want to increase points that are drawn, by 1000. But, exception is thrown which says "GL_INVALID_VALUE Out of range: offset 0, length 15378000, ..."
3) Second step is ok when I set increase to 100.
4) Is my drawArrays() call correct or am I trying to draw all points again and again?
5) Performance does it really matter for me

EDIT:

- I found mistake that I have done in second step.  I used  Buffers.SIZEOF_FLOAT when allocated buffer, but used  Buffers.SIZEOF_FLOAT when mapping to buffer. Works now. But still have questions
- My fps rate decreases dramatically.
FPS: 56
FPS: 63
FPS: 49
FPS: 38
FPS: 32
FPS: 28
FPS: 26
FPS: 23
FPS: 22
FPS: 21
FPS: 19
FPS: 19
FPS: 18
FPS: 17
FPS: 16

Is this normal ?



import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;

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

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

@SuppressWarnings("serial")
public class Main extends GLCanvas implements GLEventListener {

	private Random random = new Random();

	// VBO variables

	int[] vbo = new int[] { -1 };

	int maxNumberOfPoints = 1000000; // GL_POINTS
	int pointVertexSize = 3; // X,Y,Z
	int numberOfPointsAdded = 0;

	int pointOffset = 0;
	int increaseRate = 1000;

	// ===================================================
	// VBO related functions
	// ===================================================

	private void initVBO(GL2 gl) {

		gl.glGenBuffers(1, vbo, 0);
		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo[0]);
		gl.glBufferData(GL2.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT * maxNumberOfPoints * pointVertexSize, null,
				GL2.GL_DYNAMIC_DRAW);

		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);

	}

	private void updateVBO(GL2 gl) {

		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo[0]);
		ByteBuffer byteBuffer = gl.glMapBufferRange(GL2.GL_ARRAY_BUFFER, pointOffset, increaseRate * Buffers.SIZEOF_FLOAT * 3,
				GL2.GL_MAP_WRITE_BIT | GL2.GL_MAP_UNSYNCHRONIZED_BIT);

		FloatBuffer floatBuffer = byteBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();

		for (int i = 0; i < increaseRate; i++) {

			floatBuffer.put(random.nextFloat() + random.nextInt(1000)); // X
																		// coordinate
			floatBuffer.put(random.nextFloat() + random.nextInt(1000)); // Y
																		// coordinate
			floatBuffer.put(0);

			pointOffset += 3;
			numberOfPointsAdded += 1;
		}

		System.out.println(numberOfPointsAdded);

		gl.glUnmapBuffer(GL2.GL_ARRAY_BUFFER);
		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);

	}

	private void renderVBO(GL2 gl) {
		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo[0]);

		gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0l);

		gl.glDrawArrays(GL2.GL_POINTS, 0, pointOffset);

		gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
	}

	private void deleteVBO(GL2 gl) {

		gl.glDeleteBuffers(1, vbo, 0);

	}

	// ===================================================
	// OpenGL Callback Functions
	// ===================================================
	@Override
	public void init(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();

		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);

		initVBO(gl);
	}

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

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

		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glOrthof(0, 1000, 0, 1000, -1, 1);

		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();

		updateVBO(gl);
		renderVBO(gl);

		if (System.currentTimeMillis() - lastTimeInMillis > 1000) {
			System.out.println("FPS: " + fpsCounter);

			fpsCounter = 0;
			lastTimeInMillis = System.currentTimeMillis();
		}
		fpsCounter++;

	}

	@Override
	public void dispose(GLAutoDrawable drawable) {
		GL2 gl = drawable.getGL().getGL2();
		deleteVBO(gl);
	}

	// ===================================================
	// Main
	// ===================================================

	private static String TITLE = "JOGL 2.0 Setup (GLCanvas)";
	private static final int CANVAS_WIDTH = 320;
	private static final int CANVAS_HEIGHT = 240;
	private static final int FPS = 60;

	private int fpsCounter = 0;
	private long lastTimeInMillis = System.currentTimeMillis();

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {

				GLCanvas canvas = new Main();
				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 Main() {
		this.addGLEventListener(this);
	}
}