Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: 2D light effect with alpha mask: problem with background.

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    4

    2D light effect with alpha mask: problem with background.

    Hello to everyone,
    [sorry for my english. It's a disaster]
    I'm trying to generate a 2D light area with the precious help of our friend "alpha mask". Now, the process is very simple but I'm an opengl's newbie and I hope that someone of you can just direct me to the right way/technique.
    I've a certain amount of 2D textures (my sprites) witch composing my map: background, items, boxes etc etc. Once I've painted the map I use a large big black texture painted over the map as the foreground: this generate darkness.

    Now, before painting the "darkness" image, I paint a "light texture" (a white image, completely visible from external to completely invisible to the center) using the following declaration:
    Code :
    glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ZERO);
    The darkness image instead is preceded by the following declaration:
    Code :
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
    The natural consequence of this is this image:

    As you can see the cone of light effect is good (I need to adjust the transparency of my "light" texture, but it's ok) but the alpha channel of others semi-transparent elements from map are involved in the equation generated by the function:
    Code :
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
    This is a big problem! The render code is this:
    Code :
    	{}
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            foreach(singleton, &cengine::environment) {
    	    /* every graphical element is formed by one or more textures */
                while ((texture = singleton->get()) != EE_NULLTEXTURE) { 
                    glLoadIdentity();
                    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
                    glPushMatrix();
                    glTranslatef(...);
                    if (singleton->flipped[EFLIPDIRECTION_VERTICAL])
                        glRotatef(180.0, 1.0, 0.0, 0.0);
                    if (singleton->flipped[EFLIPDIRECTION_HORIZONTAL])
                        glRotatef(180.0, 0.0, 1.0, 0.0);
                    glRotatef(fmod(singleton->rotation, 360), 0.0, 0.0, 1.0);
                    glBegin(GL_QUADS);
                    {
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);			
                        glVertex3f(...);
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);	
                        glVertex3f(...);
                    }
                    glEnd();
                    glPopMatrix();
                }
            }
            glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ZERO);
            singleton = light;
    	/* LIGHT CONE (just a test) */
            while ((texture = singleton->get()) != EE_NULLTEXTURE) {
                 	glLoadIdentity();
                    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
                    glPushMatrix();
                    glTranslatef(...);
                    if (singleton->flipped[EFLIPDIRECTION_VERTICAL])
                        glRotatef(180.0, 1.0, 0.0, 0.0);
                    if (singleton->flipped[EFLIPDIRECTION_HORIZONTAL])
                        glRotatef(180.0, 0.0, 1.0, 0.0);
                    glRotatef(fmod(singleton->rotation, 360), 0.0, 0.0, 1.0);
                    glBegin(GL_QUADS);
                    {
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);			
                        glVertex3f(...);
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);	
                        glVertex3f(...);
                    }
                    glEnd();
                    glPopMatrix();
            }
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
            singleton = imgbackground;
    	/* FOREGROUND DARKNESS (just a test) */
            while ((texture = singleton->get()) != EE_NULLTEXTURE) {
                	glLoadIdentity();
                    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture);
                    glPushMatrix();
                    glTranslatef(...);
                    if (singleton->flipped[EFLIPDIRECTION_VERTICAL])
                        glRotatef(180.0, 1.0, 0.0, 0.0);
                    if (singleton->flipped[EFLIPDIRECTION_HORIZONTAL])
                        glRotatef(180.0, 0.0, 1.0, 0.0);
                    glRotatef(fmod(singleton->rotation, 360), 0.0, 0.0, 1.0);
                    glBegin(GL_QUADS);
                    {
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);			
                        glVertex3f(...);
                        glTexCoord2i(...);
                        glVertex3f(...);
                        glTexCoord2i(...);	
                        glVertex3f(...);
                    }
                    glEnd();
                    glPopMatrix();
            }
            glDisable(GL_BLEND);
            glutSwapBuffers();
            glFlush();
    	{}
    So, my question is: there is a technique to, for instance, applying a mask (or masks, in this case the cone of light) to a single texture (in this case to the foreground) in a fast way?
    Thanks in advice guys, really.
    [/sorry for my english. It's a disaster]

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    Do you know how to use stencils?

    With a stencil buffer you could do the following

    1) render you map

    2) enable drawing to the stencil buffer only

    3) render your light cone to the stencil buffer

    3) with the stencil buffer testing enabled, render a full screen rect in black (with what ever alpha)

    The stencil will stop any black being draw where the cone value exists.

  3. #3
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    4
    Thank you so much!

  4. #4
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    4
    Mh, just another simply question (so that I know I'm on the right path). Did stencils support the "fade out" effect or just visible/invisible pixel? I mean, with stencils can I generate the same effect of the image before (the cone of light)?
    Thanks for help!

  5. #5
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    I think it either suceeds or fails. You would need to have a dither pattern to give the illusion of fading on the edges. The alternate I thought of is to render the light cone to a texture buffer and then use a shader to check this texture when rendering the black layer. This would in effect give you a alpha mask - hope that makes sense

  6. #6
    Super Moderator OpenGL Lord
    Join Date
    Dec 2003
    Location
    Grenoble - France
    Posts
    5,575
    I am not sure I understand your exact problem, but staying with blending, I propose :

    - edit the darkness texture with the light texture using additive blending :

    glBlendFunc(GL_ONE, GL_ZERO);

    - now in this mask black means black and white mean same color
    - then apply the resulting mask to the color texture, using multiplicative blending :

    glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);

  7. #7
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    4
    @tonyo_au: Thank you for your reply! Applying a pattern to the stencil is a good choice if I've a single cone of light, thanks! Unfortunately I've two or more cone of lights that, eventually, intersecate each others (and in this case the result is not what I'm looking for). Shader is a way, thanks again! I will look around for more informations.

    @ZbuffeR: Thank you for your reply! Yeah, that's what I'm looking for: applying one/two/more masks (cone of light) to a single texture (black one). How can I mask _only_ that texture (black) with cone of light (one or more) using glBlendFunc saving the result in a "output" texture and then blending the output texture over the map? Thanks!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •