// Credit to iq: https://www.shadertoy.com/view/4sS3zG // // Created by Sam Gondelman on 7/6/2016 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // float hash(float n) { return fract(sin(n)*753.5453123); } float noise(vec2 xy) { int seed = 2503; vec2 p = floor(xy); vec2 f = fract(xy); f = f*f*(3.0-2.0*f); float n = dot(vec3(p.xy, seed), vec3(1, 157, 141)); return mix(mix(hash(n+ 0.0), hash(n+ 1.0),f.x), mix(hash(n+157.0), hash(n+158.0),f.x),f.y); } vec2 sd2Segment( vec3 a, vec3 b, vec3 p ) { vec3 pa = p - a; vec3 ba = b - a; float t = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); vec3 v = pa - ba*t; return vec2( dot(v,v), t ); } float udBox(vec3 p, vec3 b) { return length(max(abs(p)-b, 0.0)); } float udRoundBox( vec3 p, vec3 b, float r ) { return length(max(abs(p)-b,0.0))-r; } float smin( float a, float b, float k ) { float h = clamp( 0.5 + 0.5*(b-a)/k, 0.0, 1.0 ); return mix( b, a, h ) - k*h*(1.0-h); } //----------------------------------------------------------------------------------- #define NUMI 11 #define NUMF 11.0 vec3 fishPos; float fishTime; float isJump; float isJump2; vec2 anima( float ih, float t ) { float an1 = 0.9*(0.5+0.2*ih)*cos(5.0*ih - 3.0*t + 6.2831/4.0); float an2 = 1.0*cos(3.5*ih - 1.0*t + 6.2831/4.0); float an = mix( an1, an2, isJump ); float ro = 0.4*cos(4.0*ih - 1.0*t)*(1.0-0.5*isJump); return vec2( an, ro ); } vec3 anima2( void ) { vec3 a1 = vec3(0.0, sin(3.0*fishTime+6.2831/4.0),0.0); vec3 a2 = vec3(0.0,1.5+2.5*cos(1.0*fishTime),0.0); vec3 a = mix( a1, a2, isJump ); a.y *= 0.5; a.x += 0.1*sin(0.1 - 1.0*fishTime)*(1.0-isJump); return a; } vec2 sdDolphinCheap( vec3 p ) { vec2 res = vec2( 1000.0, 0.0 ); p -= fishPos; vec3 a = anima2(); float or = 0.0; float th = 0.0; float hm = 0.0; vec3 mp = a; for( int i=0; iprecis && tmaxd ) break; { t += h; vec2 res = sdDolphin( ro+rd*t ); h = res.x; l = res.y; } } if( t>maxd ) t=-1.0; return vec2( t, l); } vec3 calcNormalFish( in vec3 pos ) { const vec3 eps = vec3(0.08,0.0,0.0); float v = sdDolphin(pos).x; return normalize( vec3( sdDolphin(pos+eps.xyy).x - v, sdDolphin(pos+eps.yxy).x - v, sdDolphin(pos+eps.yyx).x - v ) ); } float softshadow( in vec3 ro, in vec3 rd, float mint, float k ) { float res = 1.0; float t = mint; float h = 1.0; for( int i=0; i<25; i++ ) { h = sdDolphinCheap(ro + rd*t).x; res = min( res, k*h/t ); t += clamp( h, 0.05, 0.5 ); if( h<0.0001 ) break; } return clamp(res,0.0,1.0); } //vec3 lig = normalize(vec3(0.9,0.15,0.5)); const vec3 lig = vec3(0.86,0.15,0.48); vec3 doLighting( in vec3 pos, in vec3 nor, in vec3 rd, float glossy, float glossy2, float shadows, in vec3 col, float occ ) { vec3 ref = reflect(rd,nor); // lighting float sky = clamp(nor.y,0.0,1.0); float bou = clamp(-nor.y,0.0,1.0); float dif = max(dot(nor,lig),0.0); float bac = max(0.3 + 0.7*dot(nor,-vec3(lig.x,0.0,lig.z)),0.0); float sha = 1.0-shadows; if( (shadows*dif)>0.001 ) sha=softshadow( pos+0.01*nor, lig, 0.0005, 32.0 ); float fre = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 5.0 ); float spe = max( 0.0, pow( clamp( dot(lig,ref), 0.0, 1.0), 0.01+glossy ) ) * glossy; float sss = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 3.0 ); // lights vec3 brdf = vec3(0.0); brdf += 8.0*dif*vec3(1.80,1.35,0.90)*vec3(sha,sha*0.5+0.5*sha*sha,sha*sha); brdf += 1.0*sky*vec3(0.20,0.40,0.55)*occ; brdf += 1.0*bac*vec3(0.40,0.60,0.70)*occ; brdf += 1.0*bou*vec3(0.10,0.20,0.25); brdf += 1.0*sss*vec3(0.40,0.40,0.40)*(0.3+0.7*dif*sha)*glossy*occ; brdf += 0.5*spe*vec3(1.3,1.0,0.8)*sha*(0.3+0.7*fre)*occ*glossy; brdf += glossy*0.3*vec3(0.8,0.9,1.0)*occ*smoothstep( 0.0, 0.2, ref.y )*(0.5+0.5*smoothstep( 0.0, 1.0, ref.y ));//*smoothstep(-0.1,0.0,dif); col = col*brdf; col += (0.5 + 1.5*fre)*occ*glossy2*glossy2*10.0*vec3(1.0,0.9,0.8)*smoothstep( 0.0, 0.2, ref.y )*(0.5+0.5*smoothstep( 0.0, 1.0, ref.y ));//*smoothstep(-0.1,0.0,dif); col += 0.25*glossy*pow(spe/(0.01+glossy),8.0)*vec3(1.3,1.0,0.8)*sha*(0.3+0.7*fre)*occ; return col; } vec3 render(vec3 ro, vec3 rd) { float t = 1000.0; vec3 col = vec3(0.0); vec3 bgcol = vec3(0.6,0.7,0.8) - .2*clamp(rd.y,0.0,1.0); // quick step till y=3 bounding plane float pt = (3.0-ro.y)/rd.y; if( rd.y<0.0 && pt>0.0 ) ro=ro+rd*pt; // raymarch vec2 tmat1 = intersectDolphin(ro,rd); vec3 posy = vec3(-100000.0); if( tmat1.x>0.0 ) { vec2 tmat = tmat1; t = tmat.x; // geometry vec3 pos = ro + tmat.x*rd; vec3 nor = calcNormalFish(pos); vec3 ref = reflect( rd, nor ); vec3 fpos = pos - fishPos; vec3 auu = normalize( vec3(-ccd.z,0.0,ccd.x) ); vec3 avv = normalize( cross(ccd,auu) ); vec3 ppp = vec3( dot(fpos-ccp,auu), dot(fpos-ccp,avv), tmat.y ); vec2 uv = vec2( 1.0*atan(ppp.x,ppp.y)/3.1416, 4.0*ppp.z ); vec3 bnor = -1.0+2.0*vec3(noise(uv), noise(uv.yx), noise(uv.xx)); nor += 0.01*bnor; vec3 te = vec3(0); vec4 mate; mate.w = 17.0; mate.xyz = mix( vec3(0.3,0.35,0.4), vec3(0.8,0.85,0.9)*0.9, 0.8*smoothstep(-0.05,0.05,ppp.y) );; mate.xyz *= 1.0 + 0.3*te; mate.xyz *= smoothstep( 0.0, 0.06, distance(vec3(abs(ppp.x),ppp.yz)*vec3(1.0,1.0,4.0),vec3(0.35,0.0,0.4)) ); mate.xyz *= 1.0 - 0.75*(1.0-smoothstep( 0.0, 0.02, abs(ppp.y) ))*(1.0-smoothstep( 0.07, 0.11, tmat.y )); mate.xyz *= 0.1*0.23; // surface-light interacion col = doLighting( pos, nor, rd, mate.w, 0.0, 0.0, mate.xyz, 1.0 ); posy = pos; } else { discard; } return col; } vec3 getProceduralColor() { //----------------------------------------------------- // animate //----------------------------------------------------- fishTime = 0.6 + 2.0*iGlobalTime - 20.0; fishPos = vec3( 0.0, 0.0-0.2, -1.1*fishTime ); isJump = 0.5 + 0.5*cos( -0.4+0.5*fishTime); isJump2 = 0.5 + 0.5*cos( 0.6+0.5*fishTime); vec3 worldEye = getEyeWorldPos(); // this will make it movable, scalable, and rotatable vec3 ro = _position.xyz; vec3 eye = (inverse(iWorldOrientation) * (worldEye - iWorldPosition)) / iWorldScale; // vec3 ro = iWorldOrientation * (_position.xyz * iWorldScale) + iWorldPosition; // world position of the current fragment // vec3 eye = worldEye; ro.x *= 3.1364; ro.y *= 4.5461; ro.z *= 5.9707; ro.x += -0.0170; ro.y += 1.0948; ro.z += 2.7953; eye.x *= 3.1364; eye.y *= 4.5461; eye.z *= 5.9707; eye.x += -0.0170; eye.y += 1.0948; eye.z += 2.7953; ro += fishPos; eye += fishPos; vec3 rd = normalize(ro - eye); // ray from camera eye to ro vec3 col = render(ro, rd); // gamma col = pow( clamp(col,0.0,1.0), vec3(0.45) ); // color col = col*vec3(0.9,0.85,0.8) + 0.4*col*col*(3.0-2.0*col); return col; } float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { vec3 color = getProceduralColor(); diffuse = color.rgb; specular = color.rgb; shininess = 0.5; return 1.0; }