Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Ocean shaders (from Shader Toy)

Here's one that looks OK and runs fast. Touch to move camera.
https://www.shadertoy.com/view/MdXyzX


function setup() --displayMode(FULLSCREEN) seaMesh = mesh() seaMesh:addRect(WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) seaMesh:setRectTex(1 , 0,0,1,1) seaMesh.shader = shader(seaShader.vertexShader, seaShader.fragmentShader) seaMesh.shader.iResolution = vec2(WIDTH, HEIGHT) end -- This function gets called once every frame function draw() background(0,0,0,255) seaMesh.shader.iGlobalTime = ElapsedTime seaMesh.shader.iMouse = vec4(CurrentTouch.x, CurrentTouch.y , 0, 0) seaMesh:draw() end seaShader = { vertexShader = [[ // // A basic vertex shader // //This is the current model * view * projection matrix // Codea sets it automatically uniform mat4 modelViewProjection; //This is the current mesh vertex position, color and tex coord // Set automatically attribute vec4 position; attribute vec2 texCoord; varying vec2 vTexCoord; //This is an output variable that will be passed to the fragment shader void main() { vTexCoord = texCoord; //Multiply the vertex position by our combined transform gl_Position = modelViewProjection * position; } ]], fragmentShader = [[ //Default precision qualifier precision highp float; uniform float iGlobalTime; uniform vec2 iResolution; uniform vec4 iMouse; varying vec2 vTexCoord; //afl_ext 2017 // its from here https://github.com/achlubek/venginenative/blob/master/shaders/include/WaterHeight.glsl float wave(vec2 uv, vec2 emitter, float speed, float phase){ float dst = distance(uv, emitter); return pow((0.5 + 0.5 * sin(dst * phase - iGlobalTime * speed)), 5.0); } #define GOLDEN_ANGLE_RADIAN 2.39996 float getwaves(vec2 uv){ float w = 0.0; float sw = 0.0; float iter = 0.0; float ww = 1.0; uv += iGlobalTime * 0.5; // it seems its absolutely fastest way for water height function that looks real for(int i=0;i<6;i++){ w += ww * wave(uv * 0.06 , vec2(sin(iter), cos(iter)) * 10.0, 2.0 + iter * 0.08, 2.0 + iter * 3.0); sw += ww; ww = mix(ww, 0.0115, 0.4); iter += GOLDEN_ANGLE_RADIAN; } return w / sw; } float getwavesHI(vec2 uv){ float w = 0.0; float sw = 0.0; float iter = 0.0; float ww = 1.0; uv += iGlobalTime * 0.5; // it seems its absolutely fastest way for water height function that looks real for(int i=0;i<24;i++){ w += ww * wave(uv * 0.06 , vec2(sin(iter), cos(iter)) * 10.0, 2.0 + iter * 0.08, 2.0 + iter * 3.0); sw += ww; ww = mix(ww, 0.0115, 0.4); iter += GOLDEN_ANGLE_RADIAN; } return w / sw; } float H = 0.0; vec3 normal(vec2 pos, float e, float depth){ vec2 ex = vec2(e, 0); H = getwavesHI(pos.xy) * depth; vec3 a = vec3(pos.x, H, pos.y); return normalize(cross(normalize(a-vec3(pos.x - e, getwavesHI(pos.xy - ex.xy) * depth, pos.y)), normalize(a-vec3(pos.x, getwavesHI(pos.xy + ex.yx) * depth, pos.y + e)))); } mat3 rotmat(vec3 axis, float angle) { axis = normalize(axis); float s = sin(angle); float c = cos(angle); float oc = 1.0 - c; return mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); } #define mouse (iMouse.xy / iResolution.xy) vec3 getRay(vec2 uv){ uv = (uv * 2.0 - 1.0)* vec2(iResolution.x / iResolution.y, 1.0); vec3 proj = normalize(vec3(uv.x, uv.y, 1.0) + vec3(uv.x, uv.y, -1.0) * pow(length(uv), 2.0) * 0.05); vec3 ray = rotmat(vec3(0.0, -1.0, 0.0), mouse.x * 2.0 - 1.0) * rotmat(vec3(1.0, 0.0, 0.0), 1.5 * (mouse.y * 2.0 - 1.0)) * proj; return ray; } float rand2sTimex(vec2 co){ return fract(sin(dot(co.xy * iGlobalTime,vec2(12.9898,78.233))) * 43758.5453); } float raymarchwater2(vec3 camera, vec3 start, vec3 end, float depth){ float stepsize = 1.0 / 5.0; float iter = 0.0; vec3 pos = start; float h = 0.0; float rd = stepsize * rand2sTimex(end.xz); for(int i=0;i<6;i++){ pos = mix(start, end, iter); h = getwaves(pos.xz) * depth - depth; if(h > pos.y) { return distance(pos, camera); } iter += stepsize; } return -1.0; } float raymarchwater(vec3 camera, vec3 start, vec3 end, float depth){ float stepsize = 1.0 / 15.0; float iter = 0.0; vec3 pos = start; float h = 0.0; float rd = stepsize * rand2sTimex(end.xz); for(int i=0;i<16;i++){ pos = mix(start, end, iter + rd); h = getwaves(pos.xz) * depth - depth; if(h > pos.y) { return raymarchwater2(camera, mix(start, end, iter - stepsize + rd), mix(start, end, iter + rd), depth); } iter += stepsize; } return -1.0; } float intersectPlane(vec3 origin, vec3 direction, vec3 point, vec3 normal) { return clamp(dot(point - origin, normal) / dot(direction, normal), -1.0, 9991999.0); } vec3 getatm(vec3 ray){ return mix(vec3(0.9), vec3(0.0, 0.2, 0.5), sqrt(abs(ray.y))); } float sun(vec3 ray){ vec3 sd = normalize(vec3(1.0)); return pow(max(0.0, dot(ray, sd)), 528.0) * 110.0; } void main() { vec2 uv = vTexCoord; float waterdepth = 2.1; vec3 wfloor = vec3(0.0, -waterdepth, 0.0); vec3 wceil = vec3(0.0, 0.0, 0.0); vec3 orig = vec3(0.0, 2.0, 0.0); vec3 ray = getRay(uv); float hihit = intersectPlane(orig, ray, wceil, vec3(0.0, 1.0, 0.0)); if(ray.y >= -0.01){ vec3 C = getatm(ray) * 2.0 + sun(ray); //tonemapping C = normalize(C) * sqrt(length(C)); gl_FragColor = vec4( C,1.0); return; } float lohit = intersectPlane(orig, ray, wfloor, vec3(0.0, 1.0, 0.0)); vec3 hipos = orig + ray * hihit; vec3 lopos = orig + ray * lohit; float dist = raymarchwater(orig, hipos, lopos, waterdepth); vec3 pos = orig + ray * dist; vec3 N = normal(pos.xz, 0.001, waterdepth); vec2 velocity = N.xz * (1.0 - N.y); N = mix(vec3(0.0, 1.0, 0.0), N, 1.0 / (dist * dist * 0.01 + 1.0)); vec3 R = reflect(ray, N); float fresnel = (0.04 + (1.0-0.04)*(pow(1.0 - max(0.0, dot(-N, ray)), 5.0))); vec3 C = fresnel * getatm(R) * 2.0 + fresnel * sun(R); //tonemapping C = normalize(C) * sqrt(length(C)); gl_FragColor = vec4(C,1.0); } ]]}

Comments

  • edited March 2017 Posts: 454

    Here's one that looks prettier, but runs way too slow
    https://www.shadertoy.com/view/Ms2SD1


    function setup() displayMode(FULLSCREEN) seaMesh = mesh() seaMesh:addRect(WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) seaMesh:setRectTex(1 , 0,0,1,1) seaMesh.shader = shader(seaShader.vertexShader, seaShader.fragmentShader) seaMesh.shader.iResolution = vec2(WIDTH, HEIGHT) end -- This function gets called once every frame function draw() background(0,0,0,255) seaMesh.shader.iGlobalTime = ElapsedTime seaMesh.shader.iMouse = CurrentTouch.x seaMesh:draw() end seaShader = { vertexShader = [[ // // A basic vertex shader // //This is the current model * view * projection matrix // Codea sets it automatically uniform mat4 modelViewProjection; //This is the current mesh vertex position, color and tex coord // Set automatically attribute vec4 position; attribute vec2 texCoord; varying vec2 vTexCoord; //This is an output variable that will be passed to the fragment shader void main() { vTexCoord = texCoord; //Multiply the vertex position by our combined transform gl_Position = modelViewProjection * position; } ]], fragmentShader = [[ /* * "Seascape" by Alexander Alekseev aka TDM - 2014 * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. * Contact: tdmaav@gmail.com */ //Default precision qualifier precision highp float; uniform float iGlobalTime; uniform vec2 iResolution; uniform float iMouse; varying vec2 vTexCoord; const int NUM_STEPS = 8; const float PI = 3.1415; const float EPSILON = 1e-3; #define EPSILON_NRM (0.1 / iResolution.x) // 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.1,0.19,0.22); const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6); #define SEA_TIME (1.0 + iGlobalTime * 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); } // lighting float diffuse(vec3 n,vec3 l,float p) { return pow(dot(n,l) * 0.4 + 0.6,p); } float specular(vec3 n,vec3 l,vec3 e,float s) { float nrm = (s + 8.0) / (3.1415 * 8.0); return pow(max(dot(reflect(e,n),l),0.0),s) * nrm; } // sky vec3 getSkyColor(vec3 e) { e.y = max(e.y,0.0); return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4); } // 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; } 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 = pow(fresnel,3.0) * 0.65; vec3 reflected = getSkyColor(reflect(eye,n)); vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12; vec3 color = mix(refracted,reflected,fresnel); float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0); color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; color += vec3(specular(n,l,eye,60.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) 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; } // main void main() { vec2 uv = vTexCoord; //fragCoord.xy / iResolution.xy; uv = uv * 2.0 - 1.0; uv.x *= iResolution.x / iResolution.y; float time = iGlobalTime * 0.3 + iMouse*0.01; // 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.15; 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 vec3 color = mix( getSkyColor(dir), getSeaColor(p,n,light,dir,dist), pow(smoothstep(0.0,-0.05,dir.y),0.3)); // post gl_FragColor = vec4(pow(color,vec3(0.75)), 1.0); } ]]}
  • Very good! I like the first one!

    The second one has some noise point:

    image

    I found another version of it, the code is here:


    function setup() displayMode(FULLSCREEN) spriteMode(CORNER) parameter.watch("1/DeltaTime") screen = image(WIDTH/1,HEIGHT/1) w,h = screen.width,screen.height m = mesh() m.vertices = {vec2(0,0),vec2(w,0),vec2(w,h),vec2(w,h),vec2(0,h),vec2(0,0)} m.shader = shader(V,F) m.shader.iResolution = vec2(w,h) * 2 end function draw() -- setContext(screen) background(0, 0, 0, 255) m.shader.iGlobalTime = ElapsedTime m.shader.iMouse = vec2(CurrentTouch.x,CurrentTouch.y) * 2 m:draw() -- setContext() -- sprite(screen,0,0,WIDTH/1,HEIGHT/1) end function touched(touch) end V = [[ uniform mat4 modelViewProjection; attribute vec4 position; void main() { gl_Position = modelViewProjection * position; } ]] F = [[ precision highp float; uniform vec2 iResolution; uniform vec2 iMouse; uniform float iGlobalTime; const int NUM_STEPS = 4; const float PI = 3.14159; const float EPSILON= 1e-3; float EPSILON_NRM= 0.1 / iResolution.x; // 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.1,0.19,0.22); const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6); float SEA_TIME = iGlobalTime * SEA_SPEED; 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); } // lighting float diffuse(vec3 n,vec3 l,float p) { return pow(dot(n,l) * 0.4 + 0.6,p); } float specular(vec3 n,vec3 l,vec3 e,float s) { float nrm = (s + 8.0) / (3.1415 * 8.0); return pow(max(dot(reflect(e,n),l),0.0),s) * nrm; } // sky vec3 getSkyColor(vec3 e) { e.y = max(e.y,0.0); vec3 ret; ret.x = pow(1.0-e.y,2.0); ret.y = 1.0-e.y; ret.z = 0.6+(1.0-e.y)*0.4; return ret; } // 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; } vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { float fresnel = 1.0 - max(dot(n,-eye),0.0); fresnel = pow(fresnel,3.0) * 0.65; vec3 reflected = getSkyColor(reflect(eye,n)); vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12; vec3 color = mix(refracted,reflected,fresnel); float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0); color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; color += vec3(specular(n,l,eye,60.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) 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; } void main() { vec2 uv = gl_FragCoord.xy / iResolution.xy; uv = uv * 2.0 - 1.0; uv.x *= iResolution.x / iResolution.y; float time = iGlobalTime * 0.3 + iMouse.x*0.01; // 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.15; 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 vec3 color = mix( getSkyColor(dir), getSeaColor(p,n,light,dir,dist), pow(smoothstep(0.0,-0.05,dir.y),0.3)); // post gl_FragColor = vec4(pow(color,vec3(0.75)), 1.0); } ]]

    The screenshot:

    image

  • dave1707dave1707 Mod
    Posts: 6,593

    These are great. You watch them long enough and you can get sea sick.

  • Posts: 248

    the shadertoy shaders are amazing. I notice there is a shadertoy app on the apple appstore, which makes it easier to visualize the shaders.

  • edited October 2017 Posts: 553

    The first one crashes my lowly iPad 3 :(

    EDIT: actually they all do.

  • Posts: 109

    I can run the first one but it really tanks the FPS the more ocean there is on screen

  • Posts: 148

    First one works for me on iPad 2 , but it can only do ~ 0.3 fps :)
    Looks very nice though.

  • @juce what iOS version?

  • Posts: 148

    @UberGoober , iOS 8.2

    (I never upgraded further because i could see newer iOS versions putting more and more strain on the older hardware. I think maybe my old iPad 2 could still run iOS 9, but with difficulty, probably.)

  • This may have shown your wisdom, then, I suppose, @juce. Anyone out there with an iPad 3 or older running iOS 9?

  • em2em2
    edited October 2017 Posts: 174

    @UberGoober My iPad 2 stayed on iOS 8.4 so I could jailbreak it. It's crazy slow, so I figured iOS 9 isn't an option for it.

Sign In or Register to comment.