diff --git a/sea.glsl b/sea.glsl new file mode 100644 index 0000000..93efbbd --- /dev/null +++ b/sea.glsl @@ -0,0 +1,192 @@ +/* + * "Seascape" by Alexander Alekseev aka TDM - 2014 + * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. + * Contact: tdmaav@gmail.com + */ +precision mediump float; +const int NUM_STEPS = 8; +const float PI = 3.141592; +const float EPSILON = 1e-3; +uniform float u_time; +uniform vec2 u_resolution; +#define EPSILON_NRM (0.1 / u_resolution.x) +//#define AA + +// sea +const int ITER_GEOMETRY = 3; +const int ITER_FRAGMENT = 5; +const float SEA_HEIGHT = 0.6; +const float SEA_CHOPPY = 4.0; +const float SEA_SPEED = 0.8; +const float SEA_FREQ = 0.16; +const vec3 SEA_BASE = vec3(0.0,0.09,0.18); +const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6)*0.6; +#define SEA_TIME (1.0 + u_time * SEA_SPEED) +const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6); + +// math +mat3 fromEuler(vec3 ang) { + vec2 a1 = vec2(sin(ang.x),cos(ang.x)); + vec2 a2 = vec2(sin(ang.y),cos(ang.y)); + vec2 a3 = vec2(sin(ang.z),cos(ang.z)); + mat3 m; + m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x); + m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x); + m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y); + return m; +} +float hash( vec2 p ) { + float h = dot(p,vec2(127.1,311.7)); + return fract(sin(h)*43758.5453123); +} +float noise( in vec2 p ) { + vec2 i = floor( p ); + vec2 f = fract( p ); + vec2 u = f*f*(3.0-2.0*f); + return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), + hash( i + vec2(1.0,0.0) ), u.x), + mix( hash( i + vec2(0.0,1.0) ), + hash( i + vec2(1.0,1.0) ), u.x), u.y); +} + +float specular(vec3 normal,vec3 lightPos,vec3 rayOrigin,float specular) { + float nrm = (specular + 8.0) / (PI * 8.0); + return pow(max(dot(reflect(rayOrigin,normal),lightPos),0.0),specular) * nrm; +} + +// sky +vec3 getSkyColor(vec3 e) { + e.y = (max(e.y,0.0)*0.8+0.2)*0.8; + return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1; +} + +// sea +float sea_octave(vec2 uv, float choppy) { + uv += noise(uv); + vec2 wv = 1.0-abs(sin(uv)); + vec2 swv = abs(cos(uv)); + wv = mix(wv,swv,wv); + return pow(1.0-pow(wv.x * wv.y,0.65),choppy); +} + +float map(vec3 p) { + float freq = SEA_FREQ; + float amp = SEA_HEIGHT; + float choppy = SEA_CHOPPY; + vec2 uv = p.xz; uv.x *= 0.75; + + float d, h = 0.0; + for(int i = 0; i < ITER_GEOMETRY; i++) { + d = sea_octave((uv+SEA_TIME)*freq,choppy); + d += sea_octave((uv-SEA_TIME)*freq,choppy); + h += d * amp; + uv *= octave_m; freq *= 1.9; amp *= 0.22; + choppy = mix(choppy,1.0,0.2); + } + return p.y - h; +} + +float map_detailed(vec3 p) { + float freq = SEA_FREQ; + float amp = SEA_HEIGHT; + float choppy = SEA_CHOPPY; + vec2 uv = p.xz; uv.x *= 0.75; + + float d, h = 0.0; + for(int i = 0; i < ITER_FRAGMENT; i++) { + d = sea_octave((uv+SEA_TIME)*freq,choppy); + d += sea_octave((uv-SEA_TIME)*freq,choppy); + h += d * amp; + uv *= octave_m; freq *= 1.9; amp *= 0.22; + choppy = mix(choppy,1.0,0.2); + } + return p.y - h; +} + +// lighting +float diffuse(vec3 n,vec3 l,float p) { + return pow(dot(n,l) * 0.4 + 0.6,p); +} + +vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { + float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0); + fresnel = min(pow(fresnel,5.0), 0.5); + + vec3 reflected = vec3(0., 0.5,0.9); //getSkyColor(reflect(eye,n)); + vec3 refracted = SEA_BASE + diffuse(n,l,60.0) * SEA_WATER_COLOR * 0.2; + + vec3 color = mix(refracted,reflected,fresnel); + + color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 ;// * atten; + + //color += vec3(specular(n,l,eye,80.0)); + + return color; +} + +// tracing +vec3 getNormal(vec3 p, float eps) { + vec3 n; + n.y = map_detailed(p); + n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y; + n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y; + n.y = eps; + return normalize(n); +} + +float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) { + float tm = 0.0; + float tx = 1000.0; + float hx = map(ori + dir * tx); + if(hx > 0.0) { + p = ori + dir * tx; + return tx; + } + float hm = map(ori + dir * tm); + float tmid = 0.0; + for(int i = 0; i < NUM_STEPS; i++) { + tmid = mix(tm,tx, hm/(hm-hx)); + p = ori + dir * tmid; + float hmid = map(p); + if(hmid < 0.0) { + tx = tmid; + hx = hmid; + } else { + tm = tmid; + hm = hmid; + } + } + return tmid; +} + +vec3 getPixel(in vec2 coord, float time) { + vec2 uv = coord / u_resolution.xy; + uv = uv * 2.0 - 1.0; + uv.x *= u_resolution.x / u_resolution.y; + + // ray + vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time); + vec3 ori = vec3(0.0,3.5,time*5.0); + vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.14; + dir = normalize(dir) * fromEuler(ang); + + // tracing + vec3 p; + heightMapTracing(ori,dir,p); + vec3 dist = p - ori; + vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM); + vec3 light = normalize(vec3(0.0,1.0,0.8)); + + // color + return mix( + getSkyColor(dir), + getSeaColor(p,n,light,dir,dist), + pow(smoothstep(0.0,-0.02,dir.y),0.2)); +} + +// main +void main() { + vec3 color = getPixel(gl_FragCoord.xy, u_time); + // post + gl_FragColor = vec4(pow(color,vec3(0.65)), 1.0); +} \ No newline at end of file diff --git a/shader.glsl b/shader.glsl index 707a7f6..51e6ba4 100644 --- a/shader.glsl +++ b/shader.glsl @@ -32,6 +32,14 @@ float noise(vec2 p, float scale ) hash( i + vec2(1.0,1.0) ), u.x), u.y); } +float noise2( in vec2 p ) { + vec2 i = floor( p ), f = fract( p ), u = f*f*(3.0-2.0*f); + return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), + hash( i + vec2(1.0,0.0) ), u.x), + mix( hash( i + vec2(0.0,1.0) ), + hash( i + vec2(1.0,1.0) ), u.x), u.y); +} + float displacement( vec3 p ) { return noise(10.*p.xy+u_time+1e3, 0.2) + 0.5*noise(10.*(p.xy+2.0)-u_time+1e3, .2); @@ -93,7 +101,10 @@ fogColor2 = vec3(.7, .4, .2), // fog color2 indirColor = vec3(.2, .1, .3), // indirect light color light1Color = vec3(.9, .5, .7), light2Color = vec3(.8, .7, .5), -chevronColor = vec3(.9, .3, 0.); +chevronColor = vec3(.9, .3, 0.), +SEA_BASE = vec3(0.0, 0.1, 0.2), +SEA_WATER_COLOR =vec3(0.8,0.9,0.6)*0.6; + // with duration d, startTime s and speed up with timeFact float timedSine(vec3 i) { @@ -129,6 +140,13 @@ float prismAnim(vec2 i) { ////////////// // SCENE // ////////////// +float sea_octave(vec2 uv, float choppy) { + uv += noise2(uv); + vec2 wv = 1.0-abs(sin(uv)); + vec2 swv = abs(cos(uv)); + wv = mix(wv,swv,wv); + return pow(1.0-pow(wv.x * wv.y,0.65),choppy); +} vec2 map(vec3 p) { @@ -206,8 +224,18 @@ vec2 map(vec3 p) d = min(d,d2); if (d==d2) mat = 3.0; - d2 = 1e3; - d2 = max(-sdCappedCylinder(p, 2.0, clamp((2.0 - (u_time*2.0 - 2.0*23.0)),0.,2.0)), sdCappedCylinder(p, .025, 1.6)+ displacement(p)*clamp(((u_time-24.0)*0.5), 0., 0.25)); + d2 = 1e3; + float h = 0.0, d3, choppy=4., freq=0.6, amp=.2; + vec2 uv = p.xy; + for(int i = 0; i < 5; i++) { + d3 = sea_octave((uv+u_time)*freq,choppy); + d3 += sea_octave((uv-u_time)*freq,choppy); + h += d3 * amp; + uv *= mat2(1.6,1.2,-1.2,1.6); freq *= 1.9; amp *= 0.22; + choppy = mix(choppy,1.0,0.4); + } + d2 = max(-sdCappedCylinder(p, 2.0, clamp((2.0 - (u_time*2.0 - 2.0*23.0)),0.,2.0)), sdCappedCylinder(p, .025, 1.6) - h*0.15); + d2 = max(d2, sdCappedCylinder ( p, 0.3, 1.6)); d = min(d, d2); if (d==d2) mat = 1.0; @@ -237,14 +265,35 @@ vec3 getNormal(vec3 p) { return normalize(n); } -float getLight(vec3 p, vec3 lightPos, float intensity, float shadow) { - vec3 l = normalize(lightPos - p), n = getNormal(p); +float getLight(vec3 p, vec3 lightPos, float intensity, float shadow, vec3 n) { + vec3 l = normalize(lightPos - p); float dif = clamp(dot(n, l), 0., intensity), d = rayMarch(p+n*.0025, l); if(abs(d) vec3 in normalize is light direction @@ -344,8 +394,9 @@ vec3 sceneGate(vec2 uv) if(mat==0.) col *= vec3(.3); - else if(mat==1.) - col *= vec3(0.,0.,.5); // + (noise(5.*(p.xy+2.)+u_time, -1.0) * noise(50.*(p.xy+2.), -0.4) + 0.5*noise(20.*(p.xy+2.0)-u_time, -0.5) * noise(5.*(p.xy+2.0), -0.75))*smoothstep(0.,0.75,(u_time-5.0)*0.1) + vec3(0.,0.,0.5*noise(10.*(p.xy+4.0)-u_time, -0.5)); + else if(mat==1.){ + col = getSeaColor(p, n, normalize(vec3(0.0,0.3,0.8)),normalize(rd)); //col = vec3(0.,0.,.5); // + (noise(5.*(p.xy+2.)+u_time, -1.0) * noise(50.*(p.xy+2.), -0.4) + 0.5*noise(20.*(p.xy+2.0)-u_time, -0.5) * noise(5.*(p.xy+2.0), -0.75))*smoothstep(0.,0.75,(u_time-5.0)*0.1) + vec3(0.,0.,0.5*noise(10.*(p.xy+4.0)-u_time, -0.5)); + } else if(mat==2.) col *= vec3(.3, .1, .0); // - 0.2*noise((vec2(100.*p.x+300.,75.*p.z+150.0)), -2.2) * noise((vec2(15.*p.x+2.0,3.*p.z+2.)), -1.) + noise((vec2(15.*p.x+2.4,3.*p.z+2.)), -0.25); else if(mat==3.) @@ -361,72 +412,7 @@ vec3 sceneGate(vec2 uv) return postProcess(col); } -void pMod1(inout float p, float size) { - p = mod(p + size*0.5, size) - size*0.5; -} - -void getQ(inout vec3 q, float i, float speed, float radius) { - q.z -= .5; - q.xy *= rot2D(sin(speed*u_time*.25)*PI); - q.x -= radius * sin(i / PI); - q.y -= radius * cos(i / PI); - q.z += i * .01; -} - -vec2 map2(vec3 pos) { - float d = 1e3, mat; - pMod1(pos.z, 1.); - for (float i = 0.; i < 90.; i++) { - vec3 q = pos; - getQ(q, i, -1., 3.); - float b = sdSphere(q, 0.05); - d = min(d, b); - if (d == b) mat = 0.; - q = pos; - getQ(q, i, 1., .3); - b = sdSphere(q, 0.01); - d = min(d, b); - if (d == b) mat = 1.; - } - return vec2(d, mat); -} - -vec3 palette(float t) { - vec3 a = vec3(0.5, 0.5, 0.5), - b = vec3(1.0, 1.0, 1.0), - c = vec3(1.0, 1.0, 1.0), - d = vec3(0.0, 0.66, 0.33); - return a + b * cos(6.3 * (c*t+d)); -} - -float rayMarch2(vec3 ro, vec3 rd) { - float t = 0.,d; - for (int i = 0; i < 60; i++) { - d = map2(ro + rd * t).x; - t += d; - if (d < .002 || t > 20.) break; - } - return t; -} - -vec3 sceneTunnel(vec2 uv) { - vec3 ro = vec3(0.,0.,u_time*2. ), - col = vec3(0., 0., .1), - rd = normalize(vec3(uv, .7)); - float d = rayMarch2(ro, rd), - mat = map2( ro + rd * d).y; - if (d < 10.) { - if (mat == 0.) col = vec3( 0., .3, .6); - if (mat == 1.) col = palette(1. - .4*d); - } - return col; -} - -void main() { - vec2 uv = (gl_FragCoord.xy * 2. - u_resolution.xy) / u_resolution.y; - if (u_time < 29.) { - gl_FragColor = vec4(sceneGate(uv), 1.); - } else { - gl_FragColor = vec4(sceneTunnel(uv), 1.); - } +void main() { + vec2 uv = (gl_FragCoord.xy * 2. - u_resolution.xy) / u_resolution.y; + gl_FragColor = vec4(sceneGate(uv), 1.); } \ No newline at end of file