Drawing over OpenGL

Hi,

I am new to SDL and tried to create a rotating cube with OpenGL in SDL. OK,
this works, but now I am interested in how can I draw lines and rectangles
over the OpenGL screen. I already tried to use the SDL_FillRect() Function
but it didn’t work. Before I called this function I locked the screen and
after that I unlocked it and called the function SDL_UpdateRect().

Karsten

There are basically three ways of doing this; one that I’m not even going to name, one that isn’t really meant for this kind of stuff: glSDL, and the one you should use: OpenGL.

glSDL (http://olofson.net/mixed.html) is an implementation of SDL’s blitting API on top of OpenGL, and the features supported so far are pretty fast. (There will be slow “SDL compatibility” features eventually, such as blitting from the screen and locking the screen for direct s/w rendering. Those are needed for “correctness”, but shouldn’t be used by glSDL aware applications.)

However, as you’re hacking an OpenGL application, you should simply do things as they were intended to be done; through OpenGL. Accelerated 3D (OpenGL, DirectX, Glide, …), accelerated 2D (GDI, Xlib, …) and software rendering (SDL, SGE, …) generally don’t mix, since they rely on different drivers and different methods. Just pick one and stick with it, and at least there’s a chance you get reasonable performance.

As to actually doing it (without relying on features that are accelerated only by professional cards and some “hacked” drivers); how about plain polygons? (Just turn texturing off and use vertex colors.)

For antialiased lines, you could use an RGBA texure with a bunch of while lines in different widths on it. (Some transparent space in between the lines, obviously.) You can have the texture “repeat” endlessy, so the size of the texture isn’t really important - just make it large enough to fit the line widths you need. (Keep in mind that you can’t stretch this texture, as that would just result in fat, blurred edges rather than antialiasing.)

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Fri, 28/06/2002 14:15:08 , Karsten Hachmeister wrote:

Hi,

I am new to SDL and tried to create a rotating cube with OpenGL in SDL. OK,
this works, but now I am interested in how can I draw lines and rectangles
over the OpenGL screen. I already tried to use the SDL_FillRect() Function
but it didn’t work. Before I called this function I locked the screen and
after that I unlocked it and called the function SDL_UpdateRect().

Friday, June 28, 2002, 8:55:04 AM, David wrote:

DO> On Fri, 28/06/2002 14:15:08 , Karsten Hachmeister wrote:

Hi,

I am new to SDL and tried to create a rotating cube with OpenGL in SDL. OK,
this works, but now I am interested in how can I draw lines and rectangles
over the OpenGL screen. I already tried to use the SDL_FillRect() Function
but it didn’t work. Before I called this function I locked the screen and
after that I unlocked it and called the function SDL_UpdateRect().

DO> However, as you’re hacking an OpenGL application, you should
DO> simply do things as they were intended to be done; through OpenGL.
DO> Accelerated 3D (OpenGL, DirectX, Glide, …), accelerated 2D (GDI,
DO> Xlib, …) and software rendering (SDL, SGE, …) generally don’t
DO> mix, since they rely on different drivers and different methods.
DO> Just pick one and stick with it, and at least there’s a chance
DO> you get reasonable performance.

I agree.

DO> As to actually doing it (without relying on features that are
DO> accelerated only by professional cards and some “hacked” drivers);
DO> how about plain polygons? (Just turn texturing off and use vertex
DO> colors.)

Be careful! Turning texturing off is often a way to SLOW DOWN consumer
graphics cards. Consumer 3D cards tend to be optimized for one thing:
drawing textured triangles. Falling off this fast path is usually
guaranteed to lose performance.

Vertex coloring works, but instead of turning texturing off, texture
with a small white rectangle (if you want to use simple coloring
methods at all).

DO> For antialiased lines, you could use an RGBA texure with a bunch
DO> of white lines in different widths on it. (Some transparent space
DO> in between the lines, obviously.) You can have the texture
DO> “repeat” endlessly, so the size of the texture isn’t really
DO> important - just make it large enough to fit the line widths you
DO> need. (Keep in mind that you can’t stretch this texture, as that
DO> would just result in fat, blurred edges rather than antialiasing.)

Similarly, many consumer cards do a terrible job of line drawing, as
David suggests. So avoid glLine calls, and instead generate long thin
rectangles and texture them with a line texture.

I don’t see much benefit in putting multiple line textures into a
single rectangular texture. It’s not like you’d save any significant
amount of space.

You can use OpenGL’s 1D or 2D texturing and simply set the texture to
repeat for the length of the line.

And although you probably don’t want to stretch a line texture, you
can probably get away with making just one and shrinking it, unless
you’re particularly picky or you’re making very wide lines.

And if you’re making wide lines, you probably have some serious work
to do anyway to generate the appropriate appearance for line ends and
joins.

Kent-- 

Kent Quirk, CTO, CogniToy
@Kent_Quirk
http://www.cognitoy.com

Friday, June 28, 2002, 8:55:04 AM, David wrote:
[…]
DO> As to actually doing it (without relying on features that are
DO> accelerated only by professional cards and some “hacked” drivers);
DO> how about plain polygons? (Just turn texturing off and use vertex
DO> colors.)

Be careful! Turning texturing off is often a way to SLOW DOWN consumer
graphics cards. Consumer 3D cards tend to be optimized for one thing:
drawing textured triangles. Falling off this fast path is usually
guaranteed to lose performance.

Vertex coloring works, but instead of turning texturing off, texture
with a small white rectangle (if you want to use simple coloring
methods at all).

Ouch! Thanks for the tip. (Didn’t know it was that bad with these “consumer cards”… heh)

DO> For antialiased lines, you could use an RGBA texure with a bunch
DO> of white lines in different widths on it. (Some transparent space
DO> in between the lines, obviously.) You can have the texture
DO> “repeat” endlessly, so the size of the texture isn’t really
DO> important - just make it large enough to fit the line widths you
DO> need. (Keep in mind that you can’t stretch this texture, as that
DO> would just result in fat, blurred edges rather than antialiasing.)

Similarly, many consumer cards do a terrible job of line drawing, as
David suggests.

Most of them don’t even accelerate lines at all, it seems…

So avoid glLine calls, and instead generate long thin
rectangles and texture them with a line texture.

I don’t see much benefit in putting multiple line textures into a
single rectangular texture. It’s not like you’d save any significant
amount of space.

Nah - I just figured indexing width -> texcoords is about as complicated as width -> texture name, so why waste space?

Besides, if you want to handle very fat lines, you’ll need rather large textures for the wider lines - and you’ll need many of them, as you can’t stretch them too much without blurring the edges.

That said, it’s probably a good idea to split very fat lines along their length and implement the “width scaling” in some other way.

BTW, any great ideas about how to do nice, antialiased “end caps”? :slight_smile:

You can use OpenGL’s 1D or 2D texturing and simply set the texture to
repeat for the length of the line.

Yeah, but you can’t adjust the line width that way. If you want antialiased lines (without FSAA, of course), you need a texture with an alpha channel so you can have a “border” of transparent pixels within the rendered polygons. (The texture filtering + alpha will take care of the AA.)

And although you probably don’t want to stretch a line texture, you
can probably get away with making just one and shrinking it, unless
you’re particularly picky or you’re making very wide lines.

That might work, though. Not sure if one should really expect this to give the same result, but considering how most cards do texture filtering, it should work pretty well.

And if you’re making wide lines, you probably have some serious work
to do anyway to generate the appropriate appearance for line ends and
joins.

Yeah… :slight_smile:

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Fri, 28/06/2002 10:20:48 , Kent Quirk <kent_quirk at cognitoy.com> wrote:

Friday, June 28, 2002, 11:34:54 AM, you wrote:

So avoid glLine calls, and instead generate long thin
rectangles and texture them with a line texture.

I don’t see much benefit in putting multiple line textures into a
single rectangular texture. It’s not like you’d save any significant
amount of space.

DO> Nah - I just figured indexing width -> texcoords is about as
DO> complicated as width -> texture name, so why waste space?

DO> Besides, if you want to handle very fat lines, you’ll need rather
DO> large textures for the wider lines - and you’ll need many of them,
DO> as you can’t stretch them too much without blurring the edges.

DO> That said, it’s probably a good idea to split very fat lines along
DO> their length and implement the “width scaling” in some other way.

DO> BTW, any great ideas about how to do nice, antialiased “end caps”? :slight_smile:

If you’re looking to join the lines with a pointed end cap, I don’t
see a way other than to do the math for where the intersection points
lie and to construct the appropriate triangles.

If you’re going to join with a rounded end cap, you MAY be able to get
away with drawing a circle (or solid arc) of appropriate size, as long
as everything you’re drawing is solid color with no alpha (you can
probably do some edge AA). Otherwise, you’ve got to do the math. Hence
my comments about having a lot of work to do.

You can use OpenGL’s 1D or 2D texturing and simply set the texture to
repeat for the length of the line.

DO> Yeah, but you can’t adjust the line width that way. If you want
DO> antialiased lines (without FSAA, of course), you need a texture
DO> with an alpha channel so you can have a “border” of transparent
DO> pixels within the rendered polygons. (The texture filtering +
DO> alpha will take care of the AA.)

I’m not sure we’re talking about the same thing. The idea is to stripe
the texture ACROSS the line, not along it.

Example:

Suppose you’re drawing a wide line. Here’s the polygon:--------------------------------------------------
| |
| |

You can make a 1D texture that looks like this:

<****>

(the < and > indicate alpha of 50%, the * is alpha of 0%.)

Then you apply it to the line like this:

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^




vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

This doesn’t give you antialiased ENDS on the line, but it handles the
width fine. But again, the end cap problem is a different problem.

DO> That might work, though. Not sure if one should really expect
DO> this to give the same result, but considering how most cards do
DO> texture filtering, it should work pretty well.

It does. We did it exactly this way in MindRover. Every line was a
thin quad textured across with a 1D texture that went from transparent
to solid to transparent. It worked great.

Kent


Kent Quirk, CTO, CogniToy
@Kent_Quirk
http://www.cognitoy.com

Not necessarily…

glDisable (GL_TEXTURE_2D) is the same as glBindTexture (GL_TEXTURE_2D, 0)
on most drivers. Texture ID 0 is always a plain white texture, which
makes since since most cards need a texture to draw, even if it’s plain
white, tinted according to vertex colors.

The trick is to avoid changing states more than you need to. Pick a state
and keep OpenGL in that state as long as possible. Change states and
repeat. Minimising state changes is the reason so many games render
indirectly today - they can sort their drawing operations so that they
only need to change major states two or three times a frame. Minor states
have to change more often, but you can’t avoid that no matter how much
sorting you do, obviously. =)On Fri, Jun 28, 2002 at 10:20:48AM -0400, Kent Quirk wrote:

DO> As to actually doing it (without relying on features that are
DO> accelerated only by professional cards and some “hacked” drivers);
DO> how about plain polygons? (Just turn texturing off and use vertex
DO> colors.)

Be careful! Turning texturing off is often a way to SLOW DOWN consumer
graphics cards. Consumer 3D cards tend to be optimized for one thing:
drawing textured triangles. Falling off this fast path is usually
guaranteed to lose performance.


Joseph Carter We can hope for the future
But there might not be one

Moonchild without an opinion? Satan is skating to work tomorrow!
– Brett Manz

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 273 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020628/8319e208/attachment.pgp

Friday, June 28, 2002, 11:34:54 AM, you wrote:
[…]
DO> Yeah, but you can’t adjust the line width that way. If you want
DO> antialiased lines (without FSAA, of course), you need a texture
DO> with an alpha channel so you can have a “border” of transparent
DO> pixels within the rendered polygons. (The texture filtering +
DO> alpha will take care of the AA.)

I’m not sure we’re talking about the same thing. The idea is to stripe
the texture ACROSS the line, not along it.

Ah! Of course. Wasn’t thinking straight. :slight_smile:

[…]

This doesn’t give you antialiased ENDS on the line,

Nor does the 2D texture variant…

Or does it? :wink:

but it handles the
width fine. But again, the end cap problem is a different problem.

What if you split the quad in three, to avoid stretching the end caps? That is, the line becomes three quads;

|----|----------------------------|----|
| | | |
| Q1 | Q2 | Q3 |

…and a texture looking like this:

|---------|
| |
| ####### |
|#########|
| ####### |

The texcoords of Q1 and Q3 are set up to render the endcaps from the texture at a 1:1 aspect ratio, while the texcoords of Q2 are set up so that the middle part of the line texture is stretched to the length of the line.

Of course, you could also do this with a 1D texture for Q2, but what’s the point in this case?

DO> That might work, though. Not sure if one should really expect
DO> this to give the same result, but considering how most cards do
DO> texture filtering, it should work pretty well.

It does. We did it exactly this way in MindRover. Every line was a
thin quad textured across with a 1D texture that went from transparent
to solid to transparent. It worked great.

I was thinking about what happens with the filtering/antialiasing if you scale the textures down. Do all cards produce the same result as with smaller textures at 1:1 tex/screen scale?

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Fri, 28/06/2002 13:04:11 , Kent Quirk <kent_quirk at cognitoy.com> wrote:

You mean when I draw some kind of info bar on top of OpenGL display - I should
texture it (instead draw with single color), to have good performance?On Fri, Jun 28, 2002 at 10:20:48AM -0400, Kent Quirk wrote:

Be careful! Turning texturing off is often a way to SLOW DOWN consumer
graphics cards. Consumer 3D cards tend to be optimized for one thing:
drawing textured triangles. Falling off this fast path is usually
guaranteed to lose performance.

Hi,

I am new to SDL and tried to create a rotating cube with OpenGL in SDL. OK,
this works, but now I am interested in how can I draw lines and rectangles
over the OpenGL screen. I already tried to use the SDL_FillRect() Function
but it didn’t work. Before I called this function I locked the screen and
after that I unlocked it and called the function SDL_UpdateRect().

the simplest way, i think, which i didn’t see mentioned is to use the
SDL_OPENGLBLIT flag in your SDL_SetVideoMode call. then you can blit over it in the simple SDL way all you want.

BUT, as it says here:

http://sdldoc.csn.ul.ie/sdlsetvideomode.php

it’s not recommended for new code. so i hope i don’t get shot down for this.

billOn Fri, 28 Jun 2002 14:15:08 +0200 “Karsten Hachmeister” wrote: