xxxxxxxxxx
90
precision mediump float;
uniform sampler2D colour;
const int NUM_SPHERES = 10;
uniform vec4 spheres[NUM_SPHERES];
uniform float millis;
uniform vec3 sunPos;
uniform float waterLevel;
uniform vec4 waterColour;
varying vec2 pos;
const float shadowBrightness = 0.5;
const int MAX_STEPS = 100;
const float EPSILON = 0.01;
float smin( float a, float b) {
float k = 32.;
float res = exp2( -k*a ) + exp2( -k*b );
return -log2( res )/k;
}
float distToTerrain(vec3 pos) {
float d = pos.z;
for(int i = 0; i < NUM_SPHERES; i ++) {
d = smin(d, length(pos - spheres[i].xyz) - spheres[i].w);
}
return d;
}
float castRay(vec3 pos, vec3 dir) {
vec3 origin = pos;
for(int i = 0; i < MAX_STEPS; i ++) {
float d = distToTerrain(pos);
if(d < EPSILON) {
return length(pos-origin);
}
pos += dir * d;
}
return -1.;
}
float heightAt(vec2 pos) {
return 1. - castRay(vec3(pos, 1.), vec3(0., 0., -1.));
}
void main() {
// Get height from height map
float hgt = heightAt(pos);
// Starting point for ray cast
vec3 p = vec3(pos, max(waterLevel, hgt + EPSILON));
// Direction of raycast is towards the sun from centre of screen
vec3 sunDir = sunPos - p;//vec3(0.5, 0.5, 0.);
vec3 stepDir = normalize(sunDir);
float inShadow = step(-0.1, castRay(p, stepDir));
float waterDepth = waterLevel - hgt;
float isWater = step(0., waterDepth);
float isFoam = isWater * (1. - smoothstep(0., 0.05, waterDepth));
isFoam *= (sin(cos(millis/500.)*2. + waterDepth * 500.) + 1.)/2.;
vec4 col = texture2D(colour, vec2(hgt, 0.5));
col = mix(col, waterColour, isWater);
col += isFoam/5.;
// create a darker version of the colour for the shadows
vec4 shadowCol = vec4(col.rgb * shadowBrightness, col.a);
// inShadow = smoothstep(0., 1., inShadow + normalShadow);
gl_FragColor = mix(col, shadowCol, inShadow);
}