Jump to content
  • Advertisement
Sign in to follow this  
Nethanek

GLSL 2D lighting artifacts

This topic is 2078 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello!

 

I have some problems with adding light features to my 2D game. It's working well until i add more than 1 light source. That's where artifacts appears. To achieve that effect im rendering lightmap into the texture and here i've got a problem with artifacts. I've tried to use glDisable(GL_DEPTH_TEST) before drawing lights into the texture, but it still doesn't work. Anyone has any idea what am I doing wrong?

Here are some pics:

 

Depth test enabled

 

2dse5qd.png

 

Depth test disabled

 

255l7k6.png

 

Vertex shader for lightmap:

#version 330 core
layout (location = 0) in vec3 v_pos;
out vec4 vout_pos;

layout (location = 2) in vec2 texcoord;
uniform vec2 cameraOffset;
out vec2 vout_texcoord;

void main()
{
    float pix = 1.0/128.0;
    vec4 scale = vec4(pix, pix, 1.0, 1.0);
	vec4 offset = vec4( v_pos.x-cameraOffset.x,
                        v_pos.y-cameraOffset.y,
                        v_pos.z, 1.0);

    /** WSPOLRZEDNE SWIATLA */
    gl_Position = offset*scale ;
    /** KOORDYNATY TEKSTURY SWIATLA */
    vout_texcoord = texcoord ;
}

Fragment shader for lightmap:

#version 330 core

in vec2 vout_texcoord;
uniform vec3 lightColor;

out vec4 color;

uniform sampler2D texture;

uniform sampler2D lightmap;

void main()
{

    vec4 col = texture2D(texture, vout_texcoord.st);
    col.rgb *= lightColor.rgb;

    vec4 l = texture2D(lightmap, (gl_FragCoord.xy/640.0));

    float x = vout_texcoord.s - 0.5f;
    float y = vout_texcoord.t - 0.5f;
    float r = sqrt((x*x) + (y*y));
    if(r > 0.5f)
    {
        col.rgb = col.rgb; // - vec3(0.3, 0.3, 0.3);
        col.a = 1.0-r;
        clamp(col.rgb, 0.0, 0.0);
    }
    vec4 val = col+l;
    color = clamp(val, 0.0, 1.0);
}

Also here's code for framebuffer initialization:

glGenFramebuffers(1, &(lbuff.buff));
    printf("Light buff: %d.\n", (lbuff.buff));
    glBindFramebuffer(GL_FRAMEBUFFER, (lbuff.buff));
    glClearColor(1.f, 1.f, 0.f, 1.f);

    glBindTexture(GL_TEXTURE_2D, lbuff.buffColorTex);
    glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 640, 640);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, lbuff.buffDepthTex);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 640, 640);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, lbuff.buffColorTex, 0);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, lbuff.buffDepthTex, 0);

    glDrawBuffers(1, lbuff.flag);

And code called directly before rendering lights:

lBindFramebuffer(GL_FRAMEBUFFER, lbuff.buff);
    glUseProgramObjectARB(lbuff.program);

    glClearBufferfv(GL_COLOR, 0, c);
    glClearBufferfv(GL_DEPTH, 0, &d);

    lbuff.addrLightTexCoord     = glGetAttribLocationARB(lbuff.program, "texcoord");
    // SPOT LIGHT TEXTURE
    lbuff.addrLightTex          = glGetUniformLocationARB(lbuff.program, "texture");
    // LIGHTMAP
    lbuff.addrLightmap          = glGetUniformLocationARB(lbuff.program, "lightmap");
    lbuff.addrLightColor        = glGetUniformLocationARB(lbuff.program, "lightColor");

        // LIGHTMAP
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, lbuff.buffColorTex);
    glUniform1i(lbuff.addrLightmap, 1);

        // SPOTLIGHT TEXTURE
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, lbuff.lightTex);
    glUniform1i(lbuff.addrLightTex, 0);

Any ideas what am i doing wrong?

Share this post


Link to post
Share on other sites
Advertisement

First, what's the point in even having a depth buffer for lighting?

 

Second, you don't show code related to populating lbuff.buffColorTex

 

I have a feeling it's something related to that. And quite possibly specifically a mismatch between the specified storage GL_RGBA8 and what you're actually filling it with.

Share this post


Link to post
Share on other sites

also your shader seems a bit funky. for example how you both calculate radius (assuming that's what `r` is) and how you use it.

 

Radius is simply a constant. Related to diameter. But your calculation almost looks like an attempt at what you would use for a distance calculation. But instead of the difference between y2-y1/x2-x1 you just use single x and y values?

 

Not sure what's up

Share this post


Link to post
Share on other sites

First of all, thank you for reply smile.png

 

 

 


also your shader seems a bit funky. for example how you both calculate radius (assuming that's what `r` is) and how you use it.



Radius is simply a constant. Related to diameter. But your calculation almost looks like an attempt at what you would use for a distance calculation. But instead of the difference between y2-y1/x2-x1 you just use single x and y values?

It's because i was checking if the problem concerns 2 methods of drawing lights to framebuffer:

1) First method use texture as below

light.png

 

2) Second method calculated radius, and drawn shades if r was greater than certain value.

 

Cause first method resulted in quare-shade at the borders of light area, i've decided to mix both methods. Texture gave me smooth lighting, and radius removed quare-shape of the shadow.  Example is in the image below. Though, they are barely visible, I decided to get rid of them smile.png

 

1zzg9c8.png

 

Removing this part of code doesn't solve the problem anyway :/
 

 


First, what's the point in even having a depth buffer for lighting?

 

