86 lines
2.3 KiB
GLSL
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);
|
|
}
|