Sign in to follow this  
3DViewer

OpenGL Dealing with large amount of data

Recommended Posts

3DViewer    122
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
_gl_coder_one_    140
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
V-man    813
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
swiftcoder    18426
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
ma_hty    100
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
stonemetal    288
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
3DViewer    122

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
swiftcoder    18426
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
ma_hty    100
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
3DViewer    122
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  

  • Similar Content

    • By Zaphyk
      I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
    • By Kjell Andersson
      I'm trying to get some legacy OpenGL code to run with a shader pipeline,
      The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
      I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
      I've got a version 330 vertex shader to somewhat work:
      #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
      What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
      Question:
      What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
       
      Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
    • By markshaw001
      Hi i am new to this forum  i wanted to ask for help from all of you i want to generate real time terrain using a 32 bit heightmap i am good at c++ and have started learning Opengl as i am very interested in making landscapes in opengl i have looked around the internet for help about this topic but i am not getting the hang of the concepts and what they are doing can some here suggests me some good resources for making terrain engine please for example like tutorials,books etc so that i can understand the whole concept of terrain generation.
       
    • By KarimIO
      Hey guys. I'm trying to get my application to work on my Nvidia GTX 970 desktop. It currently works on my Intel HD 3000 laptop, but on the desktop, every bind textures specifically from framebuffers, I get half a second of lag. This is done 4 times as I have three RGBA textures and one depth 32F buffer. I tried to use debugging software for the first time - RenderDoc only shows SwapBuffers() and no OGL calls, while Nvidia Nsight crashes upon execution, so neither are helpful. Without binding it runs regularly. This does not happen with non-framebuffer binds.
      GLFramebuffer::GLFramebuffer(FramebufferCreateInfo createInfo) { glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); textures = new GLuint[createInfo.numColorTargets]; glGenTextures(createInfo.numColorTargets, textures); GLenum *DrawBuffers = new GLenum[createInfo.numColorTargets]; for (uint32_t i = 0; i < createInfo.numColorTargets; i++) { glBindTexture(GL_TEXTURE_2D, textures[i]); GLint internalFormat; GLenum format; TranslateFormats(createInfo.colorFormats[i], format, internalFormat); // returns GL_RGBA and GL_RGBA glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, createInfo.width, createInfo.height, 0, format, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, textures[i], 0); } if (createInfo.depthFormat != FORMAT_DEPTH_NONE) { GLenum depthFormat; switch (createInfo.depthFormat) { case FORMAT_DEPTH_16: depthFormat = GL_DEPTH_COMPONENT16; break; case FORMAT_DEPTH_24: depthFormat = GL_DEPTH_COMPONENT24; break; case FORMAT_DEPTH_32: depthFormat = GL_DEPTH_COMPONENT32; break; case FORMAT_DEPTH_24_STENCIL_8: depthFormat = GL_DEPTH24_STENCIL8; break; case FORMAT_DEPTH_32_STENCIL_8: depthFormat = GL_DEPTH32F_STENCIL8; break; } glGenTextures(1, &depthrenderbuffer); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, createInfo.width, createInfo.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthrenderbuffer, 0); } if (createInfo.numColorTargets > 0) glDrawBuffers(createInfo.numColorTargets, DrawBuffers); else glDrawBuffer(GL_NONE); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer Incomplete\n"; glBindFramebuffer(GL_FRAMEBUFFER, 0); width = createInfo.width; height = createInfo.height; } // ... // FBO Creation FramebufferCreateInfo gbufferCI; gbufferCI.colorFormats = gbufferCFs.data(); gbufferCI.depthFormat = FORMAT_DEPTH_32; gbufferCI.numColorTargets = gbufferCFs.size(); gbufferCI.width = engine.settings.resolutionX; gbufferCI.height = engine.settings.resolutionY; gbufferCI.renderPass = nullptr; gbuffer = graphicsWrapper->CreateFramebuffer(gbufferCI); // Bind glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); // Draw here... // Bind to textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textures[1]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[2]); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); Here is an extract of my code. I can't think of anything else to include. I've really been butting my head into a wall trying to think of a reason but I can think of none and all my research yields nothing. Thanks in advance!
    • By Adrianensis
      Hi everyone, I've shared my 2D Game Engine source code. It's the result of 4 years working on it (and I still continue improving features ) and I want to share with the community. You can see some videos on youtube and some demo gifs on my twitter account.
      This Engine has been developed as End-of-Degree Project and it is coded in Javascript, WebGL and GLSL. The engine is written from scratch.
      This is not a professional engine but it's for learning purposes, so anyone can review the code an learn basis about graphics, physics or game engine architecture. Source code on this GitHub repository.
      I'm available for a good conversation about Game Engine / Graphics Programming
  • Popular Now