Sign in to follow this  
3DViewer

OpenGL Dealing with large amount of data

Recommended Posts

Hi! I must start saying that I am new to OpenGL. I have inherited an old piece of code that draws surfaces made of triangles. Its basic method is the following: glBegin(GL_TRIANGLES); for (i = 0; i < *n; i++) { glVertex2fv(vert[endpts[nx]-1]); nx++; glVertex2fv(vert[endpts[nx]-1]); nx++; glVertex2fv(vert[endpts[nx]-1]); } glEnd(); On top of all, this code is not using specific matrix calls such as glRotate, glTranslate and glScale to handle the object movement. It holds onto the complete view matrix and does it's own adjustments based on the inputs and then just sets the whole matrix before rendering. It is fine with small models, but when I start playing with millions of triangles, it takes about 5 seconds to render the result of a rotation/translation. I am planning to re-code the stuff, grouping the triangles to render them in 1 call, using index buffering to avoid duplicated vertices, but at the moment, I am having a problem with the following basic problem: Assuming I have already drawn the model using the above piece of code and want now to translate it using the mouse (the mouse event has returned dx and dy), How do I make the graphic card understand to use what it has already in memory and apply on it the glTranslatef(dx, dy, 0) without having to re-do the above piece of code, ie the glBegin ... glVertex2fv ... glEnd stuff? I thought of using glMultMatrixf(), so I did the following: GLfloat new_matrix[] = {1,0,0,0.5,0,1,0,0.5,0,0,1,0,0,0,0,1}; float mat[16]; int r,c; glGetFloatv(GL_MODELVIEW_MATRIX, mat); qDebug("Before glMultMatrixf"); for (c=0 ; c<16 ; c++) std::cout<<mat[c]<<" " ;std::cout<<std::endl; glMultMatrixf(new_matrix); qDebug("After glMultMatrixf"); glGetFloatv(GL_MODELVIEW_MATRIX, mat); for (c=0 ; c<16 ; c++) std::cout<<mat[c]<<" " ;std::cout<<std::endl; So I just want the model to be translate by a factor 0.5 in x and y. The outputs of my debu info are: Before glMultMatrixf -0.53704 -3.71254 -15.0809 5 -0.83904 -3.41054 -15.0809 5 0 0 0.431428 0 -0.167808 -0.742508 -3.01619 1 After glMultMatrixf -0.620944 -4.08379 -16.589 5.5 -0.922944 -3.78179 -16.589 5.5 0 0 0.431428 0 -0.167808 -0.742508 -3.01619 1 So the viewing matrix gets updated, so why not the model? Thanks for your help! -Pierre.

Share this post


Link to post
Share on other sites
to speed up the code you can try one of the following methods :
1. Display lists
2. vertex arays .
3. Vertex buffer objects.

as far as the matrix is concerned, where are u placing the glMultMatrix functions ?
Also, since your translation is 0.5 in each direction , probably thats why the change is not apparent ? Try drawing an axis at the origin and then see if the model is translated.

cheers

Share this post


Link to post
Share on other sites
Quote:
It is fine with small models, but when I start playing with millions
of triangles, it takes about 5 seconds to render the result of a
rotation/translation.


Move up to VBO. It requires GL 1.5
Avoid glGet calls.

Share this post


Link to post
Share on other sites
Quote:
Original post by _gl_coder_one_
1. Display lists
Display lists are handy, but they wont do much for you if you are feeding a ton of data.
Quote:
2. vertex arays.
3. Vertex buffer objects.
Vertex arrays should help a lot, and VBOs will help even more - what is best is that the second is only a small step from the first. For best results, interleave the vertices, and possibly even rearrange them for vertex cache coherence.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by _gl_coder_one_
1. Display lists
Display lists are handy, but they wont do much for you if you are feeding a ton of data.
Quote:
2. vertex arays.
3. Vertex buffer objects.
Vertex arrays should help a lot, and VBOs will help even more - what is best is that the second is only a small step from the first. For best results, interleave the vertices, and possibly even rearrange them for vertex cache coherence.


Display list is usually as good as static VBO (at least on a NVidia display card).

Share this post


Link to post
Share on other sites
Quote:

Assuming I have already drawn the model using the above piece of code
and want now to translate it using the mouse (the mouse event has
returned dx and dy),

How do I make the graphic card understand to use what it has already
in memory and apply on it the glTranslatef(dx, dy, 0) without having
to re-do the above piece of code, ie the glBegin ... glVertex2fv ...
glEnd stuff?

There is absolutely nothing you can do. That is why the original code is considered bad.

Share this post


Link to post
Share on other sites

Hi!

Thank you to all of you!

I think that I started with the wrong assumption. I thought that when a scene has been rendered, if this one has not changed in term of new object being rendered/deleted, a simple rotation could be done without having to redraw everything.

In fact as soon I change a bit in my scene I have to render everything
all again, ie going through the original bit of code:

glBegin(GL_TRIANGLES);
for (i = 0; i < *n; i ) {
glVertex2fv(vert[endpts[nx]-1]);
nx ;
glVertex2fv(vert[endpts[nx]-1]);
nx ;
glVertex2fv(vert[endpts[nx]-1]);
}
glEnd();

With millions of triangles, I will have too many function calls.


So, my only solution is in fact to implement some VBO approach...

Could anyone redirect me to some place where VBO is explained with some code sample?

Cheers..

Share this post


Link to post
Share on other sites
Quote:
Original post by ma_hty
Display list is usually as good as static VBO (at least on a NVidia display card).
I am going to go out on a limb here and say that this is incorrect. For small amounts of data, you may be right - but in the OP's case, he is most likely bandwidth-limited, and saving the transfer of vertex data every frame should help a lot.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by ma_hty
Display list is usually as good as static VBO (at least on a NVidia display card).
I am going to go out on a limb here and say that this is incorrect. For small amounts of data, you may be right - but in the OP's case, he is most likely bandwidth-limited, and saving the transfer of vertex data every frame should help a lot.


I really don't want to start a discussion about it in the first place because I don't really have any official spec about it. However, from my experience, the display list does have some kind of optimization to save the transfer of vertex data.

You can verify it easily. Get a big 3D model (at least 100 MB in file size), and draw it using display list, vertex pointer and VBO.

[Edited by - ma_hty on May 16, 2008 10:15:52 AM]

Share this post


Link to post
Share on other sites
I am trying to use display list, because I want to see the benefit of them. However, the code I am dealing with is rather tricky. It is a mixture of Fortran 77 (I know...) and C and If I may I am going to describe it here:

from fortran, I do

call XFtnDisTriCol(GC3, tris(1,kx), 1, snorm, xyz, iwk3, cmap, ntri, 0, norflg)

and from C I have
XFTNDISTRICOL(Window *window, int *endpts, int *skip, float norms[][3],
float vert[][3], int ci[][3], float cmap[][3],
int *n, int *mirror, int *nf)
{
static int surf = 1;
int i, mir, ninst, ni, nx;
float col[4];

// Block 1
if ((XFtnXparVal != 0.0)) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
for (ni = 0; ni < ninst; ni++) {
if (*mirror < 0) {
XFTNAPPLYXFORM(&surf, &ni, &ninst);
if (pV3_inst != NULL)
if (pV3_inst[ni] == 0) continue;
}
if (*nf == 0) xftnFixNor(norms[0], mir);
nx = 0;
glBegin(GL_TRIANGLES);
for (i = 0; i < *n; i++) {
if (*nf != 0) xftnFixNor(norms[i], mir);
xftnFixCol(cmap[ci[i][0]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][1]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][2]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx += *skip + 1;
}
glEnd();
}
glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_BLEND);

} else {

// Block 2
for (ni = 0; ni < ninst; ni++) {
if (*mirror < 0) {
XFTNAPPLYXFORM(&surf, &ni, &ninst);
if (pV3_inst != NULL)
if (pV3_inst[ni] == 0) continue;
}
if (*nf == 0) xftnFixNor(norms[0], mir);
nx = 0;
glBegin(GL_TRIANGLES);
for (i = 0; i < *n; i++) {
if (*nf != 0) xftnFixNor(norms[i], mir);
xftnFixCol(cmap[ci[i][0]], col);
xftnColor3fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][1]], col);
xftnColor3fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][2]], col);
xftnColor3fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx += *skip + 1;
}
glEnd();
}
}

}

the xftnFixCol functions fix the colour (no opengl calls)
the xftnColor3fv makes sure that the color is between 0 and 255 and then call glColor3ubv
xftnFixPos calculate the vertex position and call glVertex3fv


My implementation for Block 1 is

iflag = 1; list1=0;
get_listflag_(&iflag,&list1); // list1 is stored in a common block in the fortran
if (list1==0)
{
listName1 = glGenLists (1);
glNewList(listName1, GL_COMPILE);
fprintf(stderr, "In XFTNDISTRICOL 1\n");
glBegin(GL_TRIANGLES);
for (i = 0; i < *n; i++) {
if (*nf != 0) xftnFixNor(norms[i], mir);
xftnFixCol(cmap[ci[i][0]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][1]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx++;
xftnFixCol(cmap[ci[i][2]], col);
col[3] = XFtnXparVal;
xftnColor4fv(col);
xftnFixPos(vert[endpts[nx]-1], mir);
nx += *skip + 1;
}
glEnd();
glEndList();
list1 = 1;
iflag = 1;
set_listflag_(&iflag,&list1);
}
else
{
glCallList(listName1);
}

So the idea is that the first time the code execute the bloack, it initialise the display list. Then it uses it.

I am sorry for this rather tedious explanation and ugly code, but, hey, I don't have the choice....


I did this implementation in 3 functions, so I have 6 display lists. As a results, Some of the surfaces are drawn properly whereas some others are simply not drawn in color.... just transparent. When the model gets re-drawn, due to some rotation, for instance, I get the same result. So it is kind of work, but not completely.

Question: Can anyone spot any fundamental error that would explain why the code does not behave as the original one, ie without the display lists? I would like to know if the fact that vertices and colors are constantly changing their states and not in a direct block but in functions that are called could be the problem...

Any thoughts?

-Pierre.


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      627738
    • Total Posts
      2978881
  • Similar Content

    • By DelicateTreeFrog
      Hello! As an exercise for delving into modern OpenGL, I'm creating a simple .obj renderer. I want to support things like varying degrees of specularity, geometry opacity, things like that, on a per-material basis. Different materials can also have different textures. Basic .obj necessities. I've done this in old school OpenGL, but modern OpenGL has its own thing going on, and I'd like to conform as closely to the standards as possible so as to keep the program running correctly, and I'm hoping to avoid picking up bad habits this early on.
      Reading around on the OpenGL Wiki, one tip in particular really stands out to me on this page:
      For something like a renderer for .obj files, this sort of thing seems almost ideal, but according to the wiki, it's a bad idea. Interesting to note!
      So, here's what the plan is so far as far as loading goes:
      Set up a type for materials so that materials can be created and destroyed. They will contain things like diffuse color, diffuse texture, geometry opacity, and so on, for each material in the .mtl file. Since .obj files are conveniently split up by material, I can load different groups of vertices/normals/UVs and triangles into different blocks of data for different models. When it comes to the rendering, I get a bit lost. I can either:
      Between drawing triangle groups, call glUseProgram to use a different shader for that particular geometry (so a unique shader just for the material that is shared by this triangle group). or
      Between drawing triangle groups, call glUniform a few times to adjust different parameters within the "master shader", such as specularity, diffuse color, and geometry opacity. In both cases, I still have to call glBindTexture between drawing triangle groups in order to bind the diffuse texture used by the material, so there doesn't seem to be a way around having the CPU do *something* during the rendering process instead of letting the GPU do everything all at once.
      The second option here seems less cluttered, however. There are less shaders to keep up with while one "master shader" handles it all. I don't have to duplicate any code or compile multiple shaders. Arguably, I could always have the shader program for each material be embedded in the material itself, and be auto-generated upon loading the material from the .mtl file. But this still leads to constantly calling glUseProgram, much more than is probably necessary in order to properly render the .obj. There seem to be a number of differing opinions on if it's okay to use hundreds of shaders or if it's best to just use tens of shaders.
      So, ultimately, what is the "right" way to do this? Does using a "master shader" (or a few variants of one) bog down the system compared to using hundreds of shader programs each dedicated to their own corresponding materials? Keeping in mind that the "master shaders" would have to track these additional uniforms and potentially have numerous branches of ifs, it may be possible that the ifs will lead to additional and unnecessary processing. But would that more expensive than constantly calling glUseProgram to switch shaders, or storing the shaders to begin with?
      With all these angles to consider, it's difficult to come to a conclusion. Both possible methods work, and both seem rather convenient for their own reasons, but which is the most performant? Please help this beginner/dummy understand. Thank you!
    • By JJCDeveloper
      I want to make professional java 3d game with server program and database,packet handling for multiplayer and client-server communicating,maps rendering,models,and stuffs Which aspect of java can I learn and where can I learn java Lwjgl OpenGL rendering Like minecraft and world of tanks
    • By AyeRonTarpas
      A friend of mine and I are making a 2D game engine as a learning experience and to hopefully build upon the experience in the long run.

      -What I'm using:
          C++;. Since im learning this language while in college and its one of the popular language to make games with why not.     Visual Studios; Im using a windows so yea.     SDL or GLFW; was thinking about SDL since i do some research on it where it is catching my interest but i hear SDL is a huge package compared to GLFW, so i may do GLFW to start with as learning since i may get overwhelmed with SDL.  
      -Questions
      Knowing what we want in the engine what should our main focus be in terms of learning. File managements, with headers, functions ect. How can i properly manage files with out confusing myself and my friend when sharing code. Alternative to Visual studios: My friend has a mac and cant properly use Vis studios, is there another alternative to it?  
    • By ferreiradaselva
      Both functions are available since 3.0, and I'm currently using `glMapBuffer()`, which works fine.
      But, I was wondering if anyone has experienced advantage in using `glMapBufferRange()`, which allows to specify the range of the mapped buffer. Could this be only a safety measure or does it improve performance?
      Note: I'm not asking about glBufferSubData()/glBufferData. Those two are irrelevant in this case.
    • By xhcao
      Before using void glBindImageTexture(    GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), does need to make sure that texture is completeness. 
  • Popular Now