I'm new to OpenGL and LWJGL & I have a question about rendering using VBOs.
I rendering 50*50 objects using VBOs. Each object has its own render method where binding of the position, rotation.
The problem is I have a low frame rate (~10fps) even though my objects (for now) consist of simple quads. Why is my framerate so low?
Later I want to use much more complex objects and other computations...
Code:
public class NGINE2 { static int w = 640; static int h = 480; static float oldX = 0; static float oldY = 0; static float oldZ = 0; static List<Triangle> triangles = new ArrayList<Triangle>(); public static void main(String[] args) throws Exception { // System.out.println("Hello world from OpenGL!"); Random rand = new Random(); for (int x = 0; x < 50; x++) { for (int z = 0; z < 50; z++) { float rgb[] = new float[3]; rgb[0] = rand.nextFloat(); rgb[1] = rand.nextFloat(); rgb[2] = rand.nextFloat(); triangles.add(new Triangle(new Vector3f(x, 1, z), new Vector3f(+0.5f, 1f, -0.5f), new Vector3f(-0.5f, 1f, -0.5f), new Vector3f(+0.5f, 1f, +0.5f), rgb, rgb, rgb)); triangles.add(new Triangle(new Vector3f(x, 1, z), new Vector3f(-0.5f, 1f, +0.5f), new Vector3f(-0.5f, 1f, -0.5f), new Vector3f(+0.5f, 1f, +0.5f), rgb, rgb, rgb)); } } initContext(); renderLoop(); int height = 500; int width = 500; double value[][] = new double[500][500]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { double nx = x / width - 0.5, ny = y / height - 0.5; value[y][x] = SimplexNoise.noise(nx, ny); } } } static void initContext() throws Exception { Camera.create(); w = 640; h = 480; Display.setDisplayMode(new DisplayMode(w, h)); Display.setFullscreen(false); Display.create(); glViewport(0, 0, w, h); } static void renderLoop() { while (!Display.isCloseRequested()) { preRender(); render(); Display.update(); Display.sync(300 /* desired fps */); } Display.destroy(); } static void preRender() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLU.gluPerspective(45.0f, ((float) w / (float) h), 0.1f, 100.0f); // fix na błąd z kamerą glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static void drawVBOtriangle(float s1[], float s2[], float s3[]) { // create geometry buffers FloatBuffer cBuffer = BufferUtils.createFloatBuffer(9); cBuffer.put(s1[3]).put(s1[4]).put(s1[5]); cBuffer.put(s2[3]).put(s2[4]).put(s2[5]); cBuffer.put(s3[3]).put(s3[4]).put(s3[5]); cBuffer.flip(); FloatBuffer vBuffer = BufferUtils.createFloatBuffer(9); vBuffer.put(s1[0]).put(s1[1]).put(s1[2]); vBuffer.put(s2[0]).put(s2[1]).put(s2[2]); vBuffer.put(s3[0]).put(s3[1]).put(s3[2]); vBuffer.flip(); IntBuffer ib = BufferUtils.createIntBuffer(2); glGenBuffersARB(ib); int vHandle = ib.get(0); int cHandle = ib.get(1); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vHandle); glBufferDataARB(GL_ARRAY_BUFFER_ARB, vBuffer, GL_STATIC_DRAW_ARB); glVertexPointer(3, GL_FLOAT, /* stride */3 << 2, 0L); glBindBufferARB(GL_ARRAY_BUFFER_ARB, cHandle); glBufferDataARB(GL_ARRAY_BUFFER_ARB, cBuffer, GL_STATIC_DRAW_ARB); glColorPointer(3, GL_FLOAT, /* stride */3 << 2, 0L); glDrawArrays(GL_TRIANGLES, 0, 3 /* elements */); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); // cleanup VBO handles ib.put(0, vHandle); ib.put(1, cHandle); glDeleteBuffersARB(ib); } static void render() { glClearColor(1, 1, 1, 1); Camera.acceptInput(0.6f); Camera.apply(); for (int i = 0; i < triangles.size(); i++) { // rysowanie trójkąta z modów... float s1[] = new float[6]; s1[0] = triangles.get(i).getFirstModPoint().getX(); s1[1] = triangles.get(i).getFirstModPoint().getY(); s1[2] = triangles.get(i).getFirstModPoint().getZ(); s1[3] = triangles.get(i).getFirstColor()[0]; s1[4] = triangles.get(i).getFirstColor()[1]; s1[5] = triangles.get(i).getFirstColor()[2]; float s2[] = new float[6]; s2[0] = triangles.get(i).getSecondModPoint().getX(); s2[1] = triangles.get(i).getSecondModPoint().getY(); s2[2] = triangles.get(i).getSecondModPoint().getZ(); s2[3] = triangles.get(i).getSecondColor()[0]; s2[4] = triangles.get(i).getSecondColor()[1]; s2[5] = triangles.get(i).getSecondColor()[2]; float s3[] = new float[6]; s3[0] = triangles.get(i).getThirdModPoint().getX(); s3[1] = triangles.get(i).getThirdModPoint().getY(); s3[2] = triangles.get(i).getThirdModPoint().getZ(); s3[3] = triangles.get(i).getThirdColor()[0]; s3[4] = triangles.get(i).getThirdColor()[1]; s3[5] = triangles.get(i).getThirdColor()[2]; drawVBOtriangle(s1, s2, s3); glTranslatef(triangles.get(i).getStartPoint().x - oldX, triangles.get(i).getStartPoint().y - oldY, triangles.get(i).getStartPoint().z - oldZ); oldX = triangles.get(i).getStartPoint().x; oldY = triangles.get(i).getStartPoint().y; oldZ = triangles.get(i).getStartPoint().z; } } public static Vector3f getDirection() { Vector3f vector = new Vector3f(); float rotX = Camera.getRotationX(); // pitch float rotY = Camera.getRotationY(); // yaw vector.y = (float) -Math.sin(Math.toRadians(rotY)); float h = (float) Math.cos(Math.toRadians(rotY)); vector.x = (float) (h * Math.sin(Math.toRadians(rotX))); vector.z = (float) (-h * Math.cos(Math.toRadians(rotX))); return vector; } EDIT: I rewrited the code and now i have ~250fps in 100x100 terrain. What should i did with coide to get more fps?
New code:
public class NGINE2 { public static int MAX_PICKING_DISTANCE = 20; public static int RAY_RADIUS = 5; static int w = 640; static int h = 480; static float oldX = 0; static float oldY = 0; static float oldZ = 0; static List<Triangle> triangles = new ArrayList<Triangle>(); static double[][]map; static FloatBuffer cBuffer = BufferUtils.createFloatBuffer(9*(100*100*2)); static FloatBuffer vBuffer = BufferUtils.createFloatBuffer(9*(100*100*2)); public static void main(String[] args) throws Exception { NoiseHeightMap nsh = new NoiseHeightMap(100, 23495876); nsh.HeightmapPNG(nsh.getHeightmap(), "C:\\Users\\Przemo\\Desktop\\mapka.png"); map = nsh.getHeightmap(); Random rand = new Random(); for (int x = 0; x < 100; x++) { for (int z = 0; z < 100; z++) { float rgb[] = new float[3]; rgb[0] = rand.nextFloat(); rgb[1] = rand.nextFloat(); rgb[2] = rand.nextFloat(); triangles.add(new Triangle(new Vector3f(x, (float) map[x][z]*100, z), new Vector3f(+0.5f, 1f, -0.5f), new Vector3f(-0.5f, 1f, -0.5f), new Vector3f(+0.5f, 1f, +0.5f), rgb, rgb, rgb)); triangles.add(new Triangle(new Vector3f(x, (float) map[x][z]*100, z), new Vector3f(-0.5f, 1f, +0.5f), new Vector3f(-0.5f, 1f, -0.5f), new Vector3f(+0.5f, 1f, +0.5f), rgb, rgb, rgb)); } } initContext(); renderLoop(); } static void initContext() throws Exception { Camera.create(); w = 640; h = 480; Display.setDisplayMode(new DisplayMode(w, h)); Display.setFullscreen(false); Display.create(); glViewport(0, 0, w, h); } static void renderLoop() { long time = 0; int frames = 0; for (int i = 0; i < triangles.size(); i++) { cBuffer.put(triangles.get(i).firstColor[0]).put(triangles.get(i).firstColor[1]).put(triangles.get(i).firstColor[2]); cBuffer.put(triangles.get(i).secondColor[0]).put(triangles.get(i).secondColor[1]).put(triangles.get(i).secondColor[2]); cBuffer.put(triangles.get(i).thirdColor[0]).put(triangles.get(i).thirdColor[1]).put(triangles.get(i).thirdColor[2]); vBuffer.put(triangles.get(i).firstModPoint.x).put(triangles.get(i).firstModPoint.y).put(triangles.get(i).firstModPoint.z); vBuffer.put(triangles.get(i).secondModPoint.x).put(triangles.get(i).secondModPoint.y).put(triangles.get(i).secondModPoint.z); vBuffer.put(triangles.get(i).thirdModPoint.x).put(triangles.get(i).thirdModPoint.y).put(triangles.get(i).thirdModPoint.z); } cBuffer.flip(); vBuffer.flip(); IntBuffer ib = BufferUtils.createIntBuffer(2); glGenBuffersARB(ib); int vHandle = ib.get(0); int cHandle = ib.get(1); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vHandle); glBufferDataARB(GL_ARRAY_BUFFER_ARB, vBuffer, GL_STATIC_DRAW_ARB); glVertexPointer(3, GL_FLOAT, /* stride */3 << 2, 0L); glBindBufferARB(GL_ARRAY_BUFFER_ARB, cHandle); glBufferDataARB(GL_ARRAY_BUFFER_ARB, cBuffer, GL_STATIC_DRAW_ARB); glColorPointer(3, GL_FLOAT, /* stride */3 << 2, 0L); while (!Display.isCloseRequested()) { preRender(); render(); Display.update(); Display.sync(6000 /* desired fps */); // Calc FPS frames++; if( ( System.currentTimeMillis() - time ) >= 1000 ) { Display.setTitle(" FPS: " + (int)((frames * 1000)/( System.currentTimeMillis() - time )) ); time = System.currentTimeMillis(); frames = 0; } } glDeleteBuffersARB(ib); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); ib.put(0, vHandle); ib.put(1, cHandle); Display.destroy(); } static void preRender() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLU.gluPerspective(45.0f, ((float) w / (float) h), 0.1f, 100.0f); // fix na błąd z kamerą glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static void render() { glClearColor(1, 1, 1, 1); Camera.acceptInput(0.6f); Camera.apply(); int Count = 2*100*100; for(int Index = 0; Index < Count; Index++) { glDrawArrays(GL_TRIANGLES, Index*3, 3); glTranslatef(triangles.get(Index).getStartPoint().x - oldX, triangles.get(Index).getStartPoint().y - oldY, triangles.get(Index).getStartPoint().z - oldZ); oldX = triangles.get(Index).getStartPoint().x; oldY = triangles.get(Index).getStartPoint().y; oldZ = triangles.get(Index).getStartPoint().z; } } }
