PDA

View Full Version : openGL glDrawPixels


jackinoob
10-12-2007, 09:27 AM
Greetings,

I'd like some help in using the function glDrawPixels.This is the function definition and I am wondering what format is *pixels? Does it point to an array holding RGB values of each pixel? I'm not quite sure what the exact format is. If i know the RGB values of my pixels to be drawn, how can I create *pixels?

void glDrawPixels(
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *pixels
);

Also, I'm not even sure if this is the function I need to use. Basically depending on where the mouse is, I need to draw certain pixels. GL_BEGIN GL_END draws a new object every time the mouse has changed position, and I would like whatever is drawn to remain...kind of like a paint program. Please give me advice.

Thanks!

Ian Jones
10-13-2007, 05:49 AM
http://www.opengl.org/resources/code/samples/glut_examples/examples/abgr.c

Basically you need to provide unsigned bytes to 'pixels' as you can see in this example code.

gga
10-14-2007, 09:05 AM
No. Pixels can be in any format your graphics card supports.

format is usually a form of RGB(A) like GL_RGBA, GL_RGB, or GL_BGRA, GL_BGR, etc. Some OS and cards might also support YUV formats.

type can be any pixel type like GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_FLOAT, GL_HALF_FLOAT, etc.

It is your responsability to make sure the GL_enum format and GL_enum type is set correctly for your graphics card (as not all cards support all pixel formats or pixel types). You usually do this by checking the presence of GL extension for them (or the version of OpenGL, which guarantees certain extensions). The libraries GLEE and GLEW make this a tad easier.

format: GL_RGB and type: GL_UNSIGNED_BYTE is the one format guaranteed to work on pretty much every graphics card since the 90s, but usually not the only one available to you.

Ian Jones
10-14-2007, 01:32 PM
yeh sorry, was a rushed reply. He is correct, you can specify the format. It strongly depends on what and how you load or get the pixels from in the first place. Look closely at texture loading examples and this will help guide you to getting the right data into this function.

jackinoob
10-17-2007, 06:50 AM
Thank you!

I actually ended up using glDrawArrays, and it works great.

My question now is, does anybody know how to draw solid circles around origins stored in an array, with glDrawArrays? or does glDrawArrays just suppoert the usual GL_POINTS, GL_TRIANGLES, etc? Does anybody know is there are other ways of drawing an array of filled circles? Thank you very much.

UrbanFuturistic
10-17-2007, 08:45 AM
Does it have to be a completely accurate circle or would you settle for a close approximation?

You could use a triangle fan to approximate or you could use a mip-mapped circle texture with transparency and vertex colours to determine its overall colour on screen.

If you want it 100% accurate then you're looking at using 2D graphics techniques and drawing onto a texture the same size as (or close to) the display window.

jackinoob
10-17-2007, 05:45 PM
An approximated circle would be just fine, in fact I am drawing my circles right now with triangles. This is code I picked up from http://www.gmonline.demon.co.uk/cscene/CS6/CS6-06.html.

But I would like to know if there is a way to use drawArray (or a similar structure) to draw circles based on origins in an array, same way as you would to GL_POINTS for example?

vectorY1=originY;
vectorX1=originX;

glBegin(GL_TRIANGLES);
for(i=0;i<=360;i++)
{
angle=(float)(((double)i)/57.29577957795135);
vectorX=originX+(radius*(float)sin((double)angle));
vectorY=originY+(radius*(float)cos((double)angle));
glVertex2d(originX,originY);
glVertex2d(vectorX1,vectorY1);
glVertex2d(vectorX,vectorY);
vectorY1=vectorY;
vectorX1=vectorX;
}
glEnd();

UrbanFuturistic
10-17-2007, 11:26 PM
How much do you know about display lists and GL transform functions? A display list would mean all those sine and cosine calculations would only need to be done once, the transform would take care of position and scaling. Failing that, using a transform GL translate and scale functions would be useful.

I'll have to brush up on my OpenGL a little, my head's full of image transformations and scanline algorithms. Let me know what you know and hopefully I can fill in the blanks :)

jackinoob
10-18-2007, 05:23 AM
Thanks!

So basically I have an array whose element values are dynamically changing as the mouse moves, values reflect mouse position and some neighbors. For all x,y,z triples in ( array[i], array[i+1], array[i+2] ) I'd like to draw a circle *simultaneously*. So as you suggested I've made a display list for the circle as follows, just inserted a sphere instead of a circle to make the code easier for now:

glNewList(circle, GL_COMPILE);
for (i=0; i<12; i++) {
glColor3f(1.0, 0.0,0.0);
glTranslatef(array[i*3], array[(i*3)+1], array[(i*3)+2]);
glutSolidSphere(30.0,15,15);
}
glEndList();

and then glCallList(circle);

But this does not draw all circles simultaneously, as would glDrawArray. Any ideas on how to make this mouse trail work with circles/spheres?

jackinoob
10-18-2007, 08:32 AM
Ok, got the list stuff working. Thank you Odubtaig for suggesting it! :)

Robert Bateman
10-18-2007, 02:40 PM
using vertex arrays rather than display lists. would be trivial to convert the code to VBO instead...


#include <vector>

// resolution of circle. 100 is probably a bit high, can probably get away with less.
// lower the number, better the performance...
#define NUM_CIRCLE_POINTS 100

// struct to hold a circle
struct Circle
{
float size; ///< size of circle
float x; ///< x coord
float y; ///< y coord

// ctor
Circle(float s,float x_,float y_)
: x(x_), y(y_), size(s){}

// copy ctor
Circle(const Circle& c)
: x(c.x), y(c.y), size(c.size) {}

// render func (assumes the vertex pointer has been set)
inline void draw() const
{
glPushMatrix();
glTranslatef(x,y,0);
glScalef(size,size,1.0f);
glDrawArrays(GL_TRIANGLE_FAN,0,NUM_CIRCLE_POINTS + 1);
glPopMatrix();
}
};

// inherits from std::vector to store a dynamic array of circles
struct CircleList
: protected std::vector<Circle>
{
CircleList();

// clears all circles from the list
inline void clear()
{
std::vector<Circle>::clear();
}

// adds a new circle
inline void add(float _size,float x,float y)
{
push_back(Circle(_size,x,y));
}

// draws them all
inline void draw()
{
// tell openGL where the vertex data is
glVertexPointer(2,GL_FLOAT,sizeof(float)*2,g_TriangleData);

// enable the vertex arrays
glEnableClientState(GL_VERTEX_ARRAY);

// now draw each circle
for(iterator it = begin(); it != end(); ++it)
{
it->draw();
}

// disable the vertex arrays
glDisableClientState(GL_VERTEX_ARRAY);
}

// returns number of circles stored
unsigned numCircles() const
{
return static_cast<unsigned>(size());
}

private:

// shared vertex data.
static float* g_TriangleData;
};

float* CircleList::g_TriangleData=0;

// init vertex array data. call this before drawing any data...
CircleList::CircleList()
: std::vector<Circle>()
{
// only do setup of the vertex array once...
if(g_TriangleData==0)
{
// alloc vertex data
g_TriangleData = new float[ 2*(NUM_CIRCLE_POINTS+1) ];

// tri center
g_TriangleData[0] = g_TriangleData[1] = 0.0f;

// iterator over vertex data
float* ptr = g_TriangleData + 2;
float* end = ptr + (NUM_CIRCLE_POINTS*2);

// init all verts
for(float angle=0;ptr != end;ptr +=2)
{
ptr[0] = sinf(angle); // x
ptr[1] = cosf(angle); // y

// 360 degrees = 2*PI
angle += (6.283185307179586476925286766559f/(NUM_CIRCLE_POINTS-1));
}
}
}

void test()
{
CircleList cl;
for(float i=0;i<10;i+=1.0f)
{
cl.add(i*0.1f+0.2f,i*2.0f,5.0f);
}
cl.draw();
}

UrbanFuturistic
10-18-2007, 03:54 PM
I was thinking more along the lines of doing a display list for a circle then translating and scaling that according to values held in an array and drawing it X amount of times before swapping the buffers.

I need to get something down, then I'll edit this post.

Robert Bateman
10-18-2007, 04:57 PM
I was thinking more along the lines of doing a display list for a circle then translating and scaling that according to values held in an array and drawing it X amount of times before swapping the buffers.

however if you convert the above code to a static VBO, you basically will get the same performance as the display list method (minus the additional function call overhead you get with glBegin/glEnd). i.e.


#include <vector>

#define NUM_CIRCLE_POINTS 180

struct Circle
{
float size;
float x;
float y;

Circle(float s,float x_,float y_)
: x(x_), y(y_), size(s){}

Circle(const Circle& c)
: x(c.x), y(c.y), size(c.size) {}

inline void draw() const
{
glPushMatrix();
glTranslatef(x,y,0);
glScalef(size,size,1.0f);
glDrawArrays(GL_TRIANGLE_FAN,0,NUM_CIRCLE_POINTS + 1);
glPopMatrix();
}
};

struct CircleList
: protected std::vector<Circle>
{
CircleList();

// clears all circles from the list
inline void clear()
{
std::vector<Circle>::clear();
}

// adds a new circle
inline void add(float _size,float x,float y)
{
push_back(Circle(_size,x,y));
}

// draws them all
inline void draw()
{
// bind VBO
glBindBuffer(GL_ARRAY_BUFFER,g_VBO_id);

// tell openGL where the vertex data is
glVertexPointer(2,GL_FLOAT,sizeof(float)*2,(void*)0);

// enable the vertex arrays
glEnableClientState(GL_VERTEX_ARRAY);

// now draw each circle
for(iterator it = begin(); it != end(); ++it)
{
it->draw();
}

// disable the vertex arrays
glDisableClientState(GL_VERTEX_ARRAY);

// disable VBO
glBindBuffer(GL_ARRAY_BUFFER,0);
}

// returns number of circles stored
unsigned numCircles() const
{
return static_cast<unsigned>(size());
}

private:

static unsigned g_VBO_id;
};

unsigned CircleList::g_VBO_id=0;

// init vertex array data. call this before drawing any data...
CircleList::CircleList()
: std::vector<Circle>()
{
// only do setup of the vertex array once...
if(g_VBO_id==0)
{
// create VBO
glGenBuffers(1,&g_VBO_id);

// bind VBO
glBindBuffer(GL_ARRAY_BUFFER,g_VBO_id);

// alloc vertex data
float* TriangleData = new float[ 2*(NUM_CIRCLE_POINTS+1) ];

// tri center
TriangleData[0] = TriangleData[1] = 0.0f;

// iterator over vertex data
float* ptr = TriangleData + 2;
float* end = ptr + (NUM_CIRCLE_POINTS*2);

// init all verts
for(float angle=0;ptr != end;ptr +=2)
{
ptr[0] = sinf(angle); // x
ptr[1] = cosf(angle); // y

// 360 degrees = 2*PI
angle += (6.283185307179586476925286766559f/NUM_CIRCLE_POINTS);
}


// alloc data in the buffer and copy temp array
glBufferData(GL_ARRAY_BUFFER,2*(NUM_CIRCLE_POINTS+1)*sizeof(float),TriangleData,GL_STATIC_DRAW);

// delete temp tri data
delete [] TriangleData;
}
}


void test()
{
CircleList cl;

for(float i=0;i<10;i+=1.0f)
{
cl.add(i*2.0f + 1.0f,i*10.0f,5.0f);
}

cl.draw();

}

Robert Bateman
10-18-2007, 05:47 PM
got bored...

http://robthebloke.org/DrawCircles.zip

r = increase red colour
R = decrease red colour
g = increase green colour
G = decrease green colour
b = increase blue colour
B = decrease blue colour
s = increase size
S = decrease size
c = clear screen

UrbanFuturistic
10-18-2007, 06:07 PM
There is also the point, though, that display lists stay specifically in VRAM and, unlike vertex lists, don't have to be blitted across the memory subsystem, via the north and south bridges, every single time they're drawn, which is another overhead. That's the whole point of display lists.

Given that you can still specify colour, texture, specular, etc. outside a display list it is still considerably more efficient, especially when you get to the point of handling large data sets, be it a dense object or many copies of the same object. This is also why instancing has recently been included in the OpenGL spec (although I'm not sure if that's still an extension).

Robert Bateman
10-19-2007, 09:52 AM
There is also the point, though, that display lists stay specifically in VRAM and, unlike vertex lists, don't have to be blitted across the memory subsystem, via the north and south bridges, every single time they're drawn, which is another overhead. That's the whole point of display lists.

Not correct. In theory they can, but that is largely driver independent. static VBO's however *do* statically reside in vram. vertex arrays are client side true, but the zip example above does not use vertex arrays !!

Given that you can still specify colour, texture, specular, etc. outside a display list it is still considerably more efficient, especially when you get to the point of handling large data sets, be it a dense object or many copies of the same object.

This is simply not true. Read up on VBO's - they *are* the fastest way to handle large data sets.

This is also why instancing has recently been included in the OpenGL spec (although I'm not sure if that's still an extension).

but this has nothing to do with whether VBO's are slower than display lists. (erm, and if you read the openGL spec for the instancing you will notice is has been written with VBO's in mind, i.e. gl_VertexId)

CGTalk Moderation
10-19-2007, 09:52 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.