Files
TDT4230/res/shaders/simple.frag

83 lines
2.3 KiB
GLSL

#version 430 core
in layout(location = 0) vec3 normal;
in layout(location = 1) vec2 textureCoordinates;
in layout(location = 2) vec3 worldPosition;
struct LightSource {
vec3 position;
vec3 color;
};
uniform LightSource lights[3];
uniform vec3 cameraPosition;
uniform vec3 ballPosition;
out vec4 fragColor;
const vec3 baseColor = vec3(1.0);
const float ambientStrength = 0.1;
const float specularStrength = 0.5;
const float shininess = 32.0;
// attenuation: 1 / (la + lb*d + lc*d²)
const float la = 0.1;
const float lb = 0.01;
const float lc = 0.001;
// soft shadow radii
const float ballRadius = 1.0;
const float hardRadius = ballRadius;
const float softRadius = ballRadius * 2.0;
float rand(vec2 co) {
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}
float dither(vec2 uv) {
return (rand(uv) * 2.0 - 1.0) / 256.0;
}
void main()
{
vec3 N = normalize(normal);
vec3 V = normalize(cameraPosition - worldPosition);
// start with ambience
vec3 result = ambientStrength * baseColor;
for (int i = 0; i < 3; i++) {
vec3 toLight = lights[i].position - worldPosition;
vec3 L = normalize(toLight);
float dist = length(toLight);
float attenuation = 1.0 / (la + lb * dist + lc * dist * dist);
float diff = max(dot(N, L), 0.0);
vec3 diffuse = diff * lights[i].color;
// blinn-phong half-vector
vec3 H = normalize(L + V);
float spec = pow(max(dot(N, H), 0.0), shininess);
vec3 specular = specularStrength * spec * lights[i].color;
vec3 toBall = ballPosition - worldPosition;
float projDist = dot(toBall, L); // distance along light ray
float perpDist = length(toBall - projDist * L); // perpendicular distance to ray
bool inShadowCone = (projDist > 0.0) && (projDist < dist);
float shadow = 1.0;
// skip ball's own light (index 2) to avoid self-shadowing the whole scene
if (inShadowCone) {
if (perpDist <= hardRadius) {
shadow = 0.0;
} else if (perpDist < softRadius) {
shadow = (perpDist - hardRadius) / (softRadius - hardRadius);
}
}
result += shadow * attenuation * (diffuse + specular) * baseColor;
}
fragColor = vec4(result + dither(textureCoordinates), 1.0);
}