Hey everyone I am working on a rewrite (again) of the light_world.lua library found here:
viewtopic.php?f=5&t=78998 and I managed to compile my normal shading, shadow shading and shine shading all into one shader, and one draw call per light. I am pretty proud of this so check it out! It has sped up the library quite a bit and make the library (at least visually) function exactly the same. (I have not merged this branch yet with the master though I will let you know when I do)
I would also love some crits if you see any problem points, I am still fairly new at the whole shading thing.
Thanks!
Code: Select all
/*
The MIT License (MIT)
Copyright (c) 2014 Tim Anema
Light Shadow, Shine and Normal shader all in one
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#define PI 3.1415926535897932384626433832795
extern vec2 screenResolution; //size of the screen
extern Image shadowMap; //a canvas containing shadow data only
extern vec3 lightPosition; //the light position on the screen(not global)
extern vec3 lightColor; //the rgb color of the light
extern float lightRange; //the range of the light
extern float lightSmooth; //smoothing of the lights attenuation
extern vec2 lightGlow; //how brightly the light bulb part glows
extern float lightAngle; //if set, the light becomes directional to a slice lightAngle degrees wide
extern float lightDirection; //which direction to shine the light in if directional in degrees
extern bool invert_normal; //if the light should invert normals
//calculate if a pixel is within the light slice
bool not_in_slice(vec2 pixel_coords){
float angle = atan(lightPosition.x - pixel_coords.x, pixel_coords.y - lightPosition.y) + PI;
bool pastRightSide = angle < mod(lightDirection + lightAngle, PI * 2);
bool pastLeftSide = angle > mod(lightDirection - lightAngle, PI * 2);
bool lightUp = lightDirection - lightAngle > 0 && lightDirection + lightAngle < PI * 2;
return (lightUp && (pastRightSide && pastLeftSide)) || (!lightUp && (pastRightSide || pastLeftSide));
}
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
vec4 pixelColor = Texel(texture, texture_coords);
vec4 shadowColor = Texel(shadowMap, texture_coords);
//if the light is a slice and the pixel is not inside
if(lightAngle > 0.0 && not_in_slice(pixel_coords)) {
return vec4(0.0, 0.0, 0.0, 1.0);
}
vec3 normal;
if(pixelColor.a > 0.0) {
//if on the normal map ie there is normal map data
//so get the normal data
if(invert_normal) {
normal = normalize(vec3(pixelColor.r, 1 - pixelColor.g, pixelColor.b) * 2.0 - 1.0);
} else {
normal = normalize(pixelColor.rgb * 2.0 - 1.0);
}
} else {
// not on the normal map so it is the floor with a normal point strait up
normal = vec3(0.0, 0.0, 1.0);
}
float dist = distance(lightPosition, vec3(pixel_coords, normal.b));
//if the pixel is within this lights range
if(dist < lightRange) {
//calculater attenuation of light based on the distance
float att = clamp((1.0 - dist / lightRange) / lightSmooth, 0.0, 1.0);
// if not on the normal map draw attenuated shadows
if(pixelColor.a == 0.0) {
//start with a dark color and add in the light color and shadow color
vec4 pixel = vec4(0.0, 0.0, 0.0, 1.0);
if (lightGlow.x < 1.0 && lightGlow.y > 0.0) {
pixel.rgb = clamp(lightColor * pow(att, lightSmooth) + pow(smoothstep(lightGlow.x, 1.0, att), lightSmooth) * lightGlow.y, 0.0, 1.0);
} else {
pixel.rgb = lightColor * pow(att, lightSmooth);
}
//If on the shadow map add the shadow color
if(shadowColor.a > 0.0) {
pixel.rgb = pixel.rgb * shadowColor.rgb;
}
return pixel;
} else {
//on the normal map, draw normal shadows
vec3 dir = vec3((lightPosition.xy - pixel_coords.xy) / screenResolution.xy, lightPosition.z);
dir.x *= screenResolution.x / screenResolution.y;
vec3 diff = lightColor * max(dot(normalize(normal), normalize(dir)), 0.0);
//return the light that is effected by the normal and attenuation
return vec4(diff * att, 1.0);
}
} else {
//not in range draw in shadows
return vec4(0.0, 0.0, 0.0, 1.0);
}
}