Oh, u see, im quite beginner both in openGL and GLSL. Just read some tutorials, found rendering to texture could simplify creating lights in 2D scene, and used that technique for that purpose smile.png In tutorials there was a depth attachment, so here it is also in my code smile.png (thought seems like im not using it anyway).

 

EDIT: Removing depth attachment results in this:

 

1in3nm.png

 

 


Second, you don't show code related to populating lbuff.buffColorTex

 

lbuff is structure of type lightBuff.

typedef struct _lightBuff lightBuff;
struct _lightBuff
{
    // FRAMEBUFFER HANDLE
GLenum buff;
// COLOR_ATTACHMENT TEXTURE HANDLE
GLenum buffColorTex;
// DEPTH ATTACHMENT TEXTURE HANDLE
GLenum buffDepthTex;
// SPOT LIGHT TEXTURE HANDLE
GLenum lightTex;
// CONTAINS GL_COLOR_ATTACHMENT0
GLenum flag[1];

    // UNIFORMS AND ATTRIBUTES
GLint addrLightmap;
GLint addrLightTex;
GLint addrLightTexCoord;
GLint addrLightColor;

    // SHADER PROGRAM FOR LIGHTS
GLint program;
};
lightBuff lbuff;

It contains all data i need for using framebuffer. Here is a full init of framebuffer:

int lightInit()
{
    int result;
    lbuff.buffColorTex = TEX_FB_COLOR;
    lbuff.buffDepthTex = TEX_FB_DEPTH;
    lbuff.lightTex = TEX_LG_DOT;
    lbuff.program = myPrograms[1].program;
    lbuff.flag[0] = GL_COLOR_ATTACHMENT0;
    printf("Light program: %d.\n", lbuff.program);

    glGenFramebuffers(1, &(lbuff.buff));
    printf("Light buff: %d.\n", (lbuff.buff));
    glBindFramebuffer(GL_FRAMEBUFFER, (lbuff.buff));
    glClearColor(1.f, 1.f, 0.f, 1.f);

    glBindTexture(GL_TEXTURE_2D, lbuff.buffColorTex);
    glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 640, 640);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    glBindTexture(GL_TEXTURE_2D, lbuff.buffDepthTex);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, 640, 640);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, lbuff.buffColorTex, 0);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, lbuff.buffDepthTex, 0);

    glDrawBuffers(1, lbuff.flag);

    return 0;
}


I have a feeling it's something related to that. And quite possibly specifically a mismatch between the specified storage GL_RGBA8 and what you're actually filling it with.

 

What do you mean exactly? How could I did that?

 

 

Hope all information I provided here will help finding the source of the problem ;s

Edited by Nethanek

Share this post


Link to post
Share on other sites

Well your original attempt was close to being perfect

 

http://oi61.tinypic.com/1zzg9c8.jpg

 

You attempted to fix it and broke it :p

 

I'd say use the original method but think of a proper fix...

 

The contrast in colour probably comes from the fact that the darkest value in your light.png (black) doesn't match your ambient map colour, for some reason.

 

Technically, `l` should be getting a value of zero and so nothing is added to the final colour so it should be the base texture colour, but for some reason it's lighter.

 

You can either dive deeper into that yourself and figure out exactly what's wrong, or you can do a slight "hack" workaround, just subtract a small value fram `l` incrementally until you find the right value.

 

like l -= .02;

or

l -= .04;

 

Until the borders match.

Share this post


Link to post
Share on other sites

Well, not exactly. Even if i dont do so, or just don't use spotlight texture (if r <= 0.5 draw light else draw shadow) I still have that problem. One told me on other forum to disable depth testing before rendering light, but it also doesn't help. Problem always appears when 2 light sources are close to each other. But there is no problem if I don't try merge colors of light sources (but it's just ugly). I feel so helpless about that :/

Share this post


Link to post
Share on other sites
    if(r > 0.5f)
    {
        col.rgb = col.rgb; // - vec3(0.3, 0.3, 0.3);
        col.a = 1.0-r;
        clamp(col.rgb, 0.0, 0.0);
    }

Really?

Share this post


Link to post
Share on other sites
void main()
{
    vec4 col = texture2D(texture, vout_texcoord.st);
    col.rgb *= lightColor.rgb;

    vec4 l = texture2D(lightmap, gl_FragCoord.xy/640.0);
    vec4 val = col+l;
    color = clamp(val, 0.0, 1.0) ;
}

With such a fragment shader code problem is same so... it doesn't really matter :D

 

Now if I think about it after reading some books... could that be a cause of artifacts if I used direct mode (glVertex3f) instead of packing data into GL_ARRAY_BUFFERs? Or could wrong initialization of SDL cause such problems?

 

Here's how I do initialize openGL contex with SDL:

 

1) Init SDL

2) Create a screen surface

3) Init IMG / TTF

4) Init GL attributes:

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);

//	glEnable(GL_DEPTH_TEST);
//	glDepthFunc(GL_LEQUAL);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//	glMatrixMode(GL_PROJECTION);
//	glLoadIdentity();

//	glMatrixMode(GL_MODELVIEW);
//	glLoadIdentity();

	glClearColor(0.f, 0.f, 0.f, 1.f);

5) Init glew

 

Anyway - still trying to fix that so if someone has any clues what's going wrong, answer please ;)

Share this post


Link to post
Share on other sites

Looks to me like your lights are rendering to the depth buffer and thus culling whatever lights come after? Try leaving depth testing on, but turn depth writes off.

Edited by Styves

Share this post


Link to post
Share on other sites

Unfortunately, already tried that before. Still wonder what would that be. Also I don't think it's a hardware issue (artifacts occur on GF9800 and GF8400). 

Could that be some aliasing effect or z-fighting? How to check which of those it is?

 

Wonderning have I choose a wrong technique of rendering light? What alternatives do I have?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!