Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


2D lighting


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
14 replies to this topic

#1 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 28 April 2012 - 12:34 AM

Hi all, so, I've been looking into how to implement better looking lighting in my 2D engine and from what I can tell the most relevant way seems to be to draw a low alpha light textured quad over (well, at the same z position, really) a high alpha blanket (or is it the reverse, this is rather confusing) with the appropriate blending. To test this, I've been playing with drawing the following quads on my screen in various alphas, orders, and with various blending configurations:

glColor4d(1.0, 1.0, 1.0, 0.01);
glBegin(GL_QUADS);
glVertex3d(-1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, -1.0, 0.0);
glVertex3d(-1.0, -1.0, 0.0);
glEnd();

glColor4d(1.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(-0.9, 0.0, 0.0);
glVertex3d(0.1, 0.0, 0.0);
glVertex3d(0.1, -1.0, 0.0);
glVertex3d(-0.9, -1.0, 0.0);
glEnd();

I currently have the following at least somewhat relevant config stuff:
glEnable(GL_BLEND); // allows blending (transparency)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); // allows smooth shading (gradients)
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0);

I can't seem to find the right configuration for what I'm trying to do. I'm drawing my stage at a z level farther (higher z in my case) and drawing these masks over it. I want to eventually draw a black mask over everything and draw lights to cancel out bits of that mask to light appropriate areas (with an appropriate gradient texture). What am I doing wrong? This has been done innumerable times, but I can't seem to wrap my head around the examples I've seen.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

Sponsor:

#2 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 29 April 2012 - 01:10 PM

Pretty sure the problem is ultimately that I don't understand what the different blend func configurations do in practical terms, or even if there is one for what I'm trying to accomplish... I'm sure there's a way, I've seen it done.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#3 irreversible   Crossbones+   -  Reputation: 1380

Like
0Likes
Like

Posted 29 April 2012 - 03:11 PM

It's kind of hard to understand what you're trying to accomplish. If you want more control, simply write your own shader and do precisely what you need.

#4 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 29 April 2012 - 03:37 PM

What i'm going for is something sort of like but without the shadows. Basically, I want the stage to be dark, and by placing a light on it I could illuminate a circular area with an appropriate gradient, thereby making things in the illuminated area visible (or more visible). These lights could, hypothetically, be moved. I suppose this can sort of be described as having an opaque blanket over the stage, through which gradient holes are punched in certain places to reveal the things beneath.

I don't know the first thing about shaders... everything I do is in the fixed pipeline (horribly outdated, I know). (sidenote: If anyone knows of a way to update the opengl libraries available to mingw, that would be awesome. I know microsoft doesn't provide drivers for newer versions of opengl with windows, but the card manufacturers do, so I'd figure the libraries would be available... alternatively I suppose something like glew would give access to newer features, but I can't seem to get glew to work with mingw/Code::Blocks)

Edited by medevilenemy, 29 April 2012 - 03:39 PM.

There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#5 Digitalfragment   Members   -  Reputation: 869

Like
2Likes
Like

Posted 29 April 2012 - 06:48 PM

Pretty sure the problem is ultimately that I don't understand what the different blend func configurations do in practical terms, or even if there is one for what I'm trying to accomplish... I'm sure there's a way, I've seen it done.


In practical terms:
  • At time of blending you have 2 colours, destination and source. Destination being what is already drawn to that pixel, and Source being the colour you are currently drawing. (in some circumstances you can also have an additional constant-colour, but I'm not sure if that exists in OpenGL)
  • There are multiple blending equations (glBlendEquation). The default is Add, which is SrcResult + DstResult, there is also Subtract, Multiply, Min and Max.
  • SrcResult and DstResult come from using the functions specified in glBlendFunc to operate on Source and Destination.
  • GL_ZERO: 0 * value // i.e. use zero
  • GL_ONE: 1 * value // i.e. use value directly
  • GL_SRC_ALPHA: Source.a * value // i.e. multiply the colour by the alpha of source (regardless of if value is Destination or Source)
  • GL_DST_ALPHA: Destination.a * value // i.e. multiply the colour by the alpha of destination (regardless of if value is Destination or Source)
  • GL_ONE_MINUS_SRC_ALPHA: (1.0f - Source.a) * value; // the inverse of GL_SRC_ALPHA, mutiply by the remainding fraction of sources' alpha
  • GL_ONE_MINUS_DST_ALPHA: (1.0f - Destination.a) * value; // same as above, except using the remainder of destinations' alpha.

    Using the default blending example of Add, with SrcAlpha, InvSrcAlpha, what you have is a linear-interpolation from the destiation to the source by sources alpha:

    ResultingPixel = (Source.a * Source.rgba) + ((1 - Source.a) * Destination.rgba

    Note that through extensions or OpenGL2+ you can also seperate the alpha channel to use a seperate equation.


#6 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 29 April 2012 - 07:14 PM

Thanks, that does help clarify some stuf, though I'm still not really sure what the proper equation for my purpose is... I don't really care abou the color, its mostly that I want the equivalent of subtracting the alpha of the source (if I understand the terminology properly) form the alpha of the destination to get the final alpha. Additional potential complication: This could very well mess up how the sprites and whatnot underneath blend... At the moment they look just fine with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), but clearly that isn't the right setting for what I'm trying to do here... I don't suppose there's a way to set different blending funcs for different z depths.

At this point I suppose there are two things I need to know/figure out:
1) How to achieve the desired effect
2) How to prevent (1) from interfering with the underlying scene.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#7 Digitalfragment   Members   -  Reputation: 869

Like
1Likes
Like

Posted 29 April 2012 - 07:21 PM

As far as 2) is concerned, it comes down to order of draw calls. You can freely change blend functions and equations in between draw calls, just like anything else on the video card.
So if you draw your background, then your lighting filters, then your sprites you should be fine (Noting that your sprites blending requirements are source, not destination, so whatever has already been put into alpha is irrelevant).

#8 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 29 April 2012 - 07:46 PM

Hmm. In my object system, lights are technically classified as scenery objects, thus I can't strictly order them to the back. What I may do is split them out into a separate category (logically to be called walrus lights), which I can then put at the end of my update stage. This way I can combine the overlay "blanket" and hole punches into one big step. Thanks for the idea!

Now all that remains is (1) as described above.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#9 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 01 May 2012 - 10:16 PM

Any suggestions? Help is greatly appreciated.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#10 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 02 May 2012 - 11:48 PM

Been experimenting some more, without any luck. It seems no matter what I do, I just end up with a white box on the screen.

I'm now isolating the experimental code by drawing it last, with glpush/pop matrix, and drawing the following:

glColor4d(1.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(-1.0, 0.0, 0.01);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, -1.0, 0.0);
glVertex3d(-1.0, -1.0, 0.0);
glEnd();

glColor4d(1.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glVertex3d(-1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, -1.0, 0.0);
glVertex3d(-1.0, -1.0, 0.0);
glEnd();

What I want to do is have the 2nd quad nullify the first quad (by subtracting the alpha) to reveal the stuff drawn earlier underneath. If I understand correctly, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA should do the trick but no variant I've tried has made a difference.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#11 Digitalfragment   Members   -  Reputation: 869

Like
1Likes
Like

Posted 03 May 2012 - 01:52 AM

I think you're missing the fact that subtracting the alpha after its already been drawn will not reveal what was below that pixel. Once you have drawn to a pixel, whatever was there before hand is gone - a texture only stores 1 colour per pixel. To get more information per pixel you have to manually store it in other render targets.

#12 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 03 May 2012 - 05:07 PM

That... is a really good point that didn't occur to me <smacks forhead>. So, I suppose now the question becomes: How do I do that?
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#13 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 05 May 2012 - 02:10 PM

I found an example which, with some tweaking (since i'm not using shaders and since I need to load up an appropropriate extension -- I suppose GL_ARB_framebuffer_object) should do the trick (render the opaque "blanket" to a texture, then the light template onto that -- assuming it would let me draw a texture onto the texture -- then draw the framebuffer texture over my scene). I am attempting to build with GLEW in order to make GL_ARB_framebuffer_object accessable, but unfortunately I get the following error when I try to test for the extension's availability:

undefined reference to `__GLEW_ARB_framebuffer_object'

The relevant code is:

GLenum err = glewInit();
if (GLEW_OK != err)
{
}
else // This is not permanent... just a way for me to test to see if glew is working.
{
if (GLEW_ARB_framebuffer_object)
{
}
}

I have added glew32.lib to the linker options for my project -- but I suppose it isn't playing nice with the linker. I am using the newest version of glew and building in Code::Blocks 10.05 with a mingw backend.

Edited by medevilenemy, 05 May 2012 - 02:11 PM.

There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#14 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 05 May 2012 - 03:40 PM

Purely on a hunch, I tried linking against glew32.dll rather than glew32.lib, and it seems to link now... and it seems the extension I want is available! (I already knew it was, but its nice to see that glew agrees).
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.

#15 medevilenemy   Members   -  Reputation: 315

Like
0Likes
Like

Posted 09 May 2012 - 07:40 PM

I've made some progress... I can now render to a texture, which I can then draw to the screen... but I can't seem to get blending and/or depth (can't really tell which) to work within that texture. I'm basing my code on the bottom example in http://www.songho.ca...gl/gl_fbo.html. My setup code is pretty much exactly the same, with the drawing code replaced with the following (for testing purposes):

glPushMatrix();
// set rendering destination to FBO
glBindFramebuffer(GL_FRAMEBUFFER, 92);

// clear buffers
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glOrtho(-0.5 * width, 0.5*width, -1, 1, 1, 0);
glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // function for blending
glColor4d(0.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
	glVertex3d(-1.0, 0.0, 0.01);
	glVertex3d(0.1, 0.0, 0.01);
	glVertex3d(0.1, -1.0, 0.01);
	glVertex3d(-1.0, -1.0, 0.01);
glEnd();

glColor4d(1.0, 1.0, 1.0, 1.0);
glBegin(GL_QUADS);
	glVertex3d(-0.9, 0.0, 0.0);
	glVertex3d(0.0, 0.0, 0.0);
	glVertex3d(0.0, -0.9, 0.0);
	glVertex3d(-0.9, -0.9, 0.02);
glEnd();

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopMatrix();

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 90);
glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.1,-0.1,0.01); // Bottom-Left Vertex
	glTexCoord2f(1.0f, 0.0f); glVertex3f(0.1,-0.1,0.01); // Bottom-Right Vertex
	glTexCoord2f(1.0f, 1.0f); glVertex3f(0.1,0.1,0.01); // Top-Right Vertex
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.1,0.1,0.01); // Top-Left Vertex
glEnd();
glDisable(GL_TEXTURE_2D);

In fact.. Nothing I do seems to make any difference (even making the first quad bigger and a different color than the first and playing with texcoords, it always just shows the second box.

Does anyone know what I might need to change in the setup or in the drawing code to get the depth/alpha blending working?

Edited by medevilenemy, 09 May 2012 - 11:00 PM.

There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS