Hi!
I’m trying to test the instanced drawing extension of OpenGL on a basic example program and am desperately longing for help!
I have no experience using this extension and it is very likely that I have missed a vital point in using it…
Basicly the program prepares to draw a number of simple GL_QUADS by storing the information about the scene in the glVertexPointer-, glNormalPointer- and glIndexPointer-Buffers and then tries to draw them using the glDrawElementsInstancedEXT function of the javax.media.opengl.GL from the JOGL-lib in a simple opengl-environment.
For a number of 10000 vertices the view seams to be ok until - at some seamingly random point - the program crashes giving me nothing to go on as of where the problem lies… Also sometimes there are some very weird graphic bugs and the meshes are totally destroyed - I can’t make anything out of this…
It is probably best if I paste the code. Hopefully it is not a system problem and you find the problem in my coding.
Note that I am using no shaders - I don’t know if this is the reason.
Here the init-function… it basicaly establishes the environment settings and the view-matrices which allow navigation.
It calls myPrepare() at the end which calculates all the vertices and stores all the information about the scene into the buffers.
public void init(GLAutoDrawable drawable) {
gl= drawable.getGL();
gl.glClearColor(0.85f, 0.85f, 0.7f, 0.0f); // canvas background color
gl.glEnable(GL.GL_LIGHTING); // light enabled
gl.glEnable(GL.GL_LIGHT0);
gl.glClearDepth(1.0); // depth testing enabled
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glEnable(GL.GL_COLOR_MATERIAL); //enable some material characteristics
gl.glColorMaterial(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE);
gl.glShadeModel(GL.GL_SMOOTH); // enable smooth color shading
float light_ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f }; // ambient light
float light_diffuse[] = { 0.3f, 0.3f, 0.3f, 1.0f }; // diffuse light
float light_specular[] = { 0.4f, 0.4f, 0.4f, 1.0f }; // specular light
float shininess[] = {100.0f};
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, light_specular,0); // material characteristics
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, shininess,0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, light_ambient,0); // adding the different light
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, light_diffuse,0); // parts to the light model
gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, light_specular,0);
float light_position[] = {leftx, 0.0f, -dist, 1.0f }; // light position
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, light_position,0); // headlight
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, +600);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewTransNeg,0);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -600);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewAll,0);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewTrans,0);
myPrepare();
}
Here myPrepare()… note that if you variate ‘range’ you will get more quads. The program crashes at a range of 4000 instantly after running and runs at a range of 2000 for duration of about 30 seconds (seams to be random).
myPrepare() calls the myPlaneArrays() function which calculates the vertices and normals for a quad and returns them as an ArrayList-collection.
IntBuffer indexBuffer;
int elements;
ArrayList<Float> vertices= new ArrayList<Float>();
ArrayList<Float> normals= new ArrayList<Float>();
private void myPrepare() {
int range= 2000;
float step= 250f;
MyArrayElements myArrays;
for (float x= -range; x < range; x+= step) {
for (float y= -range; y < range; y+= step) {
myArrays= myPlaneArrays(x,y,0,100.0f);
vertices.addAll(myArrays.vertices);
normals.addAll(myArrays.normals);
}
}
// create buffers...
FloatBuffer vertexBuffer = BufferUtil.newFloatBuffer(vertices.size());
for (int i= 0; i < vertices.size(); i++)
vertexBuffer.put(i,vertices.get(i));
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuffer);
FloatBuffer normalBuffer = BufferUtil.newFloatBuffer(normals.size());
for (int i= 0; i < normals.size(); i++)
normalBuffer.put(i,normals.get(i));
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glNormalPointer(GL.GL_FLOAT, 0, normalBuffer);
elements= vertices.size()/3;
indexBuffer= BufferUtil.newIntBuffer(elements);
for (int i= 0; i < elements; i++)
indexBuffer.put(i,i);
gl.glEnableClientState(GL.GL_INDEX_ARRAY);
gl.glIndexPointer(GL.GL_UNSIGNED_INT, 0, indexBuffer);
System.out.println("prepare done.");
System.out.println("vertices.size= "+vertices.size());
}
Here myPlaneArrays()… MyArrayElements is a simple class which contains the ArrayLists for vertices, normals, colors and indices (colors and indices are not used atm).
private MyArrayElements myPlaneArrays(float x0, float y0, float z0, float size) {
ArrayList<Float> vertices= new ArrayList<Float>();
ArrayList<Float> normals= new ArrayList<Float>();
ArrayList<Float> colors= new ArrayList<Float>();
ArrayList<Integer> indices= new ArrayList<Integer>();
Integer s= 0;
normals.add(0.0f);
normals.add(0.0f);
normals.add(1.0f);
vertices.add(x0+ -size);
vertices.add(y0+ -size);
vertices.add(z0+ 0.0f);
vertices.add(x0+ size);
vertices.add(y0+ -size);
vertices.add(z0+ 0.0f);
vertices.add(x0+ size);
vertices.add(y0+ size);
vertices.add(z0+ 0.0f);
vertices.add(x0+ -size);
vertices.add(y0+ size);
vertices.add(z0+ 0.0f);
return new MyArrayElements(vertices, normals, colors, indices);
}
Here comes the display routine which essentially establishes the view, controlls navigation and the calls the myDrawing() routine in which the instance extension is used.
public void display(GLAutoDrawable drawable) {
gl= drawable.getGL();
/**
* VIEWPORT
*/
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, this.getSize().width, this.getSize().height); // reset the current viewport and perspective transformation
gl.glGetIntegerv(GL.GL_VIEWPORT, vp, 0);
gl.glMatrixMode(GL.GL_PROJECTION);// select the projection matrix
gl.glLoadIdentity();
gl.glFrustum(-0.25, 0.25, -0.25, 0.25, 1.0, 10000.0);
/**
* ANSICHT
*/
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadMatrixf(viewTrans,0);
gl.glTranslatef(leftx, upy, -dist);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewTrans,0);
gl.glRotatef(rotx, 1, 0, 0);
gl.glMultMatrixf(viewTransNeg,0);
gl.glMultMatrixf(viewAll,0);
gl.glRotatef(rotz, 0, 0, 1);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewAll,0);
gl.glLoadMatrixf(viewTransNeg,0);
gl.glTranslatef(-leftx, -upy, dist);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, viewTransNeg,0);
gl.glLoadMatrixf(viewAll,0);
resetViewVars();
/**
* DRAWING
*/
myDrawing();
gl.glFinish();
gl.glFlush();
}
And here the myDrawing() function which only calls uppon the glDrawElementsInstancedEXT routine. Note that the first 3 if-clauses do not print out the warnings - the buffers are active at this point.
private void myDrawing() {
if (!gl.glIsEnabled(GL.GL_VERTEX_ARRAY)) System.out.println("! GL_VERTEX_ARRAY nicht aktiv !");
if (!gl.glIsEnabled(GL.GL_NORMAL_ARRAY)) System.out.println("! GL_NORMAL_ARRAY nicht aktiv !");
if (!gl.glIsEnabled(GL.GL_INDEX_ARRAY)) System.out.println("! GL_INDEX_ARRAY nicht aktiv !");
gl.glDrawElementsInstancedEXT(GL.GL_QUADS, elements, GL.GL_UNSIGNED_INT, indexBuffer, 16);
}
I hope you can make some sense of my coding.
Feel free to ask me questions if anything is unclear.
I am most happy for ANY INSIGHT on the matter!!!
Oh, almost forgot my system information:
- WinXP-Prof SP2
- 2.6GHz dual core
- NVIDIA GeForce 8600GT with newest drivers
Thank you so much for reading this!
Regards,
Daniel