OpenGL and pixel access

I’m having a problem with OpenGL and SDL. I get a segmentation fault when I
try to access the pixels directly. I’ve used the SDL example as a reference,
and the code looks like this:

int main(int argc, char *argv[]) {
SDL_Surface *screen;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    screen = SDL_SetVideoMode(800, 600, 32, NULL, SDL_OPENGL);

            Uint32          *pixels = (Uint32 *) screen->pixels;

            SDL_LockSurface(screen);

            pixels[0] = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);

            SDL_UnlockSurface(screen);

            SDL_UpdateRect(screen, 0, 0, 1, 1);

    sleep(2);

    SDL_Quit();

}

This should place a white dot in the top left corner of the screen, but I get 

a seg-fault as I mentioned. If I remove SDL_OPENGL from the videomode flags
it works fine. So my question is, how do I modify the Surface pixels through
SDL (or any other method for that matter) directly when using OpenGL?–
Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

I think the general answer, you don’t.

Of course, you could instead use the gl write-to-buffer
functions, eg. glDrawPixels(), for overlays etc.
Mind the “raster position” mechanism of OpenGL though;
it’s a bit non-intuitive.

/Olof

Simon Ejsing: “[SDL] OpenGL and pixel access” (2004-05-17 14:49)

I’m having a problem with OpenGL and SDL. I get a segmentation fault when I

#try to access the pixels directly. I’ve used the SDL example as a reference,
#and the code looks like this:#
#int main(int argc, char *argv[]) {

SDL_Surface *screen;

SDL_Init(SDL_INIT_VIDEO);

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

screen = SDL_SetVideoMode(800, 600, 32, NULL, SDL_OPENGL);

Uint32 *pixels = (Uint32 *) screen->pixels;

SDL_LockSurface(screen);

pixels[0] = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff);

SDL_UnlockSurface(screen);

SDL_UpdateRect(screen, 0, 0, 1, 1);

sleep(2);

SDL_Quit();

#}

This should place a white dot in the top left corner of the screen, but I get

#a seg-fault as I mentioned. If I remove SDL_OPENGL from the videomode flags
#it works fine. So my question is, how do I modify the Surface pixels through
#SDL (or any other method for that matter) directly when using OpenGL?

Thanks for you fast reply.

Yeah, I've been fooling around with that too, my code looks like this:

void draw() {
unsigned char color[3] = { 0xFF, 0xFF, 0xFF };
int w = getWidth();
int h = getHeight();

glRasterPos2i(0, 0);

glDrawPixels(1, 1, GL_RGB, GL_UNSIGNED_BYTE, &color);

}

That, I would think, draws a white dot in top left corner. But this does not 

seem to be the case, can you give me a hint to fix it? Do I need to do
something like UpdateRect?On Monday 17 May 2004 14:55, Olof Bjarnason wrote:

I think the general answer, you don’t.

Of course, you could instead use the gl write-to-buffer
functions, eg. glDrawPixels(), for overlays etc.
Mind the “raster position” mechanism of OpenGL though;
it’s a bit non-intuitive.

/Olof


Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

I’m having a problem with OpenGL and SDL. I get a segmentation
fault when I try to access the pixels directly. I’ve used the SDL
example as a reference, and the code looks like this:

int main(int argc, char *argv[]) {
SDL_Surface *screen;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    screen = SDL_SetVideoMode(800, 600, 32, NULL, SDL_OPENGL);

You can’t do this with OpenGL, since it doesn’t support direct frame
buffer access. (This is one major PITA for the glSDL backend…)

You have to use OpenGL calls to read and write pixels. You should
avoid those, though, since they’re generally slow, and may interfere
with accelerated rendering. (Must hard-sync the CPU with the
accelerator, so you can’t have the CPU and GPU working in parallel
==> potential major frame rate reduction.)

            Uint32          *pixels = (Uint32 *)

screen->pixels;

You must read screen->pixels after locking the surface! The pointer
is can be NULL or invalid on unlocked h/w surfaces.

            SDL_LockSurface(screen);

            pixels[0] = SDL_MapRGB(screen->format, 0xff, 0xff,

0xff);

            SDL_UnlockSurface(screen);

            SDL_UpdateRect(screen, 0, 0, 1, 1);

    sleep(2);

    SDL_Quit();

}

This should place a white dot in the top left corner of the
screen, but I get a seg-fault as I mentioned.

Yep, because the SDL_OPENGL backend doesn’t support access of the
display surface, or even SDL rendering calls for that matter. Either
you use OpenGL or you don’t - as simple as that. (Well, almost. :slight_smile:

If I remove
SDL_OPENGL from the videomode flags it works fine. So my question
is, how do I modify the Surface pixels through SDL (or any other
method for that matter) directly when using OpenGL?

Have a look at the glSDL/wrapper code:

http://olofson.net/mixed.html

It implements SDL_BlitSurface(), SDL_FillRect() etc on top of OpenGL.
IIRC, screen locking (pixel access) is in 0.6 as well, but I’m not
sure…

Anyway, what do you want to do, actually…?

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Monday 17 May 2004 14.49, Simon Ejsing wrote:

Simon Ejsing wrote:>On Monday 17 May 2004 14:55, Olof Bjarnason wrote:

I think the general answer, you don’t.

Of course, you could instead use the gl write-to-buffer
functions, eg. glDrawPixels(), for overlays etc.
Mind the “raster position” mechanism of OpenGL though;
it’s a bit non-intuitive.

/Olof

Thanks for you fast reply.

Yeah, I’ve been fooling around with that too, my code looks like this:

void draw() {
unsigned char color[3] = { 0xFF, 0xFF, 0xFF };
int w = getWidth();
int h = getHeight();

glRasterPos2i(0, 0);

glDrawPixels(1, 1, GL_RGB, GL_UNSIGNED_BYTE, &color);
}

That, I would think, draws a white dot in top left corner. But this does not
seem to be the case, can you give me a hint to fix it? Do I need to do
something like UpdateRect?

Don’t forget that in OpenGL, the position described as (0, 0) is
actually the LOWER left corner:

o(0, HEIGHT)-(WIDTH, HEIGHT)o
| |
| |
| |
| |
o(0, 0)-----------(WIDTH, 0)o

It’s like a mathematical graph positioning system, just using quadrant
I. Make sure you check your lower left corner for the white dot, as
that’s what got me for my first OpenGL test project. ^_^;;;

Good luck!
–Scott

Okay, I’ve had some mail server problems apparently, I hope it’s fixed now.

To swap the OpenGL buffers in SDL/OpenGL, you use

SDL_GL_SwapBuffers()

… which completely replaces the SDL updaterects/flip etc.
functions.

Did it help?

/Olof

I've done some testing, and found the problem is with the raster position and 

depth buffering. If I disable depth buffer I can get it to show (makes
sense), and the raster position works now too.

But as someone mentioned before, it's awefully slow to draw this way. Is 

there a better way to draw overlay graphics on a 3d scene? Or can I speed
things up by using blitting somehow? Right now I’m only using it to draw a
crosshair at 0,0 so I can chech how position and scaling works, but in the
near future, I would like to be able to draw fullscreen images as overlay.

Thanks for all the help!-- 

Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

[…]

But as someone mentioned before, it’s awefully slow to draw this
way. Is there a better way to draw overlay graphics on a 3d scene?

The only proper (ie fast and reliable) way of rendering is the normal
OpenGL primitives. Overlays are done just like any other polygons,
except that you make sure they’re always rendered in the plane of the
screen. The easiest way of doing that is to just change the view
matrix when rendering the overlays.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Tuesday 18 May 2004 10.30, Simon Ejsing wrote:

I’ve done some testing, and found the problem is with the raster position and
depth buffering. If I disable depth buffer I can get it to show (makes
sense), and the raster position works now too.

But as someone mentioned before, it’s awefully slow to draw this way. Is
there a better way to draw overlay graphics on a 3d scene? Or can I speed
things up by using blitting somehow? Right now I’m only using it to draw a
crosshair at 0,0 so I can chech how position and scaling works, but in the
near future, I would like to be able to draw fullscreen images as overlay.

If your overlay doesn’t change, I suggest putting it into a texture, and then use an ortho projection and simply draw it using a quad. That’s about as fast as it can be and it’s also perfect for things like crosshairs, HUDs or simple health/score/lives type display.

There is no way to overlay a 2D blit on a 3D scene with SDL (well, there used to be one, but I’m not going to talk about it since it’s long deprecated :slight_smile:

Stephane

Actually, the way to go with OpenGL is textures. Use textures for everything…

That’s why pixel-level changes are somewhat anti-opengl, since then you
either have to

  1. create a 1x1 texture for every pixel you want or
    use previous glDrawPixels

  2. update some whole-screen texture using glTexSubImage
    (I’m not completely sure of the name…) but this might
    very well be as slow as 1

  3. Use GL_POINTS or something and combine with glColor
    to draw all your pixels, haven’t ever tried this out.

  4. … anyone got any more suggestions?

  5. might be performance improved by for example vertex arrays/vertex buffer
    objects.

I use openGL textures for everything, including font rendering. If you
want pixel-level effects eg. pixel-sized particles etc., I really have no
generally good advice for OpenGL.

What exactly do you want to do?

/Olof

Simon Ejsing: “Re: [SDL] OpenGL and pixel access” (2004-05-18 10:30)

Okay, I’ve had some mail server problems apparently, I hope it’s fixed now.#

#> To swap the OpenGL buffers in SDL/OpenGL, you use
#>
#> SDL_GL_SwapBuffers()
#>
#> … which completely replaces the SDL updaterects/flip etc.
#> functions.
#>
#> Did it help?
#>
#> /Olof

I’ve done some testing, and found the problem is with the raster position and

#depth buffering. If I disable depth buffer I can get it to show (makes
#sense), and the raster position works now too.

But as someone mentioned before, it’s awefully slow to draw this way. Is

#there a better way to draw overlay graphics on a 3d scene? Or can I speed
#things up by using blitting somehow? Right now I’m only using it to draw a
#crosshair at 0,0 so I can chech how position and scaling works, but in the
#near future, I would like to be able to draw fullscreen images as overlay.

Thanks for all the help!

Actually, the way to go with OpenGL is textures. Use textures for everything…

That’s why pixel-level changes are somewhat anti-opengl, since then you
either have to

  1. create a 1x1 texture for every pixel you want or
    use previous glDrawPixels

That sounds like a bad idea. You’d need to transfer geometry, color and texture coordinates for each point, while only color is needed.

  1. update some whole-screen texture using glTexSubImage
    (I’m not completely sure of the name…) but this might
    very well be as slow as 1

That’s basically a nice idea, but not all OpenGL drivers support glTexSubImage the rigth way, i.e. upload only the modified part :-/

  1. Use GL_POINTS or something and combine with glColor
    to draw all your pixels, haven’t ever tried this out.

The issue is that you might get cracks between points. IIRC, the spec says that you must translate everything with glTranslate3f(0.375f, 0.375f, 0.f);
Plus, that’s slow as you still have to send all the data through the bus.

  1. … anyone got any more suggestions?

If that’s some kind of HUD, I’d suggest putting each part of the hud in a texture (one texture for the font, one texture for the life indicators…), and draw each part indepentetly. That’s how I do it usually. Basically, the idea is that the HUD has to be generated from graphics that are already resident in video memory.

Stephane

I believe textures is the right approach for me too.

I just want to display an image from 0,0 with width and height equal to my 

display size (eg. 800x600), so that it acts as either a background or an
overlay for my 3d graphics (eg. a HUD). However I don’t fully get how I can
make sure the GL quad covers exactly (0,0) to (800,600), and if you add the
ability to resize the window, it get’s even more complicated.

So I guess, what I need is a way to tell the coordinates for my four cornors 

of the screen, at a distance of my zNear and zFar values?On Tuesday 18 May 2004 10:49, Olof Bjarnason wrote:

I use openGL textures for everything, including font rendering. If you
want pixel-level effects eg. pixel-sized particles etc., I really have no
generally good advice for OpenGL.

What exactly do you want to do?


Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

Stephane Marchesin: “Re: Re: [SDL] OpenGL and pixel access” (2004-05-18…

#>
#> Actually, the way to go with OpenGL is textures. Use textures for everything…
#>
#> That’s why pixel-level changes are somewhat anti-opengl, since then you
#> either have to
#>
#> 1. create a 1x1 texture for every pixel you want or
#> use previous glDrawPixels#
#That sounds like a bad idea. You’d need to transfer geometry, color and texture coordinates for each point, while only color is needed.

#> 2. update some whole-screen texture using glTexSubImage
#> (I’m not completely sure of the name…) but this might
#> very well be as slow as 1

#That’s basically a nice idea, but not all OpenGL drivers support glTexSubImage the rigth way, i.e. upload only the modified part :-/

#> 3. Use GL_POINTS or something and combine with glColor
#> to draw all your pixels, haven’t ever tried this out.

#The issue is that you might get cracks between points. IIRC, the spec says that you must translate everything with glTranslate3f(0.375f, 0.375f, 0.f);
#Plus, that’s slow as you still have to send all the data through the bus.

#> 4. … anyone got any more suggestions?

#If that’s some kind of HUD, I’d suggest putting each part of the hud in a texture (one texture for the font, one texture for the life indicators…), and draw each part indepentetly. That’s how I do it usually. Basically, the idea is that the HUD has to be generated from graphics that are already resident in video memory.
He was actually talking about pixel-level manipulations. Otherwise i’d go for
textured HUD directly…

/Olof

#Stephane

#_______________________________________________
#SDL mailing list
#SDL at libsdl.org
#http://www.libsdl.org/mailman/listinfo/sdl

Simon Ejsing: “Re: [SDL] OpenGL and pixel access” (2004-05-18 10:59)

#On Tuesday 18 May 2004 10:49, Olof Bjarnason wrote:
#> I use openGL textures for everything, including font rendering. If you
#> want pixel-level effects eg. pixel-sized particles etc., I really have no
#> generally good advice for OpenGL.
#>
#> What exactly do you want to do?#

I believe textures is the right approach for me too.

I just want to display an image from 0,0 with width and height equal to my

#display size (eg. 800x600), so that it acts as either a background or an
#overlay for my 3d graphics (eg. a HUD). However I don’t fully get how I can
#make sure the GL quad covers exactly (0,0) to (800,600), and if you add the
#ability to resize the window, it get’s even more complicated.

So I guess, what I need is a way to tell the coordinates for my four cornors

#of the screen, at a distance of my zNear and zFar values?
Read about glOrtho(), it might simplify this somewhat :slight_smile:

/Olof

I believe textures is the right approach for me too.

I just want to display an image from 0,0 with width and height equal to my
display size (eg. 800x600), so that it acts as either a background or an
overlay for my 3d graphics (eg. a HUD). However I don’t fully get how I can
make sure the GL quad covers exactly (0,0) to (800,600), and if you add the
ability to resize the window, it get’s even more complicated.

Well, there’s a very easy way around this using textures and the OpenGL transformation.

Here’s what I do : after 3D drawing, I set the modelview matrix to a virtual 640x480 screen, whatever the real resolution of the screen is. Then I draw my HUD using quads and using absolute coordinates in [0,639]x[0,479] and let OpenGL do the scaling of the quads to the real screen resolution.

So I guess, what I need is a way to tell the coordinates for my four cornors
of the screen, at a distance of my zNear and zFar values?

Sell, once you’ve changed the modelview matrix, there’s no need anymore to worry about the z values.

Stephane

Okay, you lost me there… but I got it to work this way using Ortho:

glDisable(GL_DEPTH_TEST);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluOrtho2D(0, w, 0, h);

glBegin(GL_QUADS);
	glVertex3f(10, 10, 0);
	glVertex3f(w, 10, 0);
	glVertex3f(w, h, 0);
	glVertex3f(10, h, 0);
glEnd();

This gives me pixel precision as I wanted, so now I just need to figure out 

how to put the texture on correctly, but I guess that’s the easy part :)On Tuesday 18 May 2004 11:06, Stephane Marchesin wrote:

I just want to display an image from 0,0 with width and height equal to

my display size (eg. 800x600), so that it acts as either a background or
an overlay for my 3d graphics (eg. a HUD). However I don’t fully get how
I can make sure the GL quad covers exactly (0,0) to (800,600), and if you
add the ability to resize the window, it get’s even more complicated.

Well, there’s a very easy way around this using textures and the OpenGL
transformation.

Here’s what I do : after 3D drawing, I set the modelview matrix to a
virtual 640x480 screen, whatever the real resolution of the screen is. Then
I draw my HUD using quads and using absolute coordinates in [0,639]x[0,479]
and let OpenGL do the scaling of the quads to the real screen resolution.

So I guess, what I need is a way to tell the coordinates for my four

cornors of the screen, at a distance of my zNear and zFar values?

Sell, once you’ve changed the modelview matrix, there’s no need anymore to
worry about the z values.


Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

Simon Ejsing: “Re: [SDL] OpenGL and pixel access” (2004-05-18 11:14)

#On Tuesday 18 May 2004 11:06, Stephane Marchesin wrote:
#> > I just want to display an image from 0,0 with width and height equal to
#> > my display size (eg. 800x600), so that it acts as either a background or
#> > an overlay for my 3d graphics (eg. a HUD). However I don’t fully get how
#> > I can make sure the GL quad covers exactly (0,0) to (800,600), and if you
#> > add the ability to resize the window, it get’s even more complicated.
#>
#> Well, there’s a very easy way around this using textures and the OpenGL
#> transformation.
#>
#> Here’s what I do : after 3D drawing, I set the modelview matrix to a
#> virtual 640x480 screen, whatever the real resolution of the screen is. Then
#> I draw my HUD using quads and using absolute coordinates in [0,639]x[0,479]
#> and let OpenGL do the scaling of the quads to the real screen resolution.
#>
#> > So I guess, what I need is a way to tell the coordinates for my four
#> > cornors of the screen, at a distance of my zNear and zFar values?
#>
#> Sell, once you’ve changed the modelview matrix, there’s no need anymore to
#> worry about the z values.#

Okay, you lost me there… but I got it to work this way using Ortho:

What he means is that you may use the code you’ve typed below even if you change
your window/screen resolution… try it out! Note: let w,h be your "virtual"
resolution, eg. 640x480, and some other vars/defines WIDTH/HEIGHT be your
actual, window/screen resolution, and keep them separate!

good luck

/Olof

glDisable(GL_DEPTH_TEST);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0, w, 0, h);

glBegin(GL_QUADS);

glVertex3f(10, 10, 0);

glVertex3f(w, 10, 0);

glVertex3f(w, h, 0);

glVertex3f(10, h, 0);

glEnd();

This gives me pixel precision as I wanted, so now I just need to figure out

#how to put the texture on correctly, but I guess that’s the easy part :slight_smile:

That’s cool, saves you a lot of time! Thanks for the help!On Tuesday 18 May 2004 11:22, Olof Bjarnason wrote:

What he means is that you may use the code you’ve typed below even if you
change your window/screen resolution… try it out! Note: let w,h be your
"virtual" resolution, eg. 640x480, and some other vars/defines WIDTH/HEIGHT
be your actual, window/screen resolution, and keep them separate!

good luck


Simon Ejsing, Systemudvikler
esoft ApS, http://www.esoft.dk
Skibhusvej 52C, DK-5000 Odense C.
Tlf: 70 222 466, Fax: 63 122 466

Don’t forget that in OpenGL, the position described as (0, 0) is
actually the LOWER left corner:

Simply not true. glRasterPos*() is transformed by the modelview and
projection matrices like glVertex and pals are. Therefore, lower left
corner coordinates are whatever you set via the projection matrix.–
Petri Latvala

Simon Ejsing wrote:

       I believe textures is the right approach for me too.

       I just want to display an image from 0,0 with width and height

equal to my

display size (eg. 800x600), so that it acts as either a background or an
overlay for my 3d graphics (eg. a HUD). However I don’t fully get how I
can
make sure the GL quad covers exactly (0,0) to (800,600), and if you add
the
ability to resize the window, it get’s even more complicated.

       So I guess, what I need is a way to tell the coordinates for

my four cornors

of the screen, at a distance of my zNear and zFar values?

Could you post some code showing how do you do that ? I’m mixing a
a 2D app with SDL and OpenGL but i have to paint the background (a 1024x768
bitmap) using glRasterPos2f and glDrawPixels, but i was wondering if there
is some better way to do that.

Thanks,
Jorge

jorgefm at cirsa.com: “Re: [SDL] OpenGL and pixel access” (2004-05-20…#

#Simon Ejsing wrote:

#> I believe textures is the right approach for me too.
#>
#> I just want to display an image from 0,0 with width and height
#equal to my
#>display size (eg. 800x600), so that it acts as either a background or an
#>overlay for my 3d graphics (eg. a HUD). However I don’t fully get how I
#can
#>make sure the GL quad covers exactly (0,0) to (800,600), and if you add
#the
#>ability to resize the window, it get’s even more complicated.
#>
#> So I guess, what I need is a way to tell the coordinates for
#my four cornors
#>of the screen, at a distance of my zNear and zFar values?
#>

#Could you post some code showing how do you do that ? I’m mixing a
#a 2D app with SDL and OpenGL but i have to paint the background (a 1024x768
#bitmap) using glRasterPos2f and glDrawPixels, but i was wondering if there
#is some better way to do that.
Instead of trying to find those coordinates, as simpler way is to setup
an orthographics (“2D”) projection matrix:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,WIDTH,HEIGHT,0);

… when you want to paint your background texture, because that is what
you want to use, not glDrawPixels(). OpenGL is made for textures on modern
hardware. So, upload your background picture to some OpenGL texture,
and the first thing you do in your rendering routine, draw this texture,
then go back to 3d-projection matrix or what have you, and draw the rest
of the scene. Note that you don’t have to glClear(GL_COLOR_BUFFER_BIT|
GL_DEPTH_BUFFER_BIT) then but only glClear(GL_DEPTH_BUFFER_BIT)…
To switch between the to projection matrixes, you might want to use
the matrix stack glPushMatrix()/glPopMatrix for convenience…
Just remenber to switch back to MODELVIEW matrix, that’s a very common
bug for me :wink:

good luck,

/Olof

#Thanks,
#Jorge

#_______________________________________________
#SDL mailing list
#SDL at libsdl.org
#http://www.libsdl.org/mailman/listinfo/sdl