Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » AllegroGL Tricks...

This thread is locked; no one can reply to it. rss feed Print
 1   2 
AllegroGL Tricks...
Michael Jensen
Member #2,870
October 2002
avatar

So, OpenGL is forcing me to draw farther objects away first, and closer objects last -- silly me, but then why do I have/need a 3D card if I have to do all of this in software anyway? -- am I missing something? maybe there's a mode I can set or something? ~sigh~

{"name":"590862","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/5\/c589fc810fee2c07d338dc0d49672f7c.jpg","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/5\/c589fc810fee2c07d338dc0d49672f7c"}590862
{"name":"590863","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/9\/a92c94d211c7ad2b0c14050ddc82b9ae.gif","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/9\/a92c94d211c7ad2b0c14050ddc82b9ae"}590863

this is my set video mode function that I cannibalized from like three different tutorials:

1 
2int ChangeVideoMode(int width, int height, int bpp, int fullscreen)
3{
4 allegro_gl_clear_settings();
5 allegro_gl_set (AGL_COLOR_DEPTH, bpp);
6 allegro_gl_set (AGL_Z_DEPTH, 24);
7 allegro_gl_set (AGL_FULLSCREEN, fullscreen);
8 allegro_gl_set (AGL_DOUBLEBUFFER, 1);
9
10 int suggest = AGL_COLOR_DEPTH | AGL_Z_DEPTH | AGL_DOUBLEBUFFER;
11 if (fullscreen)
12 { suggest |= AGL_FULLSCREEN; }
13 
14 allegro_gl_set (AGL_SUGGEST, suggest);
15 
16 int driver = GFX_OPENGL_WINDOWED;
17 if (fullscreen){driver = GFX_OPENGL_FULLSCREEN;}
18 
19 int r = set_gfx_mode(driver, width, height, 0, 0);
20 if (r)
21 {
22 allegro_message ("Error setting OpenGL graphics mode:\n%s\n"
23 "Allegro GL error : %s\n",
24 allegro_error, allegro_gl_error);
25 }
26 
27 // Set the OpenGL viewport:
28 glViewport(0, 0, width, height);
29 
30 // We need to set the projection transformation matrix,
31 // so switch to the projection matrix:
32 glMatrixMode(GL_PROJECTION);
33 glLoadIdentity();
34 
35 
36 // Define the projection transformation matrix. Notice
37 // that this is using glFrustum instead of gluPerspective:
38 // In order to use this we need to calculate the min and
39 // max x/y range so as to maintain proper aspect ratio:
40 float fMinX = -1.0f, fMaxX = 1.0f,
41 fMinY = -1.0f, fMaxY = 1.0f;
42 float fAspectRatio = ((float)width) / ((float)height);
43 if ( fAspectRatio > 1.0f )
44 {
45 // The height is greater than the width, so we need to
46 // recalculate the x-range:
47 fMinY = fMinX / fAspectRatio;
48 fMaxY = fMaxX / fAspectRatio;
49 }
50 else
51 {
52 // The width is greater than the height, so we need to
53 // re-calculate the y-range:
54 fMinX = fMinY * fAspectRatio;
55 fMaxX = fMaxY * fAspectRatio;
56 }
57 //glFrustum(fMinX, fMaxX, fMinY, fMaxY, 1, 1000);
58 gluPerspective(48, fAspectRatio, 1, 1000);
59 
60 // Switch back to the modelview matrix:
61 glMatrixMode(GL_MODELVIEW);
62 glLoadIdentity();
63 
64 return r;
65}

Can anyone point me in the right direction?

GullRaDriel
Member #3,861
September 2003
avatar

I think you should do some searching on something called zbuffer.

If I remember correctly, with opengl you can do some sort of 'scenes' of objects, which are automagically sorted by the graphic card.

But beginning by reading some stuff on ZBuffering is a good thing.

I already have done a software zbuffering system, so I can explain you how it works, even if I think that opengl will do this lonesome.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

X-G
Member #856
December 2000
avatar

glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Michael Jensen
Member #2,870
October 2002
avatar

BADASS!

