Skip to main content
gamedev.net
🔒 Locked

Opengl-Buffer question?

Started by frog04 15 replies 1.7k views
Original Post
frog04
frog04
I have to visualize a "chess-board" but with more than 160.000 sqaures each colored according to some measurment-values. I'm usging wxWidgets with a wxGLCanvas-object. Now i set up a glOrtho (only 2D is needed) and paint the squares. I'm using multiple windows so more "measurement-objects" could be viewn. Now i had the problem with scroll, size, overlapping,..., everything that calls a PaintEvent. There are to many float-values to render it every-time. So i tried following trick:
[source==cpp]
OnPaint(..)
{
 if(first)
 {
   glDrawBuffer(GL_FRONT);
   Render(); 

   glDrawBuffer(GL_BACK);
   Render();
  first = false;
 }
 SwapBuffers();
}


But this code makes errors on some systems, picture is getting blurred and black, a total mass. Now i'm seraching for some kind of buffer-object or anything like this!? instead of rendering it everytime (it's not animated!). Any suggestions?
V-man
V-man
Why do you call
glDrawBuffer(GL_FRONT);
Render();

Also, get rid of if(first)
so that it renders.
frog04
frog04
As i said: "There are too many float-values to render it every-time."

If I render it every-PaintEvent it's bucking hard.
Sneftel
Sneftel
Rendering 160000 texels every frame is not a significant problem if you're doing it efficiently. What method do you use to draw the chessboard?
V-man
V-man
My favorite method is to render to a texture as a temporary storage. Then render a big quad all over your screen.
Example to create a RTT

http://www.opengl.org/wiki/index.php/GL_EXT_framebuffer_object
frog04
frog04
I tried it with a FBO-Object but have this problem:
http://www.gamedev.net/community/forums/topic.asp?topic_id=515600

My draw-Method for every cell looks like this:
void GLCanvas::drawCell(int *x_pos, int *y_pos, int bin_value) {         right_x  = x_offset * (*x_pos + 1);   left_x   = x_offset * (*x_pos);   top_y    = y_offset * (*y_pos + 1);   bottom_y = y_offset * (*y_pos);        glColor3f(0.5f, 0.5f, 0.2f);   glBegin(GL_LINE_LOOP);    glVertex2i(right_x, top_y);    glVertex2i(left_x,  top_y);    glVertex2i(left_x,  bottom_y );    glVertex2i(right_x, bottom_y);   glEnd();        // switch colour depending on the bin-value        wxColour *colour = mdi_parent_ptr->getColour(bin_value);    convertColourTo3f(colour);         //if((bin_value != REF_DIE) && (bin_value != REF_DIE2))    glRecti(right_x, top_y, left_x, bottom_y);        // draw a point in the middle of all none good-dies   if(bin_value != 0x01)   {     // set color black     glColor3f(0.0f, 0.0f, 0.0f);     // set point size according the scale     glPointSize(point_size);     glBegin(GL_POINTS);       glVertex2i(left_x + x_offset / 2, bottom_y + y_offset / 2);     glEnd();   }  }


I still reduced it to integer-values and also made tried it with a display-list.

Calling it @ a for-loop:
for(int index = 0; index < num_of_dies; index++){     x = wafer_ptr->getDie(index)->getXcoord();     y = wafer_ptr->getDie(index)->getYcoord();     b = wafer_ptr->getDie(index)->getBinValue();     drawCell(&x, &y, b);      }


Probably this could be made faster in a int-array?(think so)
Sneftel
Sneftel
Yeah, that's going to be really, really slow. High-performance OpenGL requires that you NOT draw 640 thousand vertices with glVertex. Put all your square values in a texture and render that texture using a single quad.
frog04
frog04
General question on Window-buffers.

Why is it necessary to render the whole scene again if e.g. scroll-event occurs.
Why do the window itself doesn't store the picture temporary and just call a buffer if it is overlapped or scrolled.

I can't imagine that this is made with repaintings?
snoutmate
snoutmate
Quote:
Original post by frog04
General question on Window-buffers.

Why is it necessary to render the whole scene again if e.g. scroll-event occurs.
Why do the window itself doesn't store the picture temporary and just call a buffer if it is overlapped or scrolled.

I can't imagine that this is made with repaintings?

I don't know wx, but i imagine they do window stuff simply by drawing on top of the GL canvas ? Caching makes sense only in limited cases where the scene is static (not your usual GL app), meaning it's your job to do so. Simply render the scene to texture (or use glCopyTexImage* to copy the rendered scene from framebuffer to texture), then on repaint draw fullscreen quad with the texture. This will be fast everywhere.
V-man
V-man
Quote:
Original post by frog04
General question on Window-buffers.

Why is it necessary to render the whole scene again if e.g. scroll-event occurs.
Why do the window itself doesn't store the picture temporary and just call a buffer if it is overlapped or scrolled.

I can't imagine that this is made with repaintings?


Because normally, the backbuffer is not preserved when you call SwapBuffers. The driver can just switch pointers so that the back buffer becomes the front buffer and the front becomes back.
The driver can do all sorts of crazy things.

You can try setting the PFD_SWAP_COPY but personally, I would recommend the RTT method I already mentioned.

Swapbuffers issue
http://www.opengl.org/wiki/index.php/Common_Mistakes#Swap_Buffers
frog04
frog04
I tried to do it with glCopyTexImage2D and than draw a quad with this texture but the quad remain black:


[source="cpp"]glGenTextures(1, &texture[0]);glBindTexture(GL_TEXTURE_2D, texture[0]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 400, 400, 0);


thans draw the quad:

[source="cpp"]glBindTexture(GL_TEXTURE_2D, texture[0]);glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-500.0f, -500.0f,  -0.1f);	 glTexCoord2f(1.0f, 0.0f); glVertex3f(-100.0f, -500.0f,  -0.1f);	 glTexCoord2f(1.0f, 1.0f); glVertex3f(-100.0f, -100.0f,  -0.1f);	 glTexCoord2f(0.0f, 1.0f); glVertex3f(-500.0f, -100.0f,  -0.1f);glEnd();


I have a negative Ortho:
[source="cpp"]glOrtho(-900, 0, -900, 0, -1, 1);


Must i consider it @ glCopyTexImage2D for the left-bottom-corner?
V-man
V-man
Yes, glCopyTexImage2D copies starting from the bottom left corner.
Call glGetError() to make sure there are no errors.

You can use a debugging tool too see what the texture looks like
http://www.opengl.org/wiki/index.php/Debugging_Tools
frog04
frog04
Its finally done. I now have the texture, but it's slower than with repainting all glVertexes.
So i think i make smth. wrong. Here's a picture so that you can imagine how my texture looks like:
Iamge

I now use
[source="cpp"]// for creating the textureglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 900, 900, 0);// for drawing the quad with textureglEnable(GL_TEXTURE_2D);     glBindTexture(GL_TEXTURE_2D, texture[0]);     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);     glBegin(GL_QUADS);      glTexCoord2f(1.0f, 1.0f); glVertex2f(-900.0f, -900.0f); //,  0.1f);      glTexCoord2f(1.0f, 0.0f); glVertex2f(-900.0f, 0.0f); //,  0.1f);      glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); //,  0.1f);      glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, -900.0f); //,  0.1f);     glEnd();


Is the resolution with 900x900 to big?
How could i get more performance?
V-man
V-man
Are you calling glCopyTexImage2D non stop?
glCopyTexImage2D is sort of like glTexImage2D, which deletes and reallocates a texture. It is best to use glCopyTexSubImage2D to just copy texels.
http://www.opengl.org/wiki/index.php/Common_Mistakes#Updating_A_Texture
i_luv_cplusplus
i_luv_cplusplus
Many graphic cards have problems with non-power-of-2-textures. Try using 1024x1024 for size.
OpenGL fanboy.
frog04
frog04
no, i'm not calling it everyTime; it was just a part of my source; here how i do it:

OnPaint(wxPaintEvent& event){  if(first)  {    Render();    createTexture();    first=false;  }  glEnable(GL_TEXTURE_2D);   glBindTexture(GL_TEXTURE_2D, texture[0]);   glColor4f(1.0f, 1.0f, 1.0f, 1.0f);   glBegin(GL_QUADS);    glTexCoord2f(1.0f, 1.0f); glVertex2f(-900.0f, -900.0f);    glTexCoord2f(1.0f, 0.0f); glVertex2f(-900.0f, 0.0f);    glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);    glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, -900.0f);   glEnd();  glDisable(GL_TEXTURE_2D);  glFlsuh();  SwapBuffers();}void GLCanvas::createTexture(){  glEnable(GL_TEXTURE_2D);  glGenTextures(1, &texture[0]);  glBindTexture(GL_TEXTURE_2D, texture[0]);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1024, 1024, 0);


@ the link you posted glGenerateMipmap is called. Is it really necessary.
WxDev++ provides some opengl functions, but Mipmap don't seems to be part of it.
Is it really neccessary to call it? otherwise i have to use glew or smth. else.
V-man
V-man
Ok, if you are calling it once. Then try a pow2 texture like 512 x 512
Maybe your driver and GPU have some issue with non pow textures. What do you have anyway?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.