• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
medevilenemy

2D lighting

14 posts in this topic

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.
0

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
What i'm going for is something sort of like [url="http://www.youtube.com/watch?v=W53rTHXM6yo"]http://www.youtube.com/watch?v=W53rTHXM6yo[/url] 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
0

Share this post


Link to post
Share on other sites
[quote name='medevilenemy' timestamp='1335726619' post='4935870']
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.
[/quote]

In practical terms:[list]
[*]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.
[/list]
2

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
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).
1

Share this post


Link to post
Share on other sites
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 [s]walrus[/s] 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.
0

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
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.
1

Share this post


Link to post
Share on other sites
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?
0

Share this post


Link to post
Share on other sites
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
0

Share this post


Link to post
Share on other sites
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).
0

Share this post


Link to post
Share on other sites
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 [url="http://www.songho.ca/opengl/gl_fbo.html."]http://www.songho.ca...gl/gl_fbo.html.[/url] My setup code is pretty much exactly the same, with the drawing code replaced with the following (for testing purposes):

[code]
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);
[/code]

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
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0