-- Sunset on the sea v.1.0.1 - Ray Marching & Ray Tracing experiment by Riccardo Gerosa aka h3r3 -- Converted from ShaderToy to live-wallpaper system effect = nil function _create() local fxSrc = [[ const bool USE_MOUSE = false; const float PI = 3.14159265; const float MAX_RAYMARCH_DIST = 150.0; const float MIN_RAYMARCH_DELTA = 0.00015; const float GRADIENT_DELTA = 0.015; float waveHeight1 = 0.005; float waveHeight2 = 0.004; float waveHeight3 = 0.001; vec2 mouse; // --------------------- START of SIMPLEX NOISE vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } vec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); } float snoise(vec2 v) { const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); vec2 i = floor(v + dot(v, C.yy)); vec2 x0 = v - i + dot(i, C.xx); vec2 i1; i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; i = mod289(i); vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0)); vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); m = m * m; m = m * m; vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 ox = floor(x + 0.5); vec3 a0 = x - ox; m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h); vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } // --------------------- END of SIMPLEX NOISE float map(vec3 p) { return p.y + (0.5 + waveHeight1 + waveHeight2 + waveHeight3) + snoise(vec2(p.x + uTime * 0.4, p.z + uTime * 0.6)) * waveHeight1 + snoise(vec2(p.x * 1.6 - uTime * 0.4, p.z * 1.7 - uTime * 0.6)) * waveHeight2 + snoise(vec2(p.x * 6.6 - uTime * 1.0, p.z * 2.7 + uTime * 1.176)) * waveHeight3; } vec3 gradientNormalFast(vec3 p, float map_p) { return normalize(vec3( map_p - map(p - vec3(GRADIENT_DELTA, 0, 0)), map_p - map(p - vec3(0, GRADIENT_DELTA, 0)), map_p - map(p - vec3(0, 0, GRADIENT_DELTA)))); } float intersect(vec3 p, vec3 ray_dir, out float map_p, out int iterations) { iterations = 0; if (ray_dir.y >= 0.0) { return -1.0; } float distMin = (-0.5 - p.y) / ray_dir.y; float distMid = distMin; for (int i = 0; i < 50; i++) { distMid += max(0.05 + float(i) * 0.002, map_p); map_p = map(p + ray_dir * distMid); if (map_p > 0.0) { distMin = distMid + map_p; } else { float distMax = distMid + map_p; for (int i = 0; i < 10; i++) { distMid = distMin + (distMax - distMin) / 2.0; map_p = map(p + ray_dir * distMid); if (abs(map_p) < MIN_RAYMARCH_DELTA) return distMid; if (map_p > 0.0) { distMin = distMid + map_p; } else { distMax = distMid + map_p; } } return distMid; } } return distMin; } void main() { vec2 fragCoord = (vPosition * 0.5 + 0.5) * uDesktopSize; mouse = vec2(uMouse.x / uDesktopSize.x, uMouse.y / uDesktopSize.y); float waveHeight = USE_MOUSE ? mouse.x * 5.0 : cos(uTime * 0.03) * 1.2 + 1.6; waveHeight1 *= waveHeight; waveHeight2 *= waveHeight; waveHeight3 *= waveHeight; vec2 position = vec2( (fragCoord.x - uDesktopSize.x / 2.0) / uDesktopSize.y, (fragCoord.y - uDesktopSize.y / 2.0) / uDesktopSize.y ); vec3 ray_start = vec3(0, 0.2, -2); vec3 ray_dir = normalize(vec3(position, 0) - ray_start); ray_start.y = cos(uTime * 0.5) * 0.2 - 0.25 + sin(uTime * 2.0) * 0.05; const float dayspeed = 0.04; float subtime = max(-0.16, sin(uTime * dayspeed) * 0.2); float middayperc = USE_MOUSE ? mouse.y * 0.3 - 0.15 : max(0.0, sin(subtime)); vec3 light1_pos = vec3(0.0, middayperc * 200.0, USE_MOUSE ? 200.0 : cos(subtime * dayspeed) * 200.0); float sunperc = pow(max(0.0, min(dot(ray_dir, normalize(light1_pos)), 1.0)), 190.0 + max(0.0, light1_pos.y * 4.3)); vec3 suncolor = (1.0 - max(0.0, middayperc)) * vec3(1.5, 1.2, middayperc + 0.5) + max(0.0, middayperc) * vec3(1.0, 1.0, 1.0) * 4.0; vec3 skycolor = vec3(middayperc + 0.8, middayperc + 0.7, middayperc + 0.5); vec3 skycolor_now = suncolor * sunperc + (skycolor * (middayperc * 1.6 + 0.5)) * (1.0 - sunperc); vec4 color = vec4(0.0, 0.0, 0.0, 1.0); float map_p; int iterations; float dist = intersect(ray_start, ray_dir, map_p, iterations); if (dist > 0.0) { vec3 p = ray_start + ray_dir * dist; vec3 light1_dir = normalize(light1_pos - p); vec3 n = gradientNormalFast(p, map_p); vec3 ambient = skycolor_now * 0.1; vec3 diffuse1 = vec3(1.1, 1.1, 0.6) * max(0.0, dot(light1_dir, n) * 2.8); vec3 r = reflect(light1_dir, n); vec3 specular1 = vec3(1.5, 1.2, 0.6) * (0.8 * pow(max(0.0, dot(r, ray_dir)), 200.0)); float fog = min(max(p.z * 0.07, 0.0), 1.0); color.rgb = (vec3(0.6, 0.6, 1.0) * diffuse1 + specular1 + ambient) * (1.0 - fog) + skycolor_now * fog; } else { color.rgb = skycolor_now.rgb; } FragColor = color; } ]] effect = Effect.new(fxSrc) end function _update(dt) end function _render() gl.Clear(0, 0, 0, 1.0) effect:Render() end