Z-Knight
Full Member   Posts: 234
|
 |
«
on:
2008-05-28 14:39:47 » |
|
Because I've not been able to find completely working examples that show the use of VBOs with vertices and normals, etc I decided to list some snippets of code here from I finally was able to get to work. I hope this is helpful to others. I'll try to explain what needs to occur where and what things mean as best as I could decipher them. BTW, I am trying to improve the renderer in the 3DS part of JOGLUTILS so this is related to the 3DS structures that I have. 3DS files contain 'objects' which each object has arrays of vertices and arrays of normals, textures and materials/colors. So, for VBO the first thing is the generation of the VBO themselves. So say you have some 'objects' that have a size of 'objects.size()', well you want to create a VBO for each of the objects...actually since we want normals, vertices, colors, and textures we have to create 4 VBOs for each object. This code simply creates the necessary VBO ids and generates the necessary buffers. You would do this in the 'init()' method, typically. Note, there are routines to check if VBOs are available for use on the current machine but I've not listed this check here. 1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private int VBO[] = null;
VBO = new int[objects.size()*4];
gl.glGenBuffers(objects.size()*4, VBO, 0); |
Now we need to populate the VBOs in the init() method. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| private FloatBuffer vertices, normals, textures, colors;
for (int i=0; i<objects.size(); i++) { Obj tempObj = objects.get(i);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i]);
int totalBufferSize = tempObj.numOfFaces*3*3; vertices = FloatBuffer.allocate(totalBufferSize);
for (int j=0; j<tempObj.numOfFaces; j++) { for (int whichVertex=0; whichVertex<3; whichVertex++) { int index = tempObj.faces[j].vertIndex[whichVertex];
vertices.put(tempObj.verts[index].x); vertices.put(tempObj.verts[index].y); vertices.put(tempObj.verts[index].z); } }
vertices.rewind();
gl.glBufferData(GL.GL_ARRAY_BUFFER, totalBufferSize *4, vertices, GL.GL_STATIC_DRAW);
vertices = null;
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+1]);
totalBufferSize = tempObj.numOfFaces*3*3; normals = FloatBuffer.allocate(totalBufferSize);
for (int j=0; j<tempObj.numOfFaces; j++) { for (int whichVertex=0; whichVertex<3; whichVertex++) { int index = tempObj.faces[j].vertIndex[whichVertex];
normals.put(tempObj.normals[index].x); normals.put(tempObj.normals[index].y); normals.put(tempObj.normals[index].z); } }
normals.rewind();
gl.glBufferData(GL.GL_ARRAY_BUFFER, totalBufferSize *4, normals, GL.GL_STATIC_DRAW);
normals = null;
if(tempObj.hasTexture) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+2]);
totalBuffer = (tempObj.numOfFaces*3*2);
textures = ByteBuffer.allocateDirect(totalBuffer*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
for (int j=0; j<tempObj.numOfFaces; j++) { for (int whichVertex=0; whichVertex<3; whichVertex++) { int index = tempObj.faces[j].vertIndex[whichVertex];
textures.put(tempObj.texVerts[index].x); textures.put(tempObj.texVerts[index].y); } }
textures.rewind();
gl.glBufferData(GL.GL_ARRAY_BUFFER, totalBuffer*4, textures, GL.GL_STATIC_DRAW);
textures = null; }
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+3]);
totalBufferSize = tempObj.numOfFaces*3*3; colors = FloatBuffer.allocate(totalBufferSize);
for (int j=0; j<tempObj.numOfFaces; j++) { if (tempObj.faces[j].materialID < materials.size()) { byte aColor[] = materials.get(tempObj.faces[j].materialID).color; float R = inttofloat(unsignedByteToInt(aColor[0])); float G = inttofloat(unsignedByteToInt(aColor[1])); float B = inttofloat(unsignedByteToInt(aColor[2]));
colors.put(R); colors.put(G); colors.put(B); colors.put(R); colors.put(G); colors.put(B); colors.put(R); colors.put(G); colors.put(B); } else { for (int z=0; z<9; z++) { colors.put(1.0f); } } }
colors.rewind();
gl.glBufferData(GL.GL_ARRAY_BUFFER, totalBufferSize*4, colors, GL.GL_STATIC_DRAW);
colors = null; } |
|
|
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #1 on:
2008-05-28 14:44:11 » |
|
Note that in the code above we bound the buffer for the vertices first, then we added the vertices to the vertex buffer and finally added buffer to the VBO using the glBufferData() call. And then we did the same for the normals but we did it separately....yes, you could create the buffers together but you need to perform the glBindBuffer() and glBufferData() separtely for the vertices and normals...ie: glBindBuffer(vertices) glBufferData(vertices) glBindBuffer(normals) glBufferData(normals) And NOT the following (had me stuck for a while...the glBindBuffer() basically tells the system which is the current buffer that we are working with. glBindBuffer(vertices) glBindBuffer(normals) glBufferData(vertices) glBufferData(normals) OK, so now we've created the VBOs and we are ready for rendering....again, note that in my case I have several objects and so I will loop through each object to render: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| gl.glEnableClientState(GL.GL_NORMAL_ARRAY); gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
for (int i=0; i<objects.size(); i++) { Obj tempObj = objects.get(i); int numFaceIndices = tempObj.numOfFaces*3;
gl.glColor3f(1.0f, 1.0f, 1.0f); gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_COLOR_MATERIAL);
if(tempObj.hasTexture) { gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture[tempObj.materialID].getTextureObject()); gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+2]); gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
} else { gl.glEnableClientState(GL.GL_COLOR_ARRAY); gl.glEnable(GL.GL_COLOR_MATERIAL); gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+3]);
gl.glColorPointer(3, GL.GL_FLOAT, 0, 0); }
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+1]); gl.glNormalPointer(GL.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i]); gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); if (fill) { gl.glDrawArrays(GL.GL_TRIANGLES, 0, numFaceIndices); } else { gl.glDrawArrays(GL.GL_LINE_LOOP, 0, numFaceIndices); }
if(tempObj.hasTexture) { gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); } else { gl.glDisableClientState(GL.GL_COLOR_ARRAY); } }
gl.glDisableClientState(GL.GL_NORMAL_ARRAY); gl.glDisableClientState(GL.GL_VERTEX_ARRAY); |
btw, yes I know there are examples in the DEMO code but some examples I found are just too darn complicated to understand, some mix and match using the "_ARB" suffixes which people should know that the "_ARB" are no different than the calls withouth the "_ARB"...I believe the with "_ARB" calls were old version that were not in the main spec so they were experimental (so I've read somewhere). If anyone has corrections to anything I wrote then I would appreciate those comments - if you want to criticize me then keep those comments to yourself. 
|
|
|
|
|
Chris61182
Full Member   Posts: 168
|
 |
«
Reply #2 on:
2008-05-29 01:38:11 » |
|
btw, yes I know there are examples in the DEMO code but some examples I found are just too darn complicated to understand I'm a real big fan of supper simple tests and example myself, so thank you very much.
|
|
|
|
|
Games published by our own members! Go get 'em!
|
|
Riven
« League of Dukes » JGO Kernel      Posts: 5509 Medals: 204
Hand over your head.
|
 |
«
Reply #3 on:
2008-05-29 04:45:24 » |
|
For decent performance, change FloatBuffer.allocate(totalBufferSize) into BufferUtils.createFloatBuffer(totalBufferSize) which is a util-method for ByteBuffer.allocateDirect(bytes*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
Hi, appreciate more people! Σ ♥ = ¾ Learn how to award medals... and work your way up the social rankings
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #4 on:
2008-05-29 11:16:21 » |
|
For decent performance, change FloatBuffer.allocate(totalBufferSize) into BufferUtils.createFloatBuffer(totalBufferSize) which is a util-method for ByteBuffer.allocateDirect(bytes*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
What's the import for the 'BufferUtils' that you suggest?
|
|
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #5 on:
2008-05-30 12:03:59 » |
|
ok...finally figured out colors and textures so I'm updating the first and second post to include that info.
btw...we need to increase the message limit on these forums from 10,000 characters to something more (not just 10,001)....I have to freaking split my message over multiple posts and it is annoying to try to limit yourself to 10,000 (actually less since there is other html characters that are filled in for you that you normally don't count but the forum does.
|
|
|
|
|
gouessej
JGO Kernel      Posts: 3433 Medals: 26
TUER
|
 |
«
Reply #6 on:
2008-06-06 01:18:46 » |
|
What's the import for the 'BufferUtils' that you suggest?
That's rather this: com.sun.opengl.util.BufferUtil An example from the source code of TUER: StaticVertexBufferObject(GL gl,float[] array){ this.mode=GL.GL_TRIANGLES; this.gl=gl; this.buffer=BufferUtil.newFloatBuffer(array.length); this.buffer.put(array); this.buffer.position(0); this.id=new int[1]; gl.glGenBuffersARB(1,id,0); gl.glBindBufferARB(GL.GL_ARRAY_BUFFER,id[0]); gl.glBufferDataARB(GL.GL_ARRAY_BUFFER,BufferUtil.SIZEOF_FLOAT*buffer.capacity(),buffer,GL.GL_STATIC_DRAW_ARB); this.buffer.position(0); } If you plan to use VBO, treat the case of it unavailability too...
|
Julien Gouesse
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #7 on:
2008-06-09 10:56:17 » |
|
I do check for VBO unavailability...I simply do this: 1 2 3 4 5 6 7 8
| VBOSupported = gl.isFunctionAvailable("glGenBuffers") && gl.isFunctionAvailable("glBindBuffer") && gl.isFunctionAvailable("glBufferData") && gl.isFunctionAvailable("glDeleteBuffers");
if (VBOSupported) { } |
|
|
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #8 on:
2008-06-16 12:21:47 » |
|
Regarding the creation of VBOs in general has anyone had worse performance on a MAC (10.4)? In windows and Linux my VBO loader works fast, but on a MAC it works horribly slow...not the rendering but the creation part (the part in the init() code).
Every init() call rebuilds the VBOs and for some reason it is just horrible. I can't seem to run the Netbeans profiler on it either because it gives an exception on whatever code I run (so I know this is a netbeans profiler issue and not code issue).
Not sure what else to do here....anyone?
|
|
|
|
|
gouessej
JGO Kernel      Posts: 3433 Medals: 26
TUER
|
 |
«
Reply #9 on:
2008-06-17 13:28:21 » |
|
Are you sure it is because of MAC? Which graphics card do you have?
|
Julien Gouesse
|
|
|
Games published by our own members! Go get 'em!
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #10 on:
2008-06-17 14:56:30 » |
|
Are you sure it is because of MAC? Which graphics card do you have?
I can't be 100% sure but I have no reason to suspect anything else. I don't personally have a MAC so this is tested on two MAC laptops of my co-workers and I don't have the specs...I only know that these two MAC laptops were purchased about 6-9 months ago and at the time were the most expensive MACs with the best available graphics cards and 2 GB of RAM. That's not saying much but this is all I have as far as info right now. I'm using the exact same JOGL release on MAC, Windows and Enterprise Linux (64) and only the MAC has huge slowdowns in creating the VBOs. I obviously need to do some more testing to narrow down the problem so I'm sorry if I asked a question without having all the necessary information for you at this time.
|
|
|
|
|
gouessej
JGO Kernel      Posts: 3433 Medals: 26
TUER
|
 |
«
Reply #11 on:
2008-06-18 06:58:28 » |
|
I can't be 100% sure but I have no reason to suspect anything else. I don't personally have a MAC so this is tested on two MAC laptops of my co-workers and I don't have the specs...I only know that these two MAC laptops were purchased about 6-9 months ago and at the time were the most expensive MACs with the best available graphics cards and 2 GB of RAM. That's not saying much but this is all I have as far as info right now. I'm using the exact same JOGL release on MAC, Windows and Enterprise Linux (64) and only the MAC has huge slowdowns in creating the VBOs.
I obviously need to do some more testing to narrow down the problem so I'm sorry if I asked a question without having all the necessary information for you at this time.
Please check they use an Intel graphics cards. I'm very worried as I use VBOs too and I don't want Mac users to have bad performance.
|
Julien Gouesse
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #12 on:
2008-06-18 14:31:24 » |
|
Please check they use an Intel graphics cards. I'm very worried as I use VBOs too and I don't want Mac users to have bad performance.
they have the nVIDIA GeForce 8600M GT 256MB. I'm waiting for them to upgrade to using Leopard OS so that they can get the latest Java and be able to run the Netbeans profiler correctly so I can see where my problem is occurring. Either the issue is with the graphics card or something to do with the VBOs. At one time I thought they ran my initial VBO code that didn't include textures and colors and it was fine so I'm going to try and temporarily remove those 2 VBOs out and see if that improves their performance.
|
|
|
|
|
bpeck
JGO n00b  Posts: 17
|
 |
«
Reply #13 on:
2008-06-18 15:07:07 » |
|
I am using VBOs on OS X 10.5 with a ATI X1600 card (MacBook Pro), and I haven't noticed any performance problems
|
|
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #14 on:
2008-06-18 16:31:45 » |
|
I am using VBOs on OS X 10.5 with a ATI X1600 card (MacBook Pro), and I haven't noticed any performance problems
Ok, I have to clarify because I did some more investigation and it turns out that it is not the loading that is the cause but that doesn't mean I know the reason yet. Since I don't have a profiler capability right now I had my co-workers comment things as out as we went to try to see the slowdown. The initialization and creation of the VBOs is fast so that is not the problem. The rendering is where I get the slowdown...except that this happens only ONCE - the first rendering call and not subsequent calls and also after an init() it happens again just once. It makes no sense to me yet so anyone with VBO knowledge please chime in. The following code is what I have in my rendering loop that gets called by the display() method repeatedly, and as I said, only the very first time this rendering method is called do I have the huge slowdown. Also, when closing the application, I have a huge slowdown before the application actually closes (MAC only as well). I'm guessing the first is do the buffer binding? though not sure why this happens only on the first time, and the closing delay is due to the release of the buffers? Note that I do not do anything yet with releasing the buffers or clearing them, etc, I just let them die off. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| render(GL gl) { ... gl.glEnableClientState(GL.GL_NORMAL_ARRAY); gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
for (int i=0; i<objects.size(); i++) {
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i+1]); gl.glNormalPointer(GL.GL_FLOAT, 0, 0); gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[4*i]); gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
if (fill) { gl.glDrawArrays(GL.GL_TRIANGLES, 0, numFaceIndices); } else { gl.glDrawArrays(GL.GL_LINE_LOOP, 0, numFaceIndices); } }
gl.glDisableClientState(GL.GL_VERTEX_ARRAY); gl.glDisableClientState(GL.GL_NORMAL_ARRAY); ... } |
Again, this only happens on a MAC...and not on Windows or Linux (using the same JOGL release 1.1.1)
|
|
|
|
|
bpeck
JGO n00b  Posts: 17
|
 |
