I have created a very simple lighting shader. It currently only supports point lights, but it lights up surfaces that are completely blocked from the light. I know why, but I want to know how I can fix it. I was thinking of using a form of shadow mapping to darken those areas, but shadow mapping is difficult for me to understand and has very major performance issues. I was hoping for a more elegant and efficient version, even if it is not as nice.
Until something like that exists, I need a nice, efficient way of checking to see if a fragment or vertex is visible and computing things from there. I would also like to add that I intent to support semi-transparent objects, which should block light based on and alpha value.
The things I want:
- Fast (25+ fps with the modified shaders, I currently run at 82)
- Easily modified to incorporate more lights (three or four at most, probably).
- Support for edge smoothing (user can enable it, but will lose performance)
The things I do not want:
- Pulling information from the GPU during rendering (view stuttering is always visible when that happens)
- Visible/noticeable moving of lighting when scene is stationary (like the light is moving when it really isn't, due to randomizing)
- Expensive operations when the scene first renders.
I do not expect anybody to implement these things - just to leave room and maybe a comment where these would be done. I know this is the "holy grail" of rendering when combined with bump maps and such, but if you tone down the quality a bit, I hope it is possible. I may have to do some extra work on the CPU, but that is acceptable.
Now for the shaders I currently have working:
Vertex shader
varying vec4 color;
varying vec3 normal;
varying vec4 position;
void main (void) {
color = gl_Color; // pass color to the fragment shader
normal = normalize(gl_NormalMatrix * gl_Normal); // calculate useable normals from the basic normal data.
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; // set position
gl_TexCoord[0] = gl_MultiTexCoord0; // set texture coordinates
position = gl_Vertex; // pass gl_Vertex to the fragment shader for light calculations.
}
Fragment shader
varying vec4 color;
varying vec3 normal;
varying vec4 position;
uniform sampler2D texture;
uniform vec4 light; // position of the light, same coordinate system as non-transformed objects
void main (void) {
vec3 vector = light.xyz - position.xyz; // get the vector needed to determine length
float distance = sqrt((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z)); // determine length
vec4 final = color; // set color
final.xyz *= (1.0 / distance); // calculate light intensity on pixel
gl_FragColor = final * texture2D(texture, gl_TexCoord[0].st); // multiply by texture color
}
I can do a lot of extra cool things with this current code, such as giving lights their own colors and giving objects their own material properties, but that is not the point now. I just want basic code, preferably without needing more buffers and shaders, to determine visibility. From my research, it sounds like the stencil and depth buffers may be of use here, and they already setup, so they may be a better way to do it.
I can not stress enough that I only need the bare essentials here - nothing overly fancy. Thanks in advance for your help.