Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » silly openGl texture question

This thread is locked; no one can reply to it. rss feed Print
silly openGl texture question
Pavel Hilser
Member #5,788
April 2005
avatar

I have started to make a 2d top view game. Wall, monsters, etc.
Now i created a function, that is casting light and shadows on the level.
My idea is to get all light sources to one texture (using blenging) and to have a "shadowmap" that will be blended onto the level.

My problem - when creating the shadows, i draw them directly to the level - and thats bad, cause i can't do 2 lightsources at once.

So the question - how should I change the drawing code to draw on some "memory-bitmap" as used in allegro and not directly on the video screen ? :(

My code is from the tutorials, nothing special..
(the x1, ... x4 points are simple drawing rectangle shadows)

1glLoadIdentity();//reset matrix
2glBindTexture(GL_TEXTURE_2D, gl_textures[texture]);
3glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4glEnable(GL_BLEND);
5 
6 
7glBegin(GL_QUADS);
8 glColor4ub(r, g, b, alpha);
9 
10 //Draw our four points, clockwise.
11 glTexCoord2f(0, 0);
12 glVertex3f(x1,y1, 0);
13 glTexCoord2f(1, 0);
14 glVertex3f(x2,y2, 0);
15 glTexCoord2f(1, 1);
16 glVertex3f(x3,y3, 0);
17 glTexCoord2f(0, 1);
18 glVertex3f(x4,y4, 0);
19
20glEnd();
21glLoadIdentity();
22}

_____________________________________
Mein Cannon - see my new 2d game

Mr. Big
Member #6,196
September 2005

You need to render your lights and shadows on a texture using FBOs, and call 'glBlendEquationEXT(GL_MAX_EXT)', which would make your lights and shadows accumulate in a realistic way, e.g. red, green and blue lights will mix into white.

But even then, simply blending your shadowmap with the level won't do the job, because then, even the most dark spot won't be completely dark because it'll be a blend of black and whatever is underneath it.

Maybe you can use 'glBlendEquationEXT' with another parameter to fix that (what you need is to multiply the level pixel by the lightmap pixel), I don't remember how it's called, though.
I would suggest you to search the net for 'glBlendEquationEXT'.

[EDIT]

Silly me!
You can blend the lightmap with the rest of the level correctly with multitexturing and TEXTURE_ENV_MODE set to MODULATE.
And by the way, the simplest solution would be to precalculate your lightmaps instead of generating them in real time with all that render-to-texture burden, which isn't supported on old cards.

Oh, and here's an example of how to render stuff on a texture:

1#include <GL/glut.h>
2#include <math.h>
3#include <stdlib.h>
4 
5#define SIZE 256
6 
7static unsigned char texture[3 * SIZE * SIZE];
8static unsigned int texture_id;
9static int window_width = 500;
10static int window_height = 500;
11 
12 
13/*
14** Just a textured cube
15*/
16void Cube (void)
17{
18 glBegin (GL_QUADS);
19 
20 glTexCoord2i (0, 0); glVertex3f (-1, -1, -1);
21 glTexCoord2i (0, 1); glVertex3f (-1, -1, 1);
22 glTexCoord2i (1, 1); glVertex3f (-1, 1, 1);
23 glTexCoord2i (1, 0); glVertex3f (-1, 1, -1);
24 
25 glTexCoord2i (0, 0); glVertex3f ( 1, -1, -1);
26 glTexCoord2i (0, 1); glVertex3f ( 1, -1, 1);
27 glTexCoord2i (1, 1); glVertex3f ( 1, 1, 1);
28 glTexCoord2i (1, 0); glVertex3f ( 1, 1, -1);
29 
30 glTexCoord2i (0, 0); glVertex3f (-1, -1, -1);
31 glTexCoord2i (0, 1); glVertex3f (-1, -1, 1);
32 glTexCoord2i (1, 1); glVertex3f ( 1, -1, 1);
33 glTexCoord2i (1, 0); glVertex3f ( 1, -1, -1);
34 
35 glTexCoord2i (0, 0); glVertex3f (-1, 1, -1);
36 glTexCoord2i (0, 1); glVertex3f (-1, 1, 1);
37 glTexCoord2i (1, 1); glVertex3f ( 1, 1, 1);
38 glTexCoord2i (1, 0); glVertex3f ( 1, 1, -1);
39 
40 glTexCoord2i (0, 0); glVertex3f (-1, -1, -1);
41 glTexCoord2i (0, 1); glVertex3f (-1, 1, -1);
42 glTexCoord2i (1, 1); glVertex3f ( 1, 1, -1);
43 glTexCoord2i (1, 0); glVertex3f ( 1, -1, -1);
44 
45 glTexCoord2i (0, 0); glVertex3f (-1, -1, 1);
46 glTexCoord2i (0, 1); glVertex3f (-1, 1, 1);
47 glTexCoord2i (1, 1); glVertex3f ( 1, 1, 1);
48 glTexCoord2i (1, 0); glVertex3f ( 1, -1, 1);
49 
50 glEnd ();
51}
52 
53/*
54** Function called to update rendering
55*/
56void DisplayFunc (void)
57{
58 static float alpha = 20;
59 
60 glLoadIdentity();
61 glTranslatef (0, 0, -10);
62 glRotatef (30, 1, 0, 0);
63 glRotatef (alpha, 0, 1, 0);
64 
65 /* Define a view-port adapted to the texture */
66 glMatrixMode(GL_PROJECTION);
67 glLoadIdentity ();
68 gluPerspective (20, 1, 5, 15);
69 glViewport(0, 0, SIZE, SIZE);
70 glMatrixMode(GL_MODELVIEW);
71 
72 /* Render to buffer */
73 glClearColor (1, 1, 1, 0);
74 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
75 Cube ();
76 glFlush ();
77 
78 /* Copy buffer to texture */
79 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE - 10, SIZE - 10);
80 
81 /* Render to screen */
82 glMatrixMode(GL_PROJECTION);
83 glLoadIdentity ();
84 gluPerspective (20, window_width / (float) window_height, 5, 15);
85 glViewport(0, 0, window_width, window_height);
86 glMatrixMode(GL_MODELVIEW);
87 glClearColor (0, 0, 0, 0);
88 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
89 Cube ();
90 
91 /* End */
92 glFlush ();
93 glutSwapBuffers ();
94 
95 /* Update again and again */
96 alpha = alpha + 0.1;
97 glutPostRedisplay();
98}
99 
100/*
101** Function called when the window is created or resized
102*/
103void ReshapeFunc (int width, int height)
104{
105 window_width = width;
106 window_height = height;
107 glutPostRedisplay();
108}
109 
110/*
111** Function called when a key is hit
112*/
113void KeyboardFunc (unsigned char key, int x, int y)
114{
115 int foo;
116 
117 foo = x + y; /* Has no effect: just to avoid a warning */
118 if ('q' == key || 'Q' == key || 27 == key)
119 exit (0);
120}
121 
122 
123int main (int argc, char **argv)
124{
125 /* Creation of the window */
126 glutInit (&argc, argv);
127 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
128 glutInitWindowSize (500, 500);
129 glutCreateWindow ("Render to texture");
130 
131 /* OpenGL settings */
132 glEnable (GL_DEPTH_TEST);
133 
134 /* Texture setting */
135 glEnable (GL_TEXTURE_2D);
136 glGenTextures (1, &texture_id);
137 glBindTexture (GL_TEXTURE_2D, texture_id);
138 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB,
139 GL_UNSIGNED_BYTE, texture);
140 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
141 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
142 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
143 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
144 
145 /* Declaration of the callbacks */
146 glutDisplayFunc (&DisplayFunc);
147 glutReshapeFunc (&ReshapeFunc);
148 glutKeyboardFunc (&KeyboardFunc);
149 
150 /* Loop */
151 glutMainLoop ();
152 
153 /* Never reached */
154 return 0;
155}

Hope this helps!

Pavel Hilser
Member #5,788
April 2005
avatar

Ok, don't know if its what you showed - I reprogrammed my program, that it draw the shadows, then copy it to a buffer texture, draw all my stuff and put the shadow texture on the level. Ok so far. All working fine.

BUT

my fps drops from 150 to 50 and when I use multiple sources (5 monsters that are casting shadows), the game is not playable - 4 fps.

My problem is, that I handle a lot of data

-------
- clear the video to zero
- copy video to shadows bitmap (I have an empty shadows)

for(each monster)
- clear video to light
- add shadows
- add previous shadow bitmap
end for

- clear video
- draw level stuff
- draw shadow bitmap
------------
in this way i have what I wanted - any object can cast light and the lights are ok when two monsters are close to each other, etc.

but erasing&copying over and over the shadow bitmap (using blending) is not usable ..

So is there a way to draw directly to a texture ?
Or have I missunderstand your example ?
(I'm really not skilled in open gl to read your code and be able to say what each of the commands are doing)

_____________________________________
Mein Cannon - see my new 2d game

Mr. Big
Member #6,196
September 2005

Sorry it took me so long to reply.
I was on a vacation.
Anyway, I don't really know what is the cause of your problem, but there are three options I can think of:
1. Your shadow method is slow, so it doesn't work well with many light sources and occluders
2. Your card is old, so render-to-texture is very slow
3. You misunderstood the example code and did something wrong

I won't be surprised if it's the third option, 'cause the example code is pretty bad.
I will try to clarify:

First you need to get a valid OpenGL ID for your framebuffer.
Put this where your program starts:

GLuint framebuffer;
glGenFramebuffersEXT(1, &framebuffer);

Then, in the main loop, you render your shadows on the texture:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, your_lightmap, 0);
make_viewport_same_size_as_lightmap();
draw_some_shadows();

Note that in the shadow-drawing function, you need to do everything you would usually do when you draw to the screen. (Clear the color buffer ect.)

Then, you need to switch back to the ordinary screen and draw your scene with the lightmaps.

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
make_viewport_the_way_it_was();
render_scene();

And one last thing, don't be surprised if your FPS is 150 with one lightsource and 50 with two.
FPS drops in a very non-linear way, so you can't really measure how good/bad the code you've added is, (unless your FPS drops to 4... :P)

Fladimir da Gorf
Member #1,565
October 2001
avatar

But beware that especially NVidia doesn't seem to like supporting framebuffer objects...

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Bob
Free Market Evangelist
September 2000
avatar

Quote:

But beware that especially NVidia doesn't seem to like supporting framebuffer objects...

What gave you that impression? FBOs are fully supported on all GeForce FX, GeForce 6 and GeForce 7 series of GPUs.

--
- Bob
[ -- All my signature links are 404 -- ]

Mr. Big
Member #6,196
September 2005

I have a GeForce 5700 LE and they don't do me any trouble.

Pavel Hilser
Member #5,788
April 2005
avatar

Mr.Big: thanx for the explanation - I really missunderstood your code :D
I'll try it the way you wrote, hope this will help (and my large-texture-moving will not be necessary anymore;)

(BTW I have 5700 too ;)

_____________________________________
Mein Cannon - see my new 2d game

Fladimir da Gorf
Member #1,565
October 2001
avatar

Quote:

What gave you that impression? FBOs are fully supported on all GeForce FX, GeForce 6 and GeForce 7 series of GPUs.

I read it from an another thread here. Buf if they are, that's great!

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Go to: