content/hifi-content/samuel/mike.fs
2022-02-14 02:04:11 +01:00

391 lines
No EOL
12 KiB
GLSL

// Credit to iq: https://www.shadertoy.com/view/MsXGWr
//
// Created by Sam Gondelman on 6/10/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)*158.5453123);
}
float noise( in float x )
{
float p = floor(x);
float f = fract(x);
f = f*f*(3.0-2.0*f);
return mix( hash(p+0.0), hash(p+1.0),f);
}
float noise( in vec2 x )
{
vec2 p = floor(x);
vec2 f = fract(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*157.0;
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);
}
const mat2 m2 = mat2( 0.80, -0.60, 0.60, 0.80 );
float fbm( vec2 p )
{
float f = 0.0;
f += 0.5000*noise( p ); p = m2*p*2.02;
f += 0.2500*noise( p ); p = m2*p*2.03;
f += 0.1250*noise( p ); p = m2*p*2.01;
f += 0.0625*noise( p );
return f/0.9375;
}
//----------------------------------------------------------------
vec2 sdSegment( vec3 a, vec3 b, vec3 p )
{
vec3 pa = p-a, ba = b-a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return vec2( length( pa - ba*h ), h );
}
bool gUseMin;
float smin( float a, float b )
{
if( gUseMin ) return min(a,b);
float k = 0.06;
float h = clamp( 0.5 + 0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
float opS( float d1, float d2 )
{
return max(-d1,d2);
}
vec2 map( vec3 p )
{
p.y -= 1.8;
p.x = abs(p.x);
vec3 q = p;
q.y -= 0.3*pow(1.0-length(p.xz),1.0)*smoothstep(0.0, 0.2, p.y);
q.y *= 1.05;
q.z *= 1.0 + 0.1*smoothstep( 0.0, 0.5, q.z )*smoothstep( -0.5, 0.5, p.y );
float dd = length( (p - vec3(0.0,0.65,0.8))*vec3(1.0,0.75,1.0) );
float am = clamp( 4.0*abs(p.y-0.45), 0.0, 1.0 );
float fo = -0.03*(1.0-smoothstep( 0.0, 0.04*am, abs(dd-0.42) ))*am;
float dd2 = length( (p - vec3(0.0,0.65,0.8))*vec3(1.0,0.25,1.0) );
float am2 = clamp( 1.5*(p.y-0.45), 0.0, 1.0 );
float fo2 = -0.085*(1.0-smoothstep( 0.0, 0.08*am2, abs(dd2-0.42) ))*am2;
q.y += -0.05+0.05*length(q.x);
float d1 = length( q ) - 0.9 + fo + fo2;
vec2 res = vec2( d1, 1.0 );
// arms
vec2 h = sdSegment( vec3(.83,0.15,0.0), vec3(1.02,-0.6,-.1), p );
float d2 = h.x - 0.07;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(1.02,-0.6,-.1), vec3(0.95,-1.2,0.1), p );
d2 = h.x - 0.07 + h.y*0.02;
res.x = smin( res.x, d2 );
// hands
if( p.y<-1.0 )
{
float fa = sin(3.0*iGlobalTime);
h = sdSegment( vec3(0.95,-1.2,0.1), vec3(0.97,-1.5,0.0), p );
d2 = h.x - 0.03;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.97,-1.5,0.0), vec3(0.95,-1.7,0.0)-0.01*fa, p );
d2 = h.x - 0.03 + 0.01*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.95,-1.2,0.1), vec3(1.05,-1.5,0.1), p );
d2 = h.x - 0.03;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(1.05,-1.5,0.1), vec3(1.0,-1.75,0.1)-0.01*fa, p );
d2 = h.x - 0.03 + 0.01*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.95,-1.2,0.1), vec3(0.98,-1.5,0.2), p );
d2 = h.x - 0.03;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.98,-1.5,0.2), vec3(0.95,-1.7,0.15)-0.01*fa, p );
d2 = h.x - 0.03 + 0.01*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.95,-1.2,0.1), vec3(0.85,-1.4,0.2), p );
d2 = h.x - 0.04 + 0.01*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.85,-1.4,0.2), vec3(0.85,-1.63,0.15)+0.01*fa, p );
d2 = h.x - 0.03 + 0.01*h.y;
res.x = smin( res.x, d2 );
}
// legs
if( p.y<0.0 )
{
h = sdSegment( vec3(0.5,-0.5,0.0), vec3(0.6,-1.2,0.1), p );
d2 = h.x - 0.14 + h.y*0.08;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.6,-1.2,0.1), vec3(0.5,-1.8,0.0), p );
d2 = h.x - 0.06;
res.x = smin( res.x, d2 );
}
// feet
if( p.y<-1.5 )
{
h = sdSegment( vec3(0.5,-1.8,0.0), vec3(0.6,-1.8,0.4), p );
d2 = h.x - 0.09 + 0.02*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.5,-1.8,0.0), vec3(0.77,-1.8,0.35), p );
d2 = h.x - 0.08 + 0.02*h.y;
res.x = smin( res.x, d2 );
h = sdSegment( vec3(0.5,-1.8,0.0), vec3(0.9,-1.8,0.2), p );
d2 = h.x - 0.07 + 0.02*h.y;
res.x = smin( res.x, d2 );
}
// horns
vec3 hp = p - vec3(0.0,0.8,0.0);
float hh = -2.5*hp.x*hp.x;
float co = cos(hh);
float si = sin(hh);
hp.xy = mat2(co,si,-si,co)*hp.xy;
float d4 = length( hp*vec3(0.3,1.0,1.0) ) - 0.19;
d4 *= 0.5;
if( d4<res.x ) res = vec2( d4, 3.0 );
// eyes
float d3 = length( (p - vec3(0.0,0.25,0.35))*vec3(1.0,0.8,1.0) ) - 0.5;
if( d3<res.x ) res = vec2( d3, 2.0 );
// mouth
float mo = length( (q-vec3(0.0,-0.35,1.0))*vec3(1.0,1.2,0.25)/1.2 ) -0.3/1.2;
float of = 0.1*pow(smoothstep( 0.0, 0.2, abs(p.x-0.3) ),0.5);
mo = max( mo, -q.y-0.35-of );
float li = smoothstep( 0.0, 0.05, mo+0.02 ) - smoothstep( 0.05, 0.10, mo+0.02 );
res.x -= 0.03*li*clamp( (-q.y-0.4)*10.0, 0.0, 1.0 );
if( -mo > res.x )
res = vec2( -mo, 4.0 );
res.x += 0.01*(smoothstep( 0.0, 0.05, mo+0.062 ) - smoothstep( 0.05, 0.10, mo+0.062 ));
// teeth
if( p.x<0.3 )
{
p.x = mod( p.x, 0.16 )-0.08;
float d5 = length( (p-vec3(0.0,-0.37,0.65))*vec3(1.0,2.0,1.0))-0.08;
if( d5<res.x )
res = vec2( d5, 2.0 );
}
return vec2(res.x*0.8,res.y);
}
vec3 calcNormal( in vec3 pos )
{
vec3 eps = vec3(0.002,0.0,0.0);
return normalize( vec3(
map(pos+eps.xyy).x - map(pos-eps.xyy).x,
map(pos+eps.yxy).x - map(pos-eps.yxy).x,
map(pos+eps.yyx).x - map(pos-eps.yyx).x ) );
}
vec3 intersect( in vec3 ro, in vec3 rd )
{
float m = -1.0;
float mint = 20.0;
// mike
float maxd = min(20.0,mint);
float precis = 0.001;
float h = precis*2.0;
float t = 0.0;
float d = 0.0;
for( int i=0; i<80; i++ )
{
if( h<precis||t>maxd ) break;
t += h;
vec2 res = map( ro+rd*t );
h = res.x;
d = res.y;
}
if( t<maxd && t<mint )
{
mint = t;
m = d;
}
return vec3( mint, m, m );
}
vec3 lig = normalize(vec3(1.0,0.7,0.9));
vec4 render(vec3 ro, vec3 rd) {
vec3 col = vec3(1.0);
float an = 0.0;
// raymarch
vec3 tmat = intersect(ro,rd);
if( tmat.z>-0.5 )
{
// geometry
vec3 pos = ro + tmat.x*rd;
vec3 nor = calcNormal(pos);
vec3 ref = reflect( rd, nor );
// materials
vec4 mate = vec4(0.0);
vec2 mate2 = vec2(1.0,1.0);
if( tmat.z<0.5 )
{
nor = vec3(0.0,1.0,0.0);
ref = reflect( rd, nor );
mate.xyz = vec3(1.0);
mate2.y = 1.0 - 0.9*(2.0/(2.0+dot(pos.xz,pos.xz)));
}
else if( tmat.z<1.5 )
{
mate2.x = 4.0;
mate = vec4(0.16,0.32,0.0,0.8);
float f = noise(0.15*pos.xz + vec2(5.0, 5.0)) * noise(0.05*pos.xz + vec2(5.0, 5.0));
mate.xyz = mix( 0.8*mate.xyz, vec3(0.3,0.4,0.0), f );
f = noise(pos.yx + vec2(5.0, 5.0)) * noise(0.25*pos.yx + vec2(5.0, 5.0));
f = f*f;
mate.xyz = mix( mate.xyz, vec3(0.3,0.4,0.0), 0.6*f );
vec3 p2 = (pos + vec3(100))*100.0;
vec3 bnor = -1.0+2.0*vec3(noise(p2.xz), noise(p2.xy), noise(p2.zx));
nor = normalize( nor + 0.15*bnor );
mate.xyz *= 0.7;
}
else if( tmat.z<2.5 )
{
vec3 q = pos-vec3(0.0,1.8,0.0) - vec3(0.0,0.44,0.35);
float an2 = an + 0.5*(-1.0+2.0*noise( 2.0*iGlobalTime ));
vec3 oq = q;
q.x += -2.0*0.15*clamp(sin(an2),-0.42,0.42);
float f = length( q.xy );
mate2.y = 1.0-0.3*smoothstep(0.24,0.35,length( oq.xy-vec2(0.0,0.035) ));
mate = vec4(0.5,0.5,0.5,1.0);
mate.xyz = mix( mate.xyz, vec3(0.6,0.4,0.3), 0.5*smoothstep(0.1,0.4,f) );
vec3 c1 = vec3(0.0,0.15,0.05)*(1.0-0.85*f/0.19);
float a = atan(q.y,q.x);
c1 *= 0.3 + 5.0*fbm( 20.0*vec2(0.3*a,1.0*f) );
mate.xyz = mix( mate.xyz, c1, 1.0-smoothstep( 0.18, 0.19, f ) );
oq.x += -2.0*0.19*clamp(sin(an2),-0.42,0.42);
f = length( oq.xy );
mate.xyz *= smoothstep( 0.07, 0.10, f );
mate.w = 2.0;
mate2.x = 32.0;
}
else if( tmat.z<3.5 )
{
mate = 0.8*vec4(0.85,0.7,0.6,0.0);
mate2.x = 0.0;
float f = smoothstep( 0.0, 0.1, 0.5*abs(pos.x)+pos.y-3.02 );
mate.xyz *= 1.0 - 0.8*vec3( f );
mate.xyz *= 0.2 + 0.8*smoothstep( 0.0, 1.0, noise(0.21*pos*vec3(4.0,0.1,4.0)));
}
else if( tmat.z<4.5 )
{
float z = smoothstep( 0.0, 2.0, pos.z+0.5 );
mate = 0.5*vec4(0.5,0.25,0.1,0.0);
mate.x += 0.1*(1.0-z);
mate2.y = z;
}
// lighting
float occ = (0.5 + 0.5*nor.y)*mate2.y;
float amb = 0.5;
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,-lig),0.0);
float sha = 1.0;
float fre = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 2.0 );
float spe = max( 0.0, pow( clamp( dot(lig,reflect(rd,nor)), 0.0, 1.0), mate2.x ) );
// lights
vec3 lin = vec3(0.0);
lin += 2.0*dif*vec3(1.00,1.00,1.00)*pow(vec3(sha),vec3(1.0,1.2,1.5));
lin += 1.0*amb*vec3(0.30,0.30,0.30)*occ;
lin += 2.0*bou*vec3(0.40,0.40,0.40)*mate2.y;
lin += 4.0*bac*vec3(0.40,0.30,0.25)*occ;
lin += 1.0*fre*vec3(1.00,1.00,1.00)*2.0*mate.w*(0.5+0.5*dif*sha)*occ;
lin += 1.0*spe*vec3(1.0)*occ*mate.w*dif*sha;
// surface-light interacion
col = mate.xyz* lin + vec3(0.3)*mate.w*pow(spe,2.0)*sha;
} else {
discard;
}
return vec4(clamp(col, 0.0, 1.0), 1.0);
}
vec4 getProceduralColor() {
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 *= 2.2369;
ro.y *= 3.1679;
ro.z *= 1.8474;
ro.x += 0.0071;
ro.y += 1.4565;
ro.z += -0.0283;
eye.x *= 2.2369;
eye.y *= 3.1679;
eye.z *= 1.8474;
eye.x += 0.0071;
eye.y += 1.4565;
eye.z += -0.0283;
vec3 rd = normalize(ro - eye); // ray from camera eye to ro
vec4 col = render(eye, rd);
return pow(clamp(col,0.0,1.0), vec3(0.45));
}
float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) {
vec4 color = getProceduralColor();
diffuse = color.rgb;
specular = color.rgb;
shininess = 0.0;
return 1.0;
}