Edit (2.1.2012): My lighting shader has changed quite a bit since this post; I opted for a multi-pass shader, rather than maxing out the shader variables.
After several weeks of reading about shaders, learning GLSL, learning about lighting, observing other projects, finally writing my own, and spending hours debugging, tweaking, and improving, it's finally done. My shader supports multiple lights, and gets re-written on the fly to support larger and larger amounts, due to GLSL loop limitations. Whenever I want to increase the amount of lights I use, I merely say:
LightingShader.SetMacro("NUM_LIGHTS", ++lights);
Which will then re-write, re-compile, and re-link the shader with a new light count. Though I was considering not releasing the shader source code, here it is anyway:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define MAX_LIGHTS 10 // Re-written on the fly | |
/** | |
* @file | |
* Fragment shader for lighting. | |
* Per-pixel point light lighting is done in this shader. | |
* | |
* @author me | |
* @addtogroup Shaders | |
* @{ | |
*/ | |
uniform sampler2D tex; // Active texture | |
uniform int scr_height; // Screen height | |
uniform vec2 light_pos[MAX_LIGHTS]; // Light position | |
uniform vec3 light_col[MAX_LIGHTS]; // Light color | |
uniform vec3 light_att[MAX_LIGHTS]; // Light attenuation | |
uniform float light_brt[MAX_LIGHTS]; // Light brightness | |
void main() | |
{ | |
vec2 pixel = gl_FragCoord.xy; | |
pixel.y = scr_height - pixel.y; | |
vec3 lights; | |
for(int i = 0; i < MAX_LIGHTS; ++i) | |
{ | |
vec2 light_vec = light_pos[i] - pixel; | |
float dist = length(light_vec); | |
float att = 1.0 / ( light_att[i].x + | |
(light_att[i].y * dist) + | |
(light_att[i].z * dist * dist)); | |
lights += light_col[i] * att * light_brt[i]; | |
} | |
vec4 texel = texture2D(tex, gl_TexCoord[0].st) * gl_Color; | |
gl_FragColor = texel * vec4(lights, 1.0); | |
} | |
/** @} */ |
![]() |
Original shader - one light (in-game) |
![]() |
Final shader - multiple lights (test zone) |
No comments:
Post a Comment