Gldrawarrays Color Example Essay

  1. 06-29-2012, 10:11 AM#1
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    16

    Vertex Array drawing random points and colors

    The issue is when I try to render my list of Vertices using the code below, the points are not rendered properly The first point in the deque is always correctly rendered. The rest of the points sometimes shouw up for a frame or two but then disapear (causing them to look like their flickering). Furthermore, additional points that I have not created are drawn in random locations with random colors, they flicker as well. Without further ado...

    ...the code:

    I generate these points elsewhere (obviously) and I am positive that the error is NOT in the generation code. I have a version of this program that is identical expect it uses immediates to render vertList. Why is it not rendering properly with VertexArray's?

    Ill attach my initialization code as well in case that may be the cause.
    NOTE: its not in order and there are some parts left out because I deemed them highly likely not to be the cause.
    struct VertArray { float position[3]; unsigned char color[3]; };   deque <VertArray *> vertList;   GLvoid DrawPoints() { glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_COLOR_ARRAY);   if(!vertList.empty()) {   glVertexPointer (3, GL_FLOAT, sizeof (VertArray), (vertList[0]->position)); glColorPointer (3, GL_UNSIGNED_BYTE, sizeof (VertArray), (vertList[0]->color));   glDrawArrays (GL_POINTS, 0, vertList.size()); }   glDisableClientState (GL_VERTEX_ARRAY); glDisableClientState (GL_COLOR_ARRAY);
    PIXELFORMATDESCRIPTOR pfd, *ppfd; int pixelformat;   ppfd = &pfd;   ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR); ppfd->nVersion = 1; ppfd->dwFlags = PFD_DRAW_TO_WINDOW | // Draw to window PFD_SUPPORT_OPENGL | // use OpenGL PFD_DOUBLEBUFFER; // use Double Buffer ppfd->dwLayerMask = PFD_MAIN_PLANE; ppfd->iPixelType = PFD_TYPE_RGBA; // Use RGBA format ppfd->cColorBits = 32; // color bits ppfd->cDepthBits = 32; -----------------------------------------------------------------------------   glEnable(GL_LINE_SMOOTH); // Line AA glEnable(GL_POINT_SMOOTH); // Point AA glEnable(GL_BLEND); // Allow Transparency glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // how transparency acts glHint(GL_LINE_SMOOTH_HINT,GL_NICEST); glHint(GL_POINT_SMOOTH_HINT,GL_FASTEST);   glPolygonMode(GL_BACK, GL_LINE); //Draw back, and draw boundries glLineWidth(LINEWIDTH); //Width of lines in OpenGl glPointSize(POINTSIZE); //Size of Points in OpenGL

  2. 06-29-2012, 12:16 PM#2
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,135
    Last edited by thokra; 06-29-2012 at 12:21 PM.
    glVertexPointer() expects as its 4th argument a pointer to an array of all vertices you try to submit with a call to glDrawArrays(). Currently glVertexPointer() only receives a pointer to an array of size 3 * sizeof(float). What you intend to draw, however, are vertList.size() vertices. The first vertex will be fine, the second won't be and in fact may be undefined since the GPU doesn't access the correct part client memory. Also, a stride is only necessary if you have an interleaved array of vertex attributes. In your case you have two distinct arrays for positions and colors.

    In conclusion: You either need to pack all your points and colors into an interleaved array = [v1, c1, v2, c2, v3, c3, ... , vn, cn] and pass the pointer to glVertexPointer() and glColorPointer() with an appropriate stride or have seperate arrays with a stride of 0:


    One thing you may notice is that with an interleaved array the type of all attributes must be the same since they're all interleaved into a single array. Disclaimer: Untested legacy code! That's never a good thing.

    Edit: In my madness I forgot to mention that you can also pack the data like this:

      // seperate arrays GLfloat positions[NUM_VERTS * 3]; GLuchar colors[NUM_VERTS * 3];   glVertexPointer (3, GL_FLOAT, 0, positions); glColorPointer (3, GL_UNSIGNED_BYTE, 0, colors);   // interleaved array   const GLsizei stride = 3 * sizeof(float);   GLfloat interleaves[] = {v1_x, v1_y, v1_z, c1_r, c1_g, c1_b};   glVertexPointer (3, GL_FLOAT, stride, positions); glColorPointer (3, GL_FLOAT, stride, positions + 1);
      // assume you have n positions and n colors GLfloat packedAttribs = {v1_x, v1_y, v1_z, v2_x, v2_y, v2_z, ... , vn_x, vn_y, vn_z, c1_r, c1_g, c1_b, c2_r, c2_g, c2_b, ..., cn_r, cn_g, cn_b};   // address of first position is simply &packedAttribs[0] glVertexPointer(3, GL_FLOAT, 0, packedAttribs)   // address of first color is &packedAttribs[0] + n glColorPointer(3, GL_FLOAT, 0, packedAttribs + n)

  3. 06-29-2012, 12:35 PM#3
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    16
    If I were to pack my arrays of positions into a vector, i.e vector<float[3]*> would VertexPointer be able to iterate through it properly? If not, would it be able to read a vector<float> similar to the array you sugested {v1_x, v1_y, v1_z, v2_x, etc...}? It would be quite a hassle to try and manage an array of vertices in my case as I am constantly adding and removing items from the vertList. And I cant see creating one

  4. 06-29-2012, 02:16 PM#4
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,135
    Last edited by thokra; 06-29-2012 at 02:22 PM.
    std::vector uses an array as its internal data structure which you can access by std::vector<T>::data() which returns a pointer to T (or T*). Using a std::vector<float> which contains every component of every vertex is fine.

    std::vector<float[3]*> is not a legal declaration, so it's right out of the question.

    You're not getting around passing a pointer and additional information to determine which memory locations to access. What do you want to do, what's the concrete problem you're facing?

    Edit: BTW, you cannot use std::vector<float[3]> either! You generally can't use arrays as template arguments of STL containers since types designated by the arguments must be copy constructible and assignable.
    It would be quite a hassle to try and manage an array of vertices in my case as I am constantly adding and removing items from the vertList.

  5. 06-29-2012, 02:33 PM#5
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    16
    Millions of points with new ones being added rapidly. I cant really afford to manually iterate through them every frame due to cost. I would prefer to store them in a struct for easy sorting. Whats my best option?(OpenGL 1.4)

  6. 10-04-2012, 12:25 AM#6
    Intern Contributor
    Join Date
    Jun 2009
    Posts
    92
    Hi,

    Did you able to manage to implement "Millions of points with new ones being added rapidly." ? If so, can you guide me how did you do that? Also did you try dynamic deleting the points?

    Thanks
    Originally Posted by Beiufin
    Millions of points with new ones being added rapidly. I cant really afford to manually iterate through them every frame due to cost. I would prefer to store them in a struct for easy sorting. Whats my best option?(OpenGL 1.4)

  7. 10-04-2012, 09:09 AM#7
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    16
    If you can, using a VBO is most efficient (see my other noob thread here). In my case I has to have this program perform on older machines so I ended up using a Vertex array. My issue with the vertex array was that I had improperly synchronized my threads.

    In the end I had other threads working on receiving new points and then storing them in a queue, when the drawing thread was ready to draw, it would fetch all the new points and store them in a vertex. I would then pass the vertex(by reference of course) to a draw points function similar to this one.


    I did originally have it dynamically deleting points, but OpenGL does it more efficiently every draw.
    GLvoid DrawPoints(vector<float> vertArray, vector<float> colorArray) { glEnableClientState (GL_VERTEX_ARRAY); glEnableClientState (GL_COLOR_ARRAY);   glVertexPointer (2, GL_FLOAT, sizeof (vertArray), vertArray); glColorPointer (3, GL_FLOAT, sizeof (colorArray), colorArray);   glDrawArrays (GL_POINTS, 0, vertArray.size() / 2; // the vertArray is ordered (X,Y,X,Y,X,Y,...)   glDisableClientState (GL_VERTEX_ARRAY); glDisableClientState (GL_COLOR_ARRAY); }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

Forum Rules

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Welcome for the 4rth tutorial ! You will do the following :

  • Draw a cube instead of the boring triangle
  • Add some fancy colors
  • Learn what the Z-Buffer is

Draw a cube

A cube has six square faces. Since OpenGL only knows about triangles, we’ll have to draw 12 triangles : two for each face. We just define our vertices in the same way as we did for the triangle.

The OpenGL buffer is created, bound, filled and configured with the standard functions (glGenBuffers, glBindBuffer, glBufferData, glVertexAttribPointer) ; see Tutorial 2 for a quick reminder. The draw call does not change either, you just have to set the right number of vertices that must be drawn :

A few remarks on this code :

  • For now, our 3D model is fixed : in order to change it, you have to modify the source code, recompile the application, and hope for the best. We’ll learn how to load dynamic models in tutorial 7.
  • Each vertex is actually written at least 3 times (search “-1.0f,-1.0f,-1.0f” in the code above). This is an awful waste of memory. We’ll learn how to deal with this in tutorial 9.

You now have all the needed pieces to draw the cube in white. Make the shaders work ! go on, at least try :)

Adding colors

A color is, conceptually, exactly the same as a position : it’s just data. In OpenGL terms, they are “attributes”. As a matter of fact, we already used this with glEnableVertexAttribArray() and glVertexAttribPointer(). Let’s add another attribute. The code is going to be very similar.

First, declare your colors : one RGB triplet per vertex. Here I generated some randomly, so the result won’t look that good, but you can do something better, for instance by copying the vertex’s position into its own color.

The buffer is created, bound and filled in the exact same way as the previous one :

The configuration is also identical :

Now, in the vertex shader, we have access to this additional buffer :

In our case, we won’t do anything fancy with it in the vertex shader. We will simply forward it to the fragment shader :

In the fragment shader, you declare fragmentColor again :

… and copy it in the final output color :

And that’s what we get :

Urgh. Ugly. To understand what happens, here’s what happens when you draw a “far” triangle and a “near” triangle :

Seems OK. Now draw the “far” triangle last :

It overdraws the “near” one, even though it’s supposed to be behind it ! This is what happens with our cube : some faces are supposed to be hidden, but since they are drawn last, they are visible. Let’s call the Z-Buffer to the rescue !

Quick Note 1 : If you don’t see the problem, change your camera position to (4,3,-3)

Quick Note 2 : if “color is like position, it’s an attribute”, why do we need to declare out vec3 fragmentColor; and in vec3 fragmentColor; for the color, and not for the position ? Because the position is actually a bit special : It’s the only thing that is compulsory (or OpenGL wouldn’t know where to draw the triangle !). So in the vertex shader, gl_Position is a “built-in” variable.

The Z-Buffer

The solution to this problem is to store the depth (i.e. “Z”) component of each fragment in a buffer, and each and every time you want to write a fragment, you first check if you should (i.e the new fragment is closer than the previous one).

You can do this yourself, but it’s so much simpler to just ask the hardware to do it itself :

You also need to clear the depth each frame, instead of only the color :

And this is enough to solve all your problems.

Exercises

  • Draw the cube AND the triangle, at different locations. You will need to generate 2 MVP matrices, to make 2 draw calls in the main loop, but only 1 shader is required.

  • Generate the color values yourself. Some ideas : At random, so that colors change at each run; Depending on the position of the vertex; a mix of the two; Some other creative idea :) In case you don’t know C, here’s the syntax :

  • Once you’ve done that, make the colors change each frame. You’ll have to call glBufferData each frame. Make sure the appropriate buffer is bound (glBindBuffer) before !
Categories: 1

0 Replies to “Gldrawarrays Color Example Essay”

Leave a comment

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *