Hello,
I am speeding the display of animations in a java application that simulate the evolution of a plant cells in 3D dimensions .the cells are the elements of an octree. Each cell is a cube with 4 possibles colors . I'm using VBO. The thing is that the refreshing of the view is made every unity of cycles ( determined by the user ) and every unity of cycles for example 5 the cache ( containing the cells ) is sent to the GPU in order to display the new model ( cells are added in every cycle based on the modele of evolution the user choose ) so every cycle the cache gets more big leading to slowing the display in a lot of cases . I have been thinking that i can send only the new celles created in the last unity of cycles to the GPU but then how to display the old ones once the refresh is made ? here is the code responsable for updating the VBO : private void updateBuffers(GL2 gl) { /** * Cache is used as intermediate between a {@link NTree} and a OpenGL * manager to convert model data in {@link CellQuadBuffer}s to be used by OpenGL * drawing methods. */ synchronized (cache) { minPoint = (cache.getMinPoint() == null)? new Vector3d() : new Vector3d(cache.getMinPoint()); maxPoint = (cache.getMaxPoint() == null)? new Vector3d() : new Vector3d(cache.getMaxPoint()); int[] gpuBuffers; /** * CellQuadBuffer stores {@link Cell}s in {@link Buffer}s and in a format usable by * OpenGL. * <p> * {@link Cell}s are represented to match the OpenGL GL_QUADS primitive shape, * with their unique color. </br> The outlines color of a cube is the inverse of * the color of this cube (except that the alpha value is the same). */ List<CellQuadBuffer> oldList = listBuffers; listBuffers = new ArrayList<>(cache.getCellBuffers()); Buffer vertices, colors, outlinesColors, indices; if (vboEnabled) { for (CellQuadBuffer cb : oldList) { // delete existing buffers gpuBuffers = new int[] { cb.gpuBufferVertices, cb.gpuBufferColors, cb.gpuBufferIndices, cb.gpuBufferOutlinesColors }; gl.glDeleteBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); } oldList.clear(); for (CellQuadBuffer cb : listBuffers) { // generate new buffers gpuBuffers = new int[] { cb.gpuBufferVertices, cb.gpuBufferColors, cb.gpuBufferIndices, cb.gpuBufferOutlinesColors }; gl.glDeleteBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); gl.glGenBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); cb.gpuBufferVertices = gpuBuffers[0]; cb.gpuBufferColors = gpuBuffers[1]; cb.gpuBufferIndices = gpuBuffers[2]; cb.gpuBufferOutlinesColors = gpuBuffers[3]; vertices = cb.getVertices(); colors = cb.getColors(); outlinesColors = cb.getOutlinesColors(); indices = cb.getIndices(); // vertex buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, cb.gpuBufferVertices); gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices.capacity() * Buffers.sizeOfBufferElem(vertices), vertices, GL.GL_STATIC_DRAW); // color buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, cb.gpuBufferColors); gl.glBufferData(GL.GL_ARRAY_BUFFER, colors.capacity() * Buffers.sizeOfBufferElem(colors), colors, GL.GL_STATIC_DRAW); // outlines color buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, cb.gpuBufferOutlinesColors); gl.glBufferData(GL.GL_ARRAY_BUFFER, outlinesColors.capacity() * Buffers.sizeOfBufferElem(outlinesColors), outlinesColors, GL.GL_STATIC_DRAW); // indices buffer gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, cb.gpuBufferIndices); gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * Buffers.sizeOfBufferElem(indices), indices, GL.GL_STATIC_DRAW); cb.resetBuffer(); } } cache.resetData(); cache.dataUsed(); } } Thank you . |
Administrator
|
Hi
The synchronization might cause noticeable slowdowns. You should follow the advises I gave you on StackOverflow. Use glBufferSubData or glMapBufferRange to update only a part of your VBO, the performance depends on the hardware.
Julien Gouesse | Personal blog | Website
|
Hi ,
I tried to modify the code and use glBufferSubData but when i run nothing is drawed . In my code the cells are stored into a list of buffers ( created in Class cache) every buffer contains 4 principla attributs (vertices , colors , outline colors , indices ) each buffer contains stores many cells . the original code of the method UpdateBuffers is sending every time the contents of each buffer from the list to the gpu with GlBufferData ( used 4 times ; one time for each attribut of the buffer ) . I thought i can create from the begining one big space for every attribute ( vertices , colors , outline colors , indices ) with GLBuffer data and then use GLBufferSubData to send just the new cells to the GPU . Here is my code for the method : updateBuffers ---------- private void updateBuffers(GL2 gl) { synchronized (cache) { minPoint = (cache.getMinPoint() == null)? new Vector3d() : new Vector3d(cache.getMinPoint()); maxPoint = (cache.getMaxPoint() == null)? new Vector3d() : new Vector3d(cache.getMaxPoint()); int[] gpuBuffers; List<CellQuadBuffer> oldList = listBuffers; listBuffers = new ArrayList<>(cache.getCellBuffers()); Buffer vertices, colors, outlinesColors, indices; if (vboEnabled) { for (CellQuadBuffer cb : oldList) { // delete existing buffers gpuBuffers = new int[] { cb.gpuBufferVertices, cb.gpuBufferColors, cb.gpuBufferIndices, cb.gpuBufferOutlinesColors }; gl.glDeleteBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); } oldList.clear(); for (CellQuadBuffer cb : listBuffers) { if (i==0) { // generate new buffers gpuBuffers = new int[] { 0,1, 2, 3 }; gl.glDeleteBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); gl.glGenBuffers(CellQuadBuffer.NUMBER_OF_BUFFERS, IntBuffer.wrap(gpuBuffers)); cb.gpuBufferVertices = gpuBuffers[0]; cb.gpuBufferColors = gpuBuffers[1]; cb.gpuBufferIndices = gpuBuffers[2]; cb.gpuBufferOutlinesColors = gpuBuffers[3]; } vertices = cb.getVertices(); colors = cb.getColors(); outlinesColors = cb.getOutlinesColors(); indices = cb.getIndices(); // vertex buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); if (i==0) { gl.glBufferData(GL.GL_ARRAY_BUFFER, vertices.capacity() * Buffers.sizeOfBufferElem(vertices)*10, vertices, GL.GL_STATIC_DRAW); offsetPosition1 = vertices.capacity() * Buffers.sizeOfBufferElem(vertices); } else { gl.glBufferSubData(GL.GL_ARRAY_BUFFER,offsetPosition1, vertices.capacity() * Buffers.sizeOfBufferElem(vertices), vertices); offsetPosition1 = offsetPosition1 + vertices.capacity() * Buffers.sizeOfBufferElem(vertices); } // color buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 1); if (i == 0) { gl.glBufferData(GL.GL_ARRAY_BUFFER, colors.capacity() * Buffers.sizeOfBufferElem(colors)*10, colors, GL.GL_STATIC_DRAW); offsetPosition2 = colors.capacity() * Buffers.sizeOfBufferElem(colors); } else { gl.glBufferSubData(GL.GL_ARRAY_BUFFER,offsetPosition2, colors.capacity() * Buffers.sizeOfBufferElem(colors), colors); offsetPosition2 = offsetPosition2 + colors.capacity() * Buffers.sizeOfBufferElem(colors); } // outlines color buffer gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 2); if (i == 0) { gl.glBufferData(GL.GL_ARRAY_BUFFER, outlinesColors.capacity() * Buffers.sizeOfBufferElem(outlinesColors)*10, outlinesColors, GL.GL_STATIC_DRAW); offsetPosition3 = outlinesColors.capacity() * Buffers.sizeOfBufferElem(outlinesColors); } else { gl.glBufferSubData(GL.GL_ARRAY_BUFFER,offsetPosition3, outlinesColors.capacity() * Buffers.sizeOfBufferElem(outlinesColors), outlinesColors); offsetPosition3 = offsetPosition3 + outlinesColors.capacity() * Buffers.sizeOfBufferElem(outlinesColors); } // indices buffer gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 3); if (i== 0) { gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * Buffers.sizeOfBufferElem(indices)*10, indices, GL.GL_STATIC_DRAW); offsetPosition4 = indices.capacity() * Buffers.sizeOfBufferElem(indices); i=1; } else { gl.glBufferSubData(GL.GL_ELEMENT_ARRAY_BUFFER,offsetPosition4, indices.capacity() * Buffers.sizeOfBufferElem(indices), indices); System.out.println("ici"); offsetPosition4=offsetPosition4 + indices.capacity() * Buffers.sizeOfBufferElem(indices); } cb.resetBuffer(); } } cache.resetData(); cache.dataUsed(); } } ============== And this is the code responsible for the drawing : public void display(GLAutoDrawable gLDrawable) { long start = System.nanoTime(); int nbIndicesTotal=0; GL2 gl = gLDrawable.getGL().getGL2(); if (cache.isDataChanged()) { updateBuffers(gl); } // erase display and clear buffers gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); gl.glMultMatrixd(camera.getViewCopy(), 0); // Transparence if (transparencyEnabled) { gl.glDisable(GL.GL_DEPTH_TEST); gl.glEnable(GL.GL_BLEND); } else { gl.glEnable(GL.GL_DEPTH_TEST); gl.glDisable(GL.GL_BLEND); } if (drawDebug) { drawReferenceAxes(gl); drawCubeEdges(gl, minPoint, maxPoint); } // enable and specify pointer to vertex and color array gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY); gl.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY); //Buffer vertices, colors, outlinesColors, indices; for (CellQuadBuffer cb : listBuffers) { nbIndicesTotal = nbIndicesTotal + cb.getNbIndices() ; } if (vboEnabled) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); gl.glVertexPointer(CellQuadBuffer.NB_COORDINATES_PER_VERTEX, GL.GL_FLOAT, 0, 0); gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 1); gl.glColorPointer(CellQuadBuffer.NB_COLORS_PER_VERTEX, GL.GL_UNSIGNED_BYTE, 0, 0); // Link the buffer gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 3); gl.glDrawElements(GL2.GL_QUADS, nbIndicesTotal, GL.GL_UNSIGNED_INT, 0); if (outlineVisible) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 2); gl.glColorPointer(CellQuadBuffer.NB_COLORS_PER_VERTEX, GL.GL_UNSIGNED_BYTE, 0, 0); gl.glDrawElements(GL2.GL_LINES, nbIndicesTotal, GL.GL_UNSIGNED_INT, 0); } } /*else { if (cb.getVertices().capacity() > 0) { // Vertex arrays gl.glVertexPointer(CellQuadBuffer.NB_COORDINATES_PER_VERTEX, GL.GL_FLOAT, 0, cb.getVertices()); gl.glColorPointer(CellQuadBuffer.NB_COLORS_PER_VERTEX, GL.GL_UNSIGNED_BYTE, 0, cb.getColors()); gl.glDrawElements(GL2.GL_QUADS, cb.getIndices().capacity(), GL.GL_UNSIGNED_INT, cb.getIndices()); if (outlineVisible) { gl.glColorPointer(CellQuadBuffer.NB_COLORS_PER_VERTEX, GL.GL_UNSIGNED_BYTE, 0, cb.getOutlinesColors()); gl.glDrawElements(GL2.GL_LINES, cb.getIndices().capacity(), GL.GL_UNSIGNED_INT, cb.getIndices()); } } }*/ // disable vertex and color arrays after drawing gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY); gl.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY); gl.glFlush(); fireDisplayUpdated(); if (debug) { Logger.getGlobal().finest("total time for display(): " + (System.nanoTime() - start) / 1000 + "µs"); } } ====================== i hope you can help me , i'm really stuck here . Thank you for your replies and time . |
Administrator
|
Have you even succeeded in using glBufferSubData on a simple example first?
Julien Gouesse | Personal blog | Website
|
I didn't use it myself but i saw a few examples and read the documentation about how it works . i'm really pressed for time and i believe the code i put should work but i don't understand why nothing is displayed . i'll really appreciate any help , thanks .
|
Free forum by Nabble | Edit this page |