«
Reply #15 on:
2008-06-20 11:02:19 » |
|
Your render code looks ok, I would suggest binding your buffer to 0 once you are done with VBOs, but thats really all i can come up with. I don't have that much knowledge of the inner workings of VBOs or what wacky stuff apple is up to in their OpenGL drivers, so I can't really be of any service here.
|
|
|
|
|
Z-Knight
Full Member   Posts: 234
|
 |
«
Reply #16 on:
2008-06-20 11:49:02 » |
|
thanks for the info.
I'm wondering if it has something to do with the MAC having Opengl 1.5 while on my PC and Linux I have OpenGL 2.0+
Also, I was thinking the issue may have been my code because I believe an previous version that didn't include the colors/textures buffers seemed to work on the MAC fine though the 3DS model being loaded was likely a smaller one so that may be just be a perception issue.
I'm still kind of curious why the first time rendering the effect would cause a delayed response and a delay in rendering but not all subsequent rendering calls...displaying the model on PC/Linux is instantaneous, displaying this same model on MAC causes about a 5 second delay on the first pass. If I hide the model then everything runs fine and if I show it again it runs fine, but the very very very first time the rendering tells the model to unhide it has that long delay....is there something that I should move to the init() method that maybe occurs during the first rendering pass?
|
|
|
|
|
|