[edit]
I did some googling, and some other people are also adding: glDepthMask(GL_TRUE); -- this obviously isn't needed but what does it do?
[/edit]

GullRaDriel
Member #3,861
September 2003
avatar

Huh ? why ? He gaves you the right answer you know, and with some little more search you will have found it too :p

EDIT: review your google skills ;)

http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/depthmask.html

_

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Michael Jensen
Member #2,870
October 2002
avatar

"badass." == "wow, neat." == "damn cool." -- it's a compliment, er, sort of.

edit:
I had no idea what to search for, or what zbuffering was or anything.

GullRaDriel
Member #3,861
September 2003
avatar

Damn ! Sorry for misunderstooding you .

Your second question have been answered too.

Opengl link given before said:

NAME
glDepthMask - enable or disable writing into the depth
buffer

C SPECIFICATION
void glDepthMask( GLboolean flag )

PARAMETERS
flag Specifies whether the depth buffer is enabled for
writing. If flag is GL_FALSE, depth buffer writing is
disabled. Otherwise, it is enabled. Initially, depth
buffer writing is enabled.

DESCRIPTION
glDepthMask specifies whether the depth buffer is enabled
for writing. If flag is GL_FALSE, depth buffer writing is
disabled. Otherwise, it is enabled. Initially, depth
buffer writing is enabled.

ERRORS
GL_INVALID_OPERATION is generated if glDepthMask is executed
between the execution of glBegin and the corresponding
execution of glEnd.

ASSOCIATED GETS
glGet with argument GL_DEPTH_WRITEMASK

SEE ALSO
glColorMask, glDepthFunc, glDepthRange, glIndexMask,
glStencilMask

_

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Michael Jensen
Member #2,870
October 2002
avatar

thank you much. ;D

Billybob
Member #3,136
January 2003

Zbuffers are fun ... until you deal with translucency.

kikabo
Member #3,679
July 2003
avatar

yeh, because of translucent glitches I added object sorting quite late in a project which was a bit of a pain at a late stage.

If you are going to add transluceny objects it might be worth considering sorting sooner rather than later.

ed: translucent objects including perhaps bill board sprites for explosions, glow effects on anything or shadows.

Jonatan Hedborg
Member #4,886
July 2004
avatar

How is the normal way of solving that again?
1. Draw all solid objects, unsorted but with Zbuffer on (read/write)
2. Sort all non-solids, back to front
3. Draw non-solids with Zbuffer read only

Something like that?

Thomas Harte
Member #33
April 2000
avatar

Quote:

1. Draw all solid objects, unsorted but with Zbuffer on (read/write)
2. Sort all non-solids, back to front
3. Draw non-solids with Zbuffer read only

Something like that?

I'm not sure why you'd want to set the z-buffer to read only, but I normally divide all my objects into a transparent and an opaque part at startup then, per frame:

  • get rough list of objects in the current view cone

  • sort objects roughly by depth

  • for each object from front to back, draw opaque parts

  • for each object from back to front, draw transparent parts

Drawing opaques from front to back is a good idea because graphics cards are very good now at throwing away large chunks of polygon if they're invisible without doing any perpixel work. Especially if you're sorting your objects anyway, you might as well do it this way.

For dealing with transparency within an object I usually either BSP that part of it or ignore the problem and make a note not to use any complicated transparent sections!

Mika Halttunen
Member #760
November 2000
avatar

If you only use additive blending for the transparent stuff (say, particles or explosions etc.) you don't need to sort. :)

---------------------------------------------
.:MHGames | @mhgames_ :.

Jonatan Hedborg
Member #4,886
July 2004
avatar

Quote:

Drawing opaques from front to back is a good idea because graphics cards are very good now at throwing away large chunks of polygon if they're invisible without doing any perpixel work. Especially if you're sorting your objects anyway, you might as well do it this way.

Hmm. I'm not sure if it's overall more effective to just sort the transparent triangles/groups or all of them (but in different order) - Depends on where the bottle-neck is, i suppose (GPU power vs. CPU power).
I think in most cases it's better to just sort the transparent parts.

I think the read-only ZBuffer is because a rough sort may have errors, so rather than not drawing the "faulty" polygons (because they are behind something else), we draw them at the "slightly wrong place" instead (but with faulty blending, probably).

Michael Jensen
Member #2,870
October 2002
avatar

Holy Cow -- I just spent the whole day figuring out how to get some sort of lighting to work, fog was pretty easy though -- but it sounds like there are a LOT of caveats/things that don't "just work" when using OpenGL -- is there a guide somewhere?

This is a bitch.

X-G
Member #856
December 2000
avatar

Eh, there are tutorials, and reference docs. It really isn't that hard OR quirky; most is pretty straightforward if you know what you're doing. What's the problem?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Michael Jensen
Member #2,870
October 2002
avatar

Eh, for the moment:

For a long time I couldn't figure out how to use fonts -- finally I just gave up and used "allegro_gl_set_allegro_mode();" and "allegro_gl_unset_allegro_mode();" and used the allegro routines to draw on the screen, which is a nice feature I guess -- does this hurt the fps at all? I don't notice a difference on my box -- but that's just my box -- also when I save screen to a .bmp file, it comes out upside down, and seems to take forever! :(

I really can't find anything on beginner level on lighting -- other than I'm supposed to pass a "normal" into glNormal3f, (I understand that x, y, and z have to be between 0, and 1, but what does this value indicate -- is it the direction the light is shining from it's source? I'm not quite sure...

found all kinds of strange math that made no sense for lighting :-(

finally got lighting working with

float Shiney[] = { 127.0 };
glMaterialfv(GL_FRONT, GL_DIFFUSE, color);
glMaterialfv(GL_FRONT, GL_SPECULAR, grey);
glMaterialfv(GL_FRONT, GL_SHININESS, Shiney);

where color is the color of my rectangle/triangle.

BUT -- the lighting isn't constant like real world lighting -- it moves around with the camera moving around -- maybe I'm transforming wrong?

:(

-- Really I have no idea what I'm doing and the tutorials seem to all end right after the basics, or they get really heavy into math without explaining the math or giving references to something that does. :-( [/whine]

Jonatan Hedborg
Member #4,886
July 2004
avatar

A normal is the direction that the surface in question is "pointing".
Ie, if your hand is a plane it's normal would "point" out from your palm.
It's used to decide all sorts of important things in 3d lightning.
A polygon of 0,0,0 - 1,0,0 - 0,1,0 would have a normal of 0,0,1.

If the light moves around with the camera you are probably setting it's position at the wrong place. You should set it after you set your camera i think (before drawing polygons).

Thomas Harte
Member #33
April 2000
avatar

Quote:

I really can't find anything on beginner level on lighting -- other than I'm supposed to pass a "normal" into glNormal3f, (I understand that x, y, and z have to be between 0, and 1, but what does this value indicate -- is it the direction the light is shining from it's source? I'm not quite sure...

The normal is a vector pointing at a right angle to the surface it is on. For example, when you're walking along a perfectly flat surface the vector from your feet to your head is the surface normal for the floor. If you throw a dart into a dartboard then usually the vector running along the dart is pretty close to the surface normal for the dartboard.

The complicated maths you've seen probably uses the cross product. The cross product takes two vectors and produces a third that is at a right angle to the first two. If the first two vectors both lie on a particular surface then that means that the vector it produces is at a right angle to the surface — so it is the normal. The code tends to look a bit more confusing than it needs to be because you first have to get two vectors on the surface, which is normally done by just subtracting the position of some vertices from some others.

Also, it isn't that all the components of the normal should be unit length, it's that the entire vector should be unit length. So if you measured the actual vector you'd find out it was length 1. You can ensure that yourself using Pythagoras and sqrt, or let OpenGL do it for you (with glEnable(GL_NORMALIZE)). If there's no way of doing it advance you might as well let OpenGL do it, if you can do it in advance then you should.

Quote:

BUT -- the lighting isn't constant like real world lighting -- it moves around with the camera moving around -- maybe I'm transforming wrong?

You need to set the light position (with glLightfv(GL_LIGHT_POSITION), it doesn't matter if you're only using a directional light and never forget that the vector you pass is four dimensional!) after you've set up the world camera, because it is transformed by MODELVIEW. So your code is probably something like:

  • set up camera to reflect viewer's position

  • set GL_LIGHT_POSITION

  • draw all objects, adjust MODELVIEW here however you like

X-G
Member #856
December 2000
avatar

Harte is correct, and I remember this is something that tends to throw beginners off: GL_LIGHT_POSITION is transformed by the current modelview matrix! Also, it's important to note, if you are using point lights, that the w coordinate must be set to 1. The light "position" is a homogeneous coordinate, with 1 being appropriate for points, and 0 for directions; it's not sufficient to only pass three floats to glLightfv!

If you show us more code, we can help more.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Michael Jensen
Member #2,870
October 2002
avatar

so then I should set the light position every frame... that will probably work. I noticed that it took 4 parameters, and that the fourth one was always a 1 or 0 in examples I saw -- according to X-G I should pass in 1 if it's a point, and 0 if it's a direction for the last parameter?

Which surface should I pass in the normal for? In all of the example programs I've seen, glNormal3f is only called once per loop (usually with constant values) -- but if I have 100 polygons, each with their own normals which normal do I pass in? or do I pass it in for every polygon?

X-G
Member #856
December 2000
avatar

Quote:

or do I pass it in for every polygon?

That.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Michael Jensen
Member #2,870
October 2002
avatar

Ok, well I moved the lighting position to be called once per frame, and the lighting stopped moving around -- badass! ;D

Also, I have this function:

1// Calculate normal from vertices
2Vector CalcNormal(Vector * v1, Vector * v2, Vector * v3)
3{
4 double v1x,v1y,v1z,v2x,v2y,v2z;
5 double nx,ny,nz;
6 double vLen;
7
8 Vector Result;
9
10 // Calculate vectors
11 v1x = v1->x - v2->x;
12 v1y = v1->y - v2->y;
13 v1z = v1->z - v2->z;
14
15 v2x = v2->x - v3->x;
16 v2y = v2->y - v3->y;
17 v2z = v2->z - v3->z;
18
19 // Get cross product of vectors
20 nx = (v1y * v2z) - (v1z * v2y);
21 ny = (v1z * v2x) - (v1x * v2z);
22 nz = (v1x * v2y) - (v1y * v2x);
23
24 // Normalise final vector
25 vLen = sqrt( (nx * nx) + (ny * ny) + (nz * nz) );
26
27 Result.x = (float)(nx / vLen);
28 Result.y = (float)(ny / vLen);
29 Result.z = (float)(nz / vLen);
30
31 return Result;
32}

I have no idea how it works, but it's supposed to return a normal (I stole it from a tutorial) of any polygon I pass in so long as I pass in 3 of it's points in counter clockwise order, so I guess I'll start doing that.... and making a call to glNormal3f for every polygon I render -- I translate/rotate the polygons -- do the points I pass in to glNormal3f get translated/rotated with them?

Only confusing thing is -- I can't seem to find any programs/etc (even the tutorial) that call glNormal3f more than once per draw loop -- if you're supposed to pass it in for every polygon why is everyone cheating!? -- that's what makes it confusing...

Edit: Neat, it's all working -- but I get horribly exagerated results -- the bright areas are too bright and the dark areas are too dark -- I moved the light farther away and to an angle, and now I just have the problem of the dark areas being too dark... it would be nice if they just went to a darker shade of the same color rather than pure grey....

X-G
Member #856
December 2000
avatar

They are probably doing that to make the tutorials simpler for you. Remember that OpenGL is a state machine; if the normals don't change between each vertex fed to the hardware, it'll just keep using the same one. The right thing to do is have one normal per face (actually, one per vertex). (Also, precalculate the normal. Don't do it every frame.)

As for the light, check into ambient settings, reduce your specular component, and possibly add attenuation.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Michael Jensen
Member #2,870
October 2002
avatar

Thank you X-G -- Also, can you recomend a good OpenGL Book? -- It just hit me that I should probably buy a book.

 1   2 


Go to: