391 lines
No EOL
12 KiB
GLSL
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;
|
|
} |