Pixel Shader for a 2D Light

Started by Wolftein, August 11, 2009, 02:30:03

Previous topic - Next topic

Wolftein

I´m making an 2D Tileengine, and i´m doing an spot light though Shaders, and i want to know what it´s the bad thing im doing in the shader.
i can´t make the light to loose bright the more it´s far from the pointLight, i just start with Shaders 2 weeks ago and im still an newbie :D, thanks you

Vertex Shader
varying vec2 texCoord;

void main()

{
	// i pass the texture Vertex to the pixelShader
	texCoord    = gl_MultiTexCoord0.st;
	// i set the position of the vertex
    gl_Position = ftransform();
}


Pixel Shader
// variables passed by the
// application for the light
uniform float lightSize;
uniform vec2 lightPosition;
uniform vec4 lightColor;
uniform float lightTreshold;
uniform float lightIntensity;

// image that we are processing
uniform sampler2D   imageBase;

// this is the texCoordinates
// that it's passed by the vertexShader
varying vec2        texCoord;

void main()
{	
	// grab the color of the texture
	// fragment
	vec4 texColor 	 = texture2D(imageBase, texCoord);
	// normalize the fragment coordinates
	// to a 2D space
	vec2 normalFragCoord = vec2( gl_FragCoord.x, gl_FragCoord.y );
	// return the distance between the light position
	// and the fragment color
	float posDistance = distance( (lightPosition), (normalFragCoord) );
	// The color of the texture * by the lightIntensity
	// Mix with the distance		 
	// set the Fragment Color
	// to the calculed
	vec4 attenuationColor = clamp(texColor + lightColor * lightIntensity,0.0,1.0);
	
	vec4 attColor = mix( attenuationColor , texColor  ,lightColor);
		 attColor.a = 1.0;
    if(  posDistance < lightSize )
    {
    	gl_FragColor = attColor;
    }
    else
    {
   		gl_FragColor = texColor;
   	}
}

Ciardhubh

Maybe you mixed up various coordinates spaces.

From the GLSL spec:
"The variable gl_FragCoord is available as an input variable from within fragment shaders and it holds the
window relative coordinates x, y, z, and 1/w values for the fragment."

Are your lightPosition and lightSize in the same space and range?

Also, what's the point of this call?
vec4 attColor = mix( attenuationColor , texColor  ,lightColor);
It calculates (tex + light * int) (1 - light) + tex * light, which is a strange lighting function. For example a white light at full intensity only shows the tex colour. A black light also only shows the tex colour.

Wolftein

I change the equation, and now works fine thanks you, but i´m still cannot make that a degradated light.

lightPosition and lightSize are both 2D Coordinates on the screen.

what im try to do, it´s for example:

i have a light at the position 100,100 of the screen with a size of 40, that´s mean that it will go from 60-140, 60-140, my shader will paint the same pixels from 60,140, but what im try to do its that in pixel 100 draw 1.0,1.0,1.0 (RGB), 99 (1.0-Degradates%)

how can archieve that?

Ciardhubh

Quote from: Wolftein on August 12, 2009, 18:54:09
I change the equation, and now works fine thanks you, but i´m still cannot make that a degradated light.

lightPosition and lightSize are both 2D Coordinates on the screen.

what im try to do, it´s for example:

i have a light at the position 100,100 of the screen with a size of 40, that´s mean that it will go from 60-140, 60-140, my shader will paint the same pixels from 60,140, but what im try to do its that in pixel 100 draw 1.0,1.0,1.0 (RGB), 99 (1.0-Degradates%)

how can archieve that?

You'd need some attenuation based on the distance between the light and the fragment. Take a look at the default OpenGL lighting function:
http://www.glprogramming.com/red/chapter05.html
http://www.lighthouse3d.com/opengl/glsl/index.php?pointlight

If all you need is a bright circular area with falloff from the center in 2D (without any effects like normal mapping) I suggest going another way. Draw a quad - with a texture that has a white background and an alpha gradient from the center to the edge - where your light is supposed to be. This way you can draw many lights fast.

Something like:
glBlendColor(lightR, lightG, lightB, lightIntensity); // Light colour and intensity per light quad
glBlendFunc(GL_CONSTANT_COLOR, GL_ONE); // Adds the light to whatever is below the light quad
... // draw lights quads
... // Revert back to whatever you used before

However, glBlendColor requires the "ARB_imaging" extension. Alternatively you could pregenerate coloured gradients for light colours you need; together with an appropriate blend function (glBlendFunc(GL_SRC_ALPHA, GL_ONE) I guess). There are probably other ways to do this, too.

Experiment with glBlendEquation and glBlendFunc. You can get some nice effects with these.