Saturday 13 November 2010

Coding, Coding, Coding...

Yay! Coding!

I've been getting back into coding this week, after a bit of a hiatus. I've thrown myself into a new project, a kind of spiritual successor to kreis, and so far its going well.

I've got some lighting sorted out, which so far is much prettier looking, and more realistic than what kreis had.
Basically, this time, instead of assuming everything is "lit" from the off, then drawing in shadows to darken bits, I'm simply drawing a black (unlit) texture over everything and "cutting out" bits of it which are lit.
The process is slightly more complicated than that however, and goes a bit like this:

1) Render the white light to a texture:
This is relatively simple, you simply get a gradiated circle, with 100% alpha at the centre, and 0% at the edges:
void draw_light(float x, float y, float rad, float intensity)
{
float nx,ny;
glBegin(GL_TRIANGLE_FAN);
glColor4f(1,1,1,intensity);
glVertex2f(x,y);
glColor4f(1,1,1,0);
for (float ang = (2*pi)+(pi/24);ang>=0;ang-=pi/24)
{
nx = (rad*sin(ang))+x;
ny = (rad*cos(ang))+y;
glVertex2f(nx,ny);
}
glEnd();
}

2) Composite the lights onto one render texture.
Again, this is pretty simple. You simply draw the light texture of each of the lights in turn onto one master texture:
void predraw_light(GLuint tex, int x_l, int y_t, int x_r, int y_b)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glColor4f(1,1,1,1);
glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0); glVertex2d(x_l,y_t);
glTexCoord2d(1.0,0.0); glVertex2d(x_r,y_t);
glTexCoord2d(1.0,1.0); glVertex2d(x_r,y_b);
glTexCoord2d(0.0,1.0); glVertex2d(x_l,y_b);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
Where "tex" is the lights texture, and "x_l, x_r, y_t, y_b" are the right, left, top and bottom positions of the texture.

3) Render the master texture onto the scene, inverting the alpha values.
This is when it starts to get trickier. We need to render all the lights to the scene, but at the moment, we just have a collection of white blobs on a transparent black texture. What we do is draw the texture, whilst REVERSING the alpha. This means that the alpha of every pixel becomes 1-its alpha. So, during reversing, all the transparent black becomes opaque (unlit) and our lights become transparent, and therefore lit.
void draw_light_tex(GLuint tex, int x_l, int y_t, int x_r, int y_b)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glColor4f(1,1,1,1);
glBlendFunc( GL_SRC_ALPHA, GL_SRC_ALPHA );
glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0); glVertex2d(x_l,y_t);
glTexCoord2d(1.0,0.0); glVertex2d(x_r,y_t);
glTexCoord2d(1.0,1.0); glVertex2d(x_r,y_b);
glTexCoord2d(0.0,1.0); glVertex2d(x_l,y_b);
glEnd();
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
Tex, x_l, x_r... all stand for the same things. Note the opengl blend functions:
glBlendFunc( GL_SRC_ALPHA, GL_SRC_ALPHA );
...
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
The first is the magic of this system. It reverses how the alpha is normally drawn (ie, the second function) and thus allows all our lights to work nicely.

Once you combine this with some nice physics (another thing I've been working on, getting Box2d integrated) you get lovely effects like this:

This is still VERY much wip, and I'm planning to tidy up the code a bit this weekend and package up some of the lighting stuff into its own class.

After that, I've got a couple of major targets which I want to meet:
1) Get shadows working.
So far, I've got some nice lights going, and darkness where there isn't light. However, what I dont have is objects casting shadows. I've done most of the legwork for this before (with kreis) so this time I just need to get it sitting nicely with the texture based lights.

2) Get some actor classes working.
I'll need an actor class eventually, so I may as well get one going now to tie together Box2d bodies, and the lights.

Apart from that, things are going pretty well! Box2d was a bit of an effort to get going, but only because of working out which projects to compile, and integrating it nicely.

Also, if anybody wants the full code, or the code for the texture generation and drawing, just email me at the address given on my website (harries {dot} adam {at} googlemail {dot} com), and I'll get back to you asap with it...

No comments:

Post a Comment