PDA

View Full Version : Heightmap render order performance



Florian
05-02-2012, 03:04 PM
Hello,
I render a textured heightmap in OpenGL but the performance is too bad, because I calculate at each redraw the whole render order of 240x240 pixels (and that many times).
The performance of one chunk is good, but if i duplicate the loop to test the performance for later, the performance is too bad.

Here is a plan how i calculate the render order of one chunk:
697
X in the middle = Player position, the red box the heightmap border, the arrows and numbers are the order, and then there are the 2 black axis that build the cross.

and the code to draw it:


hmt.getTexture().bind(gl);
gl.glCullFace(GL.GL_FRONT);
for(int i = 0; i < (int)(cam1.getXPos() * 10); i++){
gl.glBegin(GL.GL_TRIANGLE_STRIP);
for(int j = 0; j <= (int)((cam1.getZPos()) * 10); j++){
gl.glTexCoord2f((float)i / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)i / 10, (float)hm.getData(i, j) / 100 - 10, (float)j / 10);
gl.glTexCoord2f((float)(i+1) / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i+1) / 10, (float)hm.getData(i+1, j) / 100 - 10, (float)j / 10);
}
gl.glEnd();
}

for(int i = 238; i > (int)(cam1.getXPos() * 10); i--){
gl.glBegin(GL.GL_TRIANGLE_STRIP);
for(int j = 239; j > (int)((cam1.getZPos()) * 10); j--){
gl.glTexCoord2f((float)(i+1) / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i+1) / 10, (float)hm.getData(i+1, j) / 100 - 10, (float)j / 10);
gl.glTexCoord2f((float)i / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i) / 10, (float)hm.getData(i, j) / 100 - 10, (float)j / 10);
}
gl.glEnd();
}

gl.glCullFace(GL.GL_BACK);

for(int i = 0; i <= (int)(cam1.getXPos() * 10); i++){
gl.glBegin(GL.GL_TRIANGLE_STRIP);
for(int j = 239; j >= (int)((cam1.getZPos()) * 10); j--){
gl.glTexCoord2f((float)i / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)i / 10, (float)hm.getData(i, j) / 100 - 10, (float)j / 10);
gl.glTexCoord2f((float)(i+1) / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i+1) / 10, (float)hm.getData(i+1, j) / 100 - 10, (float)j / 10);
}
gl.glEnd();
}

for(int i = 238; i >= (int)(cam1.getXPos() * 10); i--){
gl.glBegin(GL.GL_TRIANGLE_STRIP);
for(int j = 0; j <= (int)((cam1.getZPos()) * 10)+1; j++){
gl.glTexCoord2f((float)(i+1) / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i+1) / 10, (float)hm.getData(i+1, j) / 100 - 10, (float)j / 10);
gl.glTexCoord2f((float)i / 239.0f, (float)j / 240.0f);
gl.glVertex3f((float)(i) / 10, (float)hm.getData(i, j) / 100 - 10, (float)j / 10);
}
gl.glEnd();
}

Is there a better way to do this?

ZbuffeR
05-02-2012, 04:12 PM
1) if you care about performance, do not use glBegin/glEnd. Search for VBO tutorials : http://www.opengl.org/wiki/Vertex_Buffer_Object
2) it is actually better for fillrate to draw front to back, so that a nearby mountain will optimize away all the costly shaders of distant hills.

Florian
05-03-2012, 11:38 AM
Ok thanks ZbuffeR for the answer i will try the vob, but if I draw from front to back, then i see the back hills instead of the front hills :confused:.
Or do I have to use a special shader / buffer / ? for this?

menzel
05-03-2012, 12:38 PM
Enable the depth test: glEnable(GL_DEPTH_TEST), it will take care that only the front-most object gets drawn independent of the rendering order.
ZbufferR is right, that rendering front to back will reduce overdraw and thus increase perfomance - but only if the sorting isn't more complex than the increase you get. Try rendering without any sorting and a VBO first. Even if overdraw becomes a problem, sorting on a triangle-level might be too much.