Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //This is the default Sprite Lamp shader. It is not optimised for speed but rather, readability,
- //so certain things wouldn't make sense in a game environment (for instance you'd probably
- //want to pack things into fewer textures).
- #version 120
- uniform sampler2D normalMap;
- uniform sampler2D diffuseMap;
- uniform sampler2D depthMap;
- uniform sampler2D specularMap; //Optionally contains glossiness in the alpha channel
- uniform sampler2D emissiveMap;
- uniform sampler2D aoMap;
- uniform sampler2D anisotropyMap; //Not used in this shader.
- uniform vec3 lightPosition;
- uniform vec3 directLightColour;
- uniform vec3 ambientLightColour; //Upper ambient colour
- uniform vec3 ambientLightColour2; //Lower ambient colour
- uniform vec2 textureResolution; //Used for per texel lighting
- uniform float celShadingLevel;
- uniform float lightWrap;
- uniform float amplifyDepth;
- uniform float shadows; //boolean value - determines whether to use shadows
- uniform float ambientMapStrength;
- uniform float normalFlip; //boolean value so the shader knows whether to expect normals with upsidedown Y values
- uniform float attenuationMultiplier;
- uniform float glossFromSpecAlpha; //boolean value - determines whether to get specular exponent from the spec map alpha
- uniform mat2 rotationMatrix; //Simple case of 2D rotation - not suitable for general game engine use
- void main()
- {
- //This value will be the tex coords at the centre of the nearest texel.
- vec2 centredTexCoords = gl_TexCoord[0].xy;
- centredTexCoords *= textureResolution.xy;
- centredTexCoords = floor(centredTexCoords.xy) + vec2(0.5, 0.5);
- centredTexCoords /= textureResolution.xy;
- //All the texture lookups done at the start where possible.
- vec4 normalColour = texture2D(normalMap, gl_TexCoord[0].xy);
- vec4 diffuseColour = texture2D(diffuseMap, gl_TexCoord[0].xy);
- vec4 specularColour = texture2D(specularMap, gl_TexCoord[0].xy);
- vec4 emissiveColour = texture2D(emissiveMap, gl_TexCoord[0].xy);
- vec4 aoColour = texture2D(aoMap, gl_TexCoord[0].xy);
- vec4 anisotropyColour = texture2D(anisotropyMap, gl_TexCoord[0].xy);
- float depthColour = texture2D(depthMap, gl_TexCoord[0].xy).x;
- if (diffuseColour.a <= 0.1)
- {
- discard;
- }
- aoColour *= ambientMapStrength;
- aoColour += 1.0 - ambientMapStrength;
- vec3 fragPos;
- fragPos.xy = gl_TexCoord[0].xy;
- //This sets the fragment position at the centre of the nearest texel,
- //for per-texel lighting. This unfortunately isn't very reusable in a general game engine sense.
- fragPos.xy *= textureResolution.xy;
- fragPos.xy = floor(fragPos.xy);
- fragPos.xy /= textureResolution.xy;
- fragPos.y = 1.0 - fragPos.y;
- fragPos = fragPos + vec3(-0.5, -0.5, 0.0);
- fragPos.x *= (textureResolution.x / textureResolution.y);
- fragPos.z = depthColour * amplifyDepth;
- vec3 normal = (normalColour.rgb - 0.5) * 2.0;
- normal.y *= normalFlip;
- normal.xy *= rotationMatrix;
- vec3 lightVec = lightPosition - fragPos;
- lightVec.xy *= rotationMatrix;
- float lightDistance = length(lightVec) * attenuationMultiplier;
- //Currently attenuation uses certain fudge factors.
- float attenuation = 1.0 / (1.0 + 20.0 * lightDistance + 200.0 * lightDistance * lightDistance);
- normal = normalize(normal);
- lightVec = normalize(lightVec);
- float shadowMult = 1.0;
- if (shadows > 0.5)
- {
- //Shadowing in Sprite Lamp works by tracing the light path backwards and checking to see
- //how many points on that line are 'inside' the depth map. The more there are, the darker the shadow,
- //until it becomes black. This isn't really physically accurate, but it does give reasonably convincing
- //soft shadows.
- float thisHeight = fragPos.z;
- vec3 tapPos = vec3(centredTexCoords, fragPos.z + 0.01);
- vec3 moveVec = lightVec.xyz * vec3(1.0, -1.0, 1.0) * 0.006;
- moveVec.xy *= rotationMatrix;
- moveVec.x *= textureResolution.y / textureResolution.x;
- for (int i = 0; i < 16; i++)
- {
- tapPos += moveVec;
- float tapDepth = texture2D(depthMap, tapPos.xy).x * amplifyDepth;
- if (tapDepth > tapPos.z)
- {
- shadowMult -= 0.125;
- }
- }
- }
- shadowMult = clamp(shadowMult, 0.0, 1.0);
- float rawDiffuse = clamp(dot(normal, lightVec) * 1000.0, 0.0, 1.0);
- //Somewhat confusing calculation to determine the diffuse level modified by the light wrap value.
- float diffuseLevel = clamp(dot(normal, lightVec) + lightWrap, 0.0, lightWrap + 1.0) / (lightWrap + 1.0) * attenuation;
- //Specular calculations
- vec3 viewVec = vec3(0.0, 0.0, 1.0); //Orthographic camera makes this nice and simple.
- vec3 bounceVec = reflect(-lightVec, normal);
- //Add 0.5 to the end of this to avoid raising to the zeroth power.
- float glossiness = (5.0 * (1.0 - glossFromSpecAlpha)) + (specularColour.a * 50.0 * glossFromSpecAlpha) + 0.5;
- float specLevel = pow(clamp(dot(bounceVec, viewVec), 0.0, 1.0), glossiness) * rawDiffuse * 0.5 * attenuation;
- diffuseLevel *= shadowMult;
- diffuseLevel *= celShadingLevel;
- diffuseLevel = floor(diffuseLevel);
- diffuseLevel /= celShadingLevel - 0.5;
- specLevel *= celShadingLevel;
- specLevel = floor(specLevel);
- specLevel /= celShadingLevel - 0.5;
- //The 'upFactor' is the extent to which the surface normal is pointing up in world space.
- //1.0 meaning straight up, 0.0 meaning straight down, and 0.5 meaning horizontal. It is
- //then used for mixing the upper and lower amnbient colours.
- float upFactor = normal.y * 0.5 + 0.5;
- upFactor *= celShadingLevel;
- upFactor = floor(upFactor);
- upFactor /= celShadingLevel - 0.5;
- vec3 ambientResult = ambientLightColour * upFactor + ambientLightColour2 * (1.0 - upFactor);
- //Everything is comnbined in a big final calculation here.
- gl_FragColor.rgb = (diffuseLevel * directLightColour + ambientResult * aoColour.rgb) * diffuseColour.rgb;
- gl_FragColor.rgb += vec3(specLevel, specLevel, specLevel) * specularColour.rgb * directLightColour * shadowMult + emissiveColour.rgb;
- gl_FragColor.a = diffuseColour.a;
- }
Add Comment
Please, Sign In to add comment