decla-red/frontend/src/shaders/lights-shading-fs.glsl
schmelczerandras edd7d4836e Tweak code
2020-07-25 19:27:21 +02:00

86 lines
2.3 KiB
GLSL

#version 300 es
precision mediump float;
#define INFINITY 1000.0
#define LIGHT_COUNT 8
#define AMBIENT_LIGHT vec3(0.15)
#define LIGHT_DROP 400.0
uniform struct Light {
vec2 center;
float radius;
vec3 value;
}[LIGHT_COUNT] lights;
uniform sampler2D distanceTexture;
uniform vec2 viewBoxSize;
float getDistance(in vec2 target, out vec3 color) {
vec4 values = texture(distanceTexture, target);
color = values.rgb;
return values.w * 32.0;
}
float getDistance(in vec2 target) {
return texture(distanceTexture, target).w * 32.0;
}
float getFractionOfLightArriving(
in vec2 target,
in vec2 direction,
in float startingDistance,
in float lightDistance,
in float lightRadius
) {
float q = 1.0;
float rayLength = startingDistance;
float movingAverageMeanDistance = startingDistance;
direction /= viewBoxSize;
for (int j = 0; j < 48; j++) {
float minDistance = getDistance(target + direction * rayLength);
movingAverageMeanDistance = movingAverageMeanDistance / 2.0 + minDistance / 2.0;
q = min(q, movingAverageMeanDistance / rayLength);
rayLength = min(lightDistance, rayLength + max(5.0, minDistance));
}
return clamp(q * (lightDistance + lightRadius) / lightRadius, 0.0, 1.0);
}
vec3 getPixelColor(in vec2 worldCoordinates, in vec2 uvCoordinates) {
vec3 colorAtPosition;
float startingDistance = getDistance(uvCoordinates, colorAtPosition);
vec3 result = colorAtPosition * AMBIENT_LIGHT;
for (int i = 0; i < LIGHT_COUNT; i++) {
Light light = lights[i];
vec2 lightDelta = light.center - worldCoordinates;
float lightDistance = length(lightDelta);
vec2 lightDirection = lightDelta / lightDistance;
float r = lightDistance / LIGHT_DROP + 1.0;
vec3 lightColorAtPosition = light.value / (r * r);
float fractionOfLightArriving = getFractionOfLightArriving(
uvCoordinates, lightDirection, startingDistance,
lightDistance, light.radius
);
result += colorAtPosition * lightColorAtPosition * fractionOfLightArriving;
}
return result;
}
in vec2 worldCoordinates;
in vec2 uvCoordinates;
out vec4 fragmentColor;
void main() {
fragmentColor = vec4(getPixelColor(worldCoordinates, uvCoordinates), 1.0);
}