4
\$\begingroup\$

I'm looking into doing a 2d lighting system with a result similar to this: http://forums.tigsource.com/index.php?topic=15619.0 This thread I believe disregards color, as well as doesn't really list a clear final solution, which is something we could provide here.

What I'd like to do is start with a solid black texture, and render colored lights to it. When I render a colored light onto the texture, I'd like it to subtract the alpha away from the solid black texture but also add in the color of the light. In the end, my goal would be to have a texture that I can blend normally on top of my scene, using glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), which would let the background show through in the "lighted" areas in addition to adding some of that lights color to the area.

To start I fill the texture with black:

glColor4f( 0.0f, 0.0f, 0.0f, 1.0 )

Then I set the blend function to subtract and draw the lights:

glBlendEquation( GL_FUNC_SUBTRACT );
glBlendFunc( ??? , ??? ); // Not quite sure what to put here

// Draw a triangle fan for the circle of light.
glColor4f( 0.0f, 0.0f, 0.0f, 0.8f );
glBegin(GL_TRIANGLE_FAN);
glVertex2f(0, 0);
glColor4f( 0.0f, 0.0f, 0.0f, 0.0f );
for (float angle = 0; angle <= 6.28; angle+=0.1) {
    glVertex2f(sin(angle) * sizeOfLight, cos(angle) * sizeOfLight);
}
glVertex2f(sin(3.14159*2) * sizeOfLight, cos(3.14159*2) * sizeOfLight);
glEnd();

// Reset this back to normal
glBlendEquation(GL_FUNC_ADD);

The guts of my question is what type of blending would I need here, on the second line of this code block.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

What it sounds like you want to do is additively blend your lights together, and then multiply the results on top of your scene.

\$\endgroup\$
0
\$\begingroup\$

If I were you, I'd render two scenes: a light-only scene and an everything-else scene. First, clear the Z buffer to zNear and render the light-only scene with zCompare turned off and Z set to zFar. This will make it so unlit pixels = zNear and lit pixels = zFar.

To draw the lights, the simple way is to bound each light by a rectangle on screen and render a quad with a texture of a radial gradient and additive blend.

If you intend to have a very large amount of lights, eventually you will have to do it the fast way: divide the screen into tiles and for each tile, set pixel shader constants to say where each light in the tile is and what color it is, and in the pixel shader for each tile, render all the lights into pixel shader registers before finally returning only the total light with no additive blend.

Anyway, after you've rendered all the lights, copy off the light color buffer somewhere else as a texture, and start to render the main scene.

Since all unlit pixels were set to zNear in the light pass, you won't waste any GPU time rendering unlit pixels in the main scene, woot!

If the main scene is rendered with deferred rendering, then use the light texture you made in the beginning in a deferred lighting pass. If the main scene is forward-rendered, then in the pixel shader of each object in the main scene, read in the light texture and multiply the pixel's albedo by it before writing it out.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .