Thread: Can I have some Sample Code? (OpenGL, glDrawPixels();)

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968

    Can I have some Sample Code? (OpenGL, glDrawPixels();)

    Posting this quote to show that I have looked, can anyone gimme some sample code that uses glDrawpixels()?


    Preferably something that uses NeHe's base GL code... Really not interested in fudging with GLUT, seeing as how its not being used anymore...

    14.015 How do I use glDrawPixels() and glReadPixels()?

    glDrawPixels() and glReadPixels() write and read rectangular areas to and from the framebuffer, respectively. Also, you can access stencil and depth buffer information with the format parameter. Single pixels can be written or read by specifying width and height parameters of 1.

    glDrawPixels() draws pixel data with the current raster position at the lower left corner. Problems using glDrawPixels() typically occur because the raster position is set incorrectly. When the raster position is set with the glRasterPos*() function, it is transformed as if it were a 3D vertex. Then the glDrawPixels() data is written to the resulting device coordinate raster position. (This allows you to tie pixel arrays and bitmap data to positions in 3D space).

    When the raster position is outside the view volume, it's clipped and the glDrawPixels() call isn't rendered. This occurs even when part of the glDrawPixels() data would be visible. Here's info on how to render when the raster position is clipped.

    glReadPixels() doesn't use the raster position. Instead, it obtains its (X,Y) device coordinate address from its first two parameters. Like glDrawPixels(), the area read has x and y for the lower left corner. Problems can occur when reading pixels if:

    The area being read is from a window that is overlapped or partially offscreen. glReadPixels() will return undefined data for the obscured area. (More info.)
    Memory wasn't allocated for the return data (the 7th parameter is a NULL pointer) causing a segmentation fault, core dump, or program termination. If you think you've allocated enough memory, but you still run into this problem, try doubling the amount of memory you've allocated. If this causes your read to succeed, chances are you've miscalculated the amount of memory needed.
    For both glDrawPixels() and glReadPixels(), keep in mind:

    The width and height parameters are in pixels.
    If the drawn or read pixel data seems correct, but is slightly off, make sure you've set alignment correctly. Argument values are controlled with the glPixelStore*() functions. The PACK and UNPACK values control sending and receiving pixel data, from and to OpenGL, respectively.
    Last edited by Shamino; 10-18-2005 at 08:35 AM.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    In my experience with Shakti, one of my friends from the board, I don't recommend using glDrawPixels to do anything. It seems to require 2 copies - 1 to get the data to a buffer, and 1 internal to GL to get that data to the actual frame buffer.

    Not a good idea.

    GL does not let you 'lock' surfaces like DX (from what I know of GL which is very little).

    Direct access to buffers is becoming less and less popular and/or needed due to modern advances like vertex and pixel shaders which give you a huge amount of control over rendering processes - down to the pixel level.

  3. #3
    ---
    Join Date
    May 2004
    Posts
    1,379
    it seems Shamino just isn't having much luck

  4. #4
    Registered User Frobozz's Avatar
    Join Date
    Dec 2002
    Posts
    546
    Quote Originally Posted by Shamino
    Preferably something that uses NeHe's base GL code... Really not interested in fudging with GLUT, seeing as how its not being used anymore...
    I'm sure GLUT is used more than glDrawPixels(). You'd be better off simply creating a quad, drawing the pixels to a texture, and then putting the texture on the quad. That's the way I'd do it.

  5. #5
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Thats funny frobozz, cuz I just got done rewriting my entire program so that i don't loop render 392 quads to do that job, it lags, bad.....

    at first I had it so I would loop 392 quads, give them click detection, and a green/red sold flag all in one punch...

    That lagged really really bad......

    now I made it so I used lines to create my grid, rather than quads, runs uber smooth, mouse click detection will be easy to implement, but...

    I need to turn the cells of my grid different colors depending whether or not the cell on the grid is "sold" or not....

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Here's a hint. Stop drawing quads everywhere. All you need is this:

    A vertex buffer holding vertex positions, normals, texture coords, etc.
    An index buffer which indexes into the vertex buffer to create triangles.
    A call to OpenGL to render the triangles. The texture coords should be set so that every 2 triangles makes up one quad.

    I'm not sure how GL works but in D3D you do not iterate through your vertex buffer to render it. You pass the vertex buffer, index buffer, and set the correct rendering states and then call DrawPrimitive() or ID3DXMesh::DrawSubset(x) and D3D does the rest.

    Manually looping through the vertex buffer during a render is basically a software hack for what should be done in hardware.

  7. #7
    ---
    Join Date
    May 2004
    Posts
    1,379
    Shamino might be getting confused the vertex buffer thing. OpenGL doesn't have vertex buffers as part of the standard API but you can use vertex buffers with the ARB extensions.

  8. #8
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Okay.... soooo, I can't play with the vertex buffer in standard OGL....

    okay, so is there a way I can solve my problem without adding on other libraries and such?

    If not, what do I need, and maybe even a link to a tutorial if you're feeling nice ....

    Ultimately, what i need to do, is change a certain set of pixels (20x20) green, which arent outlined by a polygon of any sort....without killing my system... I really don't know where to look anymore

  9. #9
    ---
    Join Date
    May 2004
    Posts
    1,379
    Maybe I didn't say that properly.
    It's not an add on library they are just extensions that should come with your grpahics card drivers.
    http://oss.sgi.com/projects/ogl-sample/registry/

  10. #10
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Alright.... sooo Learn how to manipulate the vertex buffer through the ARB extensions... This will ultimately lead me to the solution to my problem, correct?

  11. #11

  12. #12
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    So doing that lesson, and fully understanding it (vertex buffer objects), will ultimately let me apply it to my simple tiny 2d program to color a set of pixels green when i need them to be green, without making a quad?

  13. #13
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    I think I finally understand what Bubba is getting at, with all those triangles, I just ran that Demo from Nehe....


    32000 triangles at 120 FPS............... Now I'm sure you can color each one of those triangles on the fly if you wanted to... or add a texture.. etc etc.....

    Exactly what my program needs, a quick way to draw 392 quads (or 2(392) triangles (i think)...... with 120 fookin fps, and i can color each one of them as easy as a glcolor3f....

    All this time my problem has been not having a solid object to color, i was thinking I was going to have to actually take the pixels and like, color them individually, but I can have something solid through the vertex buffer, and get like 120 fps too :d

    Gotta learn this!

    Bubba 4tw again...

    Talk about skipping ahead though, lesson 41.... I've really only played with stuff up to lesson 20... But i guess the in betweens aren't required for the vertex buffer lesson...

    Vertex buffers are like, "the cool new thing".... everybody is doin it, you should too... How long do you guys think it would take to master the vertex buffer? Or at least be fluent in it?
    Last edited by Shamino; 10-20-2005 at 10:59 PM.

  14. #14
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Turns out the video cards that I will be using for the project I'm working on don't support Vertex Buffer Objects, here it runs 32000 triangles at 4-6 fps....

    Poopy bad video cards

  15. #15
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well you should be able to create your own vertex library. Granted you won't get the speed of hardware buffers but it will be better than nothing.

    I have a hard time believing that any accelerator wouldn't in some form support hardware vertex buffers since that is the fundamental building block of hardware accelerated 3D graphics.

    If you know assembly language you could code a somewhat slower version of the hardware equivalent of vertex buffers.

    Here is the theory behind vertex and index buffers.

    A vertex buffer simply holds all the vertices of the object in question. It will also hold normal information, diffuse color, specular color, and/or multiple sets of texture coordinates.

    Also you will need 3 types of coordinates. You will need model space, world space, and view or camera space. You may also wish to store the final 2D coords after projection has been done.

    Here is a sample of what a software vertex structure might look like.

    Code:
    class Vector3
    {
      float x,y,z;
      public:
         Vector3(const Vector3 &v)
         {
           x=v.x;y=v.y;z=v.z;
         }
    
         Vector3(void):x(0.0f),y(0.0f),z(0.0f);
         Vector3(float vx,float vy,float vz):x(vx),y(vy),z(vz) {}
         
         Vector3 &operator = (const Vector3 &v)
         {
            x=v.x;
            y=v.y;
            z=v.z;
            return *this;
         }
    
         bool operator ==(const Vector3 &v) const
         {
           return x==v.x && y==v.y && z==v.z;
         }
         
         bool operator !=(const Vector3 &v) const
         {
           return x!=v.x || y!=v.y || z!=v.z;
         }
    
         void Zero(void)
         {
            x=y=z=0.0f;
         }
    
         Vector3 operator  - () const
         {
           return Vector3(-x,-y,-z);
         }
    
         Vector3 operator + (const Vector3  &v) const
         {
           return Vector3(x+v.x,y+v.y,z+v.z);
         }
    
         Vector3 operator - (const Vector3 &v) const
         {
           return Vector3(x-v.x,y-v.y,z-v.z);
         }
    
         Vector3 operator *(float s) const
         {
           return Vector3(x*s,y*s,z*s);
         }
    
         Vector3 operator /(float s) const
         {
           float OneOverS=1.0f/s;
           return Vector3(x*OneOverS,y*OneOverS,z*OneOverS);
         }
    
         Vector3 &operator +=(const Vector3 &v)
         {
           x+=v.x;
           y+=v.y;
           z+=v.z;
           return *this;
         }
    
          Vector3 &operator -=(const Vector3 &v)
          {
             x-=v.x;
             y-=v.y;
             z-=v.z;
             return *this;
          }
    
          Vector3 &operator *=(float s
          {
            x*=s
            y*=s
            z*=s
            return *this;
          }
     
          Vector3 &operator /=(float s)
          {
            float OneOverS=1.0f/s;
            x*=OneOverS;
            y*=OneOverS;
            z*=OneOverS;
          }
      
          void Normalize(void)
          {
            float length=(x*x)+(y*y)+(z*z);
            if (length>0.0f)
            {
              float OneOverLength=1.0f/sqrt(Length);
              x*=OneOverLength;
              y*=OneOverLength;
              z*=OneOverLength;
            }
          }
    
          float Dot(const Vector3 &v) const
          {
             return (x*v.x)+(y*v.y)+(z*v.z);
          }
    };
    
    struct Vertex3D
    {
      Vector3 Model;
      Vector3 World;
      Vector3 View;
      Vector3 Pos;
      DWORD Diffuse;
      DWORD Specular;
      float tu,tv;
    
      Vertex3D(void):Model(Vector3(0.0f,0.0f,0.0f)),
                               World(Vector3(0.0f,0.0f,0.0f)),
                               View(Vector3(0.0f,0.0f,0.0f)),
                               Pos(Vector3(0.0f,0.0f,0.0f)),
                               Diffuse(0),
                               Specular(0);
                               tu(0.0f),
                               tv(0.0f)  {}
    
      Vertex3D(Vector3 _pos,DWORD _diffuse=0,DWORD Specular=0,
                      float _tu=0.0f,float tv=0.0f):Pos(_pos),
                      Diffuse (_diffuse),Specular(_specular),tu(_tu),
                      tv(_tv) {}
    };
    
    template <class T> class VertexBuffer
    {
      T *m_pVertexData;
      DWORD m_dwNumVertices;
      DWORD m_dwStride;
      
      public:
         VertexBuffer(void):m_pVertexData(null),m_dwNumVertices(0),m_dwStride(0) {}
    
         bool Create(DWORD _numverts,DWORD _stride);
         T *Lock(void) {return m_pVertexData;}
    };
    
    template <class T>
      bool VertexBuffer<T>::Create(DWORD _numverts,DWORD _stride)
    {
      m_pVertexData=new T[_numverts];
      if (!m_pVertexData) return false;
      m_pdwStride=_stride;
      return true;
    }
    Now you can create a vertex buffer of any type using:

    VertexBuffer<Vertex3D> MyVertexBuffer;


    You can also create a class for index buffers quite easily. Index buffers hold the element numbers of the vertices as they appear in the array. This allows you to access the vertex buffer based on element positions and can speed up rendering since you don't have to repeat vertices to create a primitive. To create a quad without an index buffer you need to create 6 vertices. 2 of them will be the same exact vertex. So why waste memory repeating vertex data? Solution: Use an index buffer. The index buffer is like a draw by the number type setup. With an index buffer you only need to have 4 vertices for a quad. Here is what the index buffer would look like using a counter-clockwise winding order.

    0,1,2 - 1st triangle
    2,1,3 - 2nd triangle

    The index buffer does not have any connection whatsoever with the vertex data. So the two classes can be separate.

    The draw function in your 3D library might look like this:

    bool Draw(VertexBuffer *pVB,IndexBuffer *pIB=NULL,BYTE PrimitiveType=3DPRIMS_POINT);

    Or you can set up streams like Direct3D uses. Hook the vertex data up to a stream and you will have a simple version of Direct3D or a different version of OpenGL type rendering.

    If you have problems let me know. The Vector3 class comes from one of my 3D books and since I don't use it, I thought I'd post it.
    No guarantees as to code accuracy. That's a lot of code to type while sitting here.
    Last edited by VirtualAce; 10-22-2005 at 01:02 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. SMS sample code
    By hagenuk in forum C Programming
    Replies: 1
    Last Post: 05-30-2008, 11:47 AM
  2. Sample code please help!!!
    By aewing30 in forum C Programming
    Replies: 6
    Last Post: 05-29-2008, 10:51 AM
  3. The code sample of classes in the tutorial. :o
    By Wall in forum C++ Programming
    Replies: 3
    Last Post: 08-20-2004, 09:18 AM
  4. looking for book with sample code
    By stella in forum C++ Programming
    Replies: 5
    Last Post: 06-25-2003, 10:48 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM