Back to shaders

Shader test bench

SimplePS

shadered-examples generative glsl runnable fragment MIT
Source
runnable fragment

Complete GLSL fragment shader. Stronghold runs it directly when the browser can compile it.

Code

precision mediump float;

#define outColor gl_FragColor

uniform vec2 iResolution;
uniform vec2 iMouse;
uniform float iTime;

#define ROTATE false   
#define flag true

//---------------------------------------------------------
vec3 rotateX(vec3 p, float a)
{
  float sa = sin(a);
  float ca = cos(a);
  return vec3(p.x, ca * p.y - sa * p.z, sa * p.y + ca * p.z);
}
vec3 rotateY(vec3 p, float a)
{
  float sa = sin(a);
  float ca = cos(a);
  return vec3(ca * p.x + sa * p.z, p.y, -sa * p.x + ca * p.z);
}
vec3 rotateZ(vec3 p, float a)
{
  float sa = sin(a);
  float ca = cos(a);
  return vec3(ca * p.x - sa * p.y, sa * p.x + ca * p.y, p.z);
}

float length2( vec2 p )  // sqrt(x^2+y^2) 
{
  return sqrt( p.x*p.x + p.y*p.y );
}

float length6( vec2 p )  // (x^6+y^6)^(1/6)
{
  p = p*p*p; 
  p = p*p;
  return pow( p.x + p.y, 1.0/6.0 );
}

float length8( vec2 p )  // (x^8+y^8)^(1/8)
{
  p = p*p; 
  p = p*p; 
  p = p*p;
  return pow( p.x + p.y, 1.0/8.0 );
}

//---------------------------------------------------------
//  primitives
//---------------------------------------------------------
float sdPlane( vec3 p )
{
  return p.y;
}

float sdSphere( vec3 p, float radius )
{
  return length(p) - radius;
}

float sdWaveSphere(vec3 p, float radius, int waves, float waveSize) 
{	// deformation of radius
	float d = waveSize*(radius-length(p.y));
	radius += d*cos(atan(p.x,p.z)*float(waves));
	return length(p) - radius;
}

float sdBox( vec3 p, vec3 b )
{
  vec3 d = abs(p) - b;
  return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
}

float udRoundBox( vec3 p, vec3 b, float r )
{
  return length(max(abs(p)-b, 0.0))-r;
}

// t.x = torus radius,  t.y = ring radius
float sdTorus( vec3 p, vec2 t )
{
  return length(vec2(length(p.xz)-t.x, p.y)) - t.y;
}

float sdTorus82( vec3 p, vec2 t )
{
  vec2 q = vec2(length2(p.xz)-t.x, p.y);
  return length8(q) - t.y;
}

float sdTorus88( vec3 p, vec2 t )
{
  vec2 q = vec2(length8(p.xz)-t.x, p.y);
  return length8(q)-t.y;
}

float sdBlob (vec3 pos, float r)
{
  vec3 v1 = pos * 6.0;
  return 0.05*(r + 0.5* (length(dot(v1, v1)) -0.51*(cos(4.*v1.x) +cos(4.*v1.y) +cos(4.*v1.z))));
}

// Capsule:  a,b = end points, r = cylinder radius
float sdCapsule( vec3 p, vec3 a, vec3 b, float r )
{
  vec3 pa = p-a, ba = b-a;
  float h = clamp( dot(pa, ba)/dot(ba, ba), 0.0, 1.0 );
  return length( pa - ba*h ) - r;
}

// Triangle prism: 
float sdTriPrism( vec3 p, float radius, float height )
{
  vec3 q = abs(p);
  #ifdef flag
    return max(q.z-height, max(q.x*0.866025 +p.y*0.5, -p.y) - radius*0.5);
  #else
    float d1 = q.z-height;
    float d2 = max(q.x*0.866025+p.y*0.5, -p.y) - radius*0.5;
    return length(max(vec2(d1, d2), 0.0)) + min(max(d1, d2), 0.0);
  #endif
}

// hexagonal prism:r 
float sdHexPrism( vec3 p, float radius, float height)
{
  vec3 q = abs(p);
  #ifdef flag
    return max(q.z-height, max((q.x*0.866025 +q.y*0.5), q.y) - radius);
  #else
    float d1 = q.z-heighty;
    float d2 = max((q.x*0.866025 +q.y*0.5), q.y)-radius;
    return length(max(vec2(d1, d2), 0.0)) + min(max(d1, d2), 0.);
  #endif
}

float sdCylinder( vec3 p, vec2 h )
{
  vec2 d = abs(vec2(length(p.xz), p.y)) - h;
  return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}

float sdCylinder( vec3 p, vec3 h )
{
  return length(p.xz - h.xy) - h.z;
}
// h.xy = base rectangle size,  h.z = height
float sdCylinder6( vec3 p, vec3 h )
{
  return max( length6(p.xz) - h.x, abs(p.y) - h.z );
}

float sdCone( in vec3 p, in vec3 c )
{
  vec2 q = vec2( length(p.xz), p.y );
  #if 0
    return max( max( dot(q, c.xy), p.y), -p.y -c.z );
  #else
    float d1 = -p.y - c.z;
    float d2 = max( dot(q, c.xy), p.y);
    return length(max(vec2(d1, d2), 0.0)) + min(max(d1, d2), 0.);
  #endif
}

//----------------------------------------------------------------------
// distance operations
//----------------------------------------------------------------------

// Substraction: d1 -d2
float opS( float d1, float d2 )
{
  return max(-d2, d1);
}

// Union: d1 +d2
vec2 opU( vec2 d1, vec2 d2 )
{
  return (d1.x < d2.x) ? d1 : d2;
}

//----------------------------------------------------------------------
// domain operations
//----------------------------------------------------------------------

// Repetition: 
vec3 opRep( vec3 p, vec3 c )
{
  return mod(p, c)-0.5*c;
}

// Twist: 
vec3 opTwist( vec3 p, float angle )
{
  float  c = cos(10.0*p.y + angle);
  float  s = sin(10.0*p.y + angle);
  mat2   m = mat2(c, -s, s, c);
  return vec3(m*p.xz, p.y);
}

//----------------------------------------------------------------------
// sphere cutted out from a rounded box
//----------------------------------------------------------------------
float sdBoxMinusSphere( vec3 pos, float radius )
{
  return opS( udRoundBox( pos, vec3(0.15), 0.05)
            , sdSphere(   pos, radius - 0.012 + 0.02*sin(iTime)));
}
//----------------------------------------------------------------------
// rack-wheel with holes
//----------------------------------------------------------------------
float sdRackWheel( vec3 pos)
{
  return opS(sdTorus82(  pos-vec3(-2.0, 0.2, 0.0), vec2(0.20, 0.1)), 
             sdCylinder( opRep( vec3(atan(pos.x+2.0, pos.z)/6.2831 + 0.1*iTime, 
                                     pos.y, 
                                     0.02+0.5*length(pos-vec3(-2.0, 0.2, 0.0))), 
                                vec3(0.05, 1.0, 0.05)
							   )
                          , vec2(0.02, 0.6)
			           )
		    );
}
//----------------------------------------------------------------------
float sdBallyBall( vec3 pos)
{
  return 0.7 * sdSphere(pos, 0.2 ) 
         + 0.03*sin(50.0*pos.x)*sin(50.0*pos.y+8.0*iTime)*sin(50.0*pos.z);
}
//----------------------------------------------------------------------
float sdTwistedTorus( vec3 pos, float angle)
{
  return 0.5*sdTorus( opTwist(pos,angle), vec2(0.20, 0.05));
}
//----------------------------------------------------------------------
vec2 map( vec3 pos )
{
  vec3 r1, r2;
  float sphy = 0.35 + 0.1 * sin(iTime);
  vec3 sp = pos - vec3( 1.0, sphy, 0.0);
  vec2 res = vec2( sdPlane(     pos), 1.0 ); 
  res = opU( res, vec2( sdSphere(    sp, 0.25 ), 46.9 ) );
  res = opU( res, vec2( sdBlob(      pos-vec3( 0.0, 0.25, 0.0), -0.5 - 0.45*sin(iTime) ), 246.9 ) );

  res = opU( res, vec2( sdBox(       pos-vec3( 1.0, 0.25, 0.0), vec3(0.20) ), 3.0 ) );
  res = opU( res, vec2( udRoundBox(  pos-vec3( 1.0, 0.25, 1.0), vec3(0.12), 0.1 ), 41.0 ) );
                                     r1 = rotateX (pos - vec3( 0.0, 0.25, 1.0), sin(iTime)*0.3);
                                     r1 = rotateY (r1, iTime*2.0);
  res = opU( res, vec2( sdTorus(     r1, vec2(0.20, 0.05) ), 25.0 ) );
                                     r1 = vec3(-1.0, 0.2, 0.0) + rotateY (vec3(-0.15, 0.0, -0.15), iTime);
                                     r2 = vec3(-1.0, 0.2, 0.0) + rotateY (vec3(-0.15, 0.0, +0.15), iTime);
  res = opU( res, vec2( sdCapsule(   pos, r1, r2, 0.1  ), 31.9 ) );
  res = opU( res, vec2( sdTriPrism(  pos-vec3(-1.0, 0.25, -1.0), 0.1*sin(iTime) + 0.25, 0.05 ), 43.5 ) );
                                     float h1 = 0.2 + 0.06 * sin(iTime);
  res = opU( res, vec2( sdCylinder(  pos-vec3( 1.0, 0.30, -1.0), vec2(0.1, h1) ), 8.0 ) );
  res = opU( res, vec2( sdCone(      pos-vec3( 0.0, 0.50, -1.0), vec3(0.8, 0.5+0.1*sin(iTime), 0.3) ), 55.0 ) );
  res = opU( res, vec2( sdTorus82(   pos-vec3( 0.0, 0.25, 2.0), vec2(0.20, 0.05) ), 50.0 ) );
                                     r1 = rotateY (pos - vec3(-1.0, 0.25, 2.0), iTime*0.25);
  res = opU( res, vec2( sdTorus88(   r1, vec2(0.20, 0.05) ), 43.0 ) );
                                     r1 = rotateY (pos - vec3(1.0, 0.30, 2.0), iTime*0.25);
  res = opU( res, vec2( sdCylinder6( r1, vec3(0.1, 0.05, 0.25) ), 12.0 ) );
                                     r1 = rotateX (pos - vec3(-1.0, 0.25, 1.0), iTime*0.5);
  res = opU( res, vec2( sdHexPrism(  r1, 0.25, 0.05 ), 17.0 ) );
  res = opU( res, vec2( sdBoxMinusSphere(pos - vec3(-2.0, 0.2, 1.0), 0.25), 13.0 ) );
  res = opU( res, vec2( sdRackWheel   ( pos ), 51.0 ) );
  res = opU( res, vec2( sdTwistedTorus( pos - vec3(-2.0, 0.25, 2.0), 6.0*sin(iTime) ), 46.7 ) );
  res = opU( res, vec2( sdWaveSphere  ( pos - vec3(-2.0, 0.25, -1.0), 0.2 , 10, sin(iTime)*0.2), 880 ) );
// res = opU( res, vec2( sdBallyBall   ( pos - vec3(-2.0, 0.25, -1.0)), 65.0 ) );
  return res;
}

//----------------------------------------------------------------------
vec2 castRay( vec3 ro, vec3 rd )
{
  float tmin = 1.0;
  float tmax = 20.0;

  #if 0
    float tp1 = (0.0-ro.y) / rd.y; 
    if ( tp1>0.0 ) 
	  tmax = min( tmax, tp1 );
    float tp2 = (1.6-ro.y)/rd.y; 
    if ( tp2>0.0 ) 
    { 
      if ( ro.y>1.6 ) tmin = max( tmin, tp2 );
      else            tmax = min( tmax, tp2 );
    }
  #endif

  float precis = 0.002;
  float t = tmin;
  float m = -1.0;
  for ( int i=0; i<50; i++ )
  {
    vec2 res = map( ro+rd*t );
    if ( res.x<precis || t>tmax ) break;
    t += res.x;
    m = res.y;
  }

  if ( t>tmax ) m=-1.0;
  return vec2( t, m );
}

//----------------------------------------------------------------------
float softshadow( vec3 ro, vec3 rd, float mint, float tmax )
{
  float res = 1.0;
  float t = mint;
  for ( int i=0; i<16; i++ )
  {
    float h = map( ro + rd*t ).x;
    res = min( res, 8.0*h/t );
    t += clamp( h, 0.02, 0.10 );
    if ( h<0.001 || t>tmax ) break;
  }
  return clamp( res, 0.0, 1.0 );
}

//----------------------------------------------------------------------
vec3 calcNormal( vec3 pos )
{
  vec3 eps = vec3( 0.001, 0.0, 0.0 );
  vec3 nor = 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 );
  return normalize(nor);
}

//----------------------------------------------------------------------
float calcAO( vec3 pos, vec3 nor )
{
  float occ = 0.0;
  float sca = 1.0;
  for ( int i=0; i<5; i++ )
  {
    float hr = 0.01 + 0.12*float(i)/4.0;
    vec3 aopos =  nor * hr + pos;
    float dd = map( aopos ).x;
    occ += -(dd-hr)*sca;
    sca *= 0.95;
  }
  return clamp( 1.0 - 3.0*occ, 0.0, 1.0 );
}
//---------------------------------------------------------
vec3 render( vec3 ro, vec3 rd )
{ 
  vec3 col = vec3(0.8, 0.9, 1.0);
  vec2 res = castRay(ro, rd);
  float t = res.x;
  float m = res.y;
  if ( m>-0.5 )
  {
    vec3 pos = ro + t*rd;
    vec3 nor = calcNormal( pos );
    vec3 ref = reflect( rd, nor );

    // material        
    col = 0.45 + 0.3*sin( vec3(0.05, 0.08, 0.10)*(m-1.0) );

    if ( m<1.5 )
    {
      float f = mod( floor(5.0*pos.z) + floor(5.0*pos.x), 2.0);
      col = 0.4 + 0.1*f*vec3(1.0);
    }

    // lighting        
    float occ = calcAO( pos, nor );
    vec3  lig = normalize( vec3(-0.6, 0.7, -0.5) );
    float amb = clamp( 0.5+0.5*nor.y, 0.0, 1.0 );
    float dif = clamp( dot( nor, lig ), 0.0, 1.0 );
    float bac = clamp( dot( nor, normalize(vec3(-lig.x, 0.0, -lig.z))), 0.0, 1.0 )*clamp( 1.0-pos.y, 0.0, 1.0);
    float dom = smoothstep( -0.1, 0.1, ref.y );
    float fre = pow( clamp(1.0+dot(nor, rd), 0.0, 1.0), 2.0 );
    float spe = pow(clamp( dot( ref, lig ), 0.0, 1.0 ), 16.0);

    dif *= softshadow( pos, lig, 0.02, 2.5 );
    dom *= softshadow( pos, ref, 0.02, 2.5 );

    vec3 brdf = vec3(0.0);
    brdf += 1.20*dif*vec3(1.00, 0.90, 0.60);
    brdf += 1.20*spe*vec3(1.00, 0.90, 0.60)*dif;
    brdf += 0.30*amb*vec3(0.50, 0.70, 1.00)*occ;
    brdf += 0.40*dom*vec3(0.50, 0.70, 1.00)*occ;
    brdf += 0.30*bac*vec3(0.25, 0.25, 0.25)*occ;
    brdf += 0.40*fre*vec3(1.00, 1.00, 1.00)*occ;
    brdf += 0.02;
    col = col*brdf;
    col = mix( col, vec3(0.8, 0.9, 1.0), 1.0-exp( -0.005*t*t ) );
  }
  return vec3( clamp(col, 0.0, 1.0) );
}
//---------------------------------------------------------
void main( )
{
  vec2 p = 2.0*(gl_FragCoord.xy / iResolution.xy) - 1.0;
  p.x *= iResolution.x / iResolution.y;
  vec2 mo = iMouse.xy;

  // camera  
  float angle = ROTATE ? 0.1*iTime : 0.0;
  float rx = -0.5 + 3.2*cos(angle + 6.0*mo.x);
  float rz =  0.5 + 3.2*sin(angle + 6.0*mo.x);
  vec3 ro = vec3( rx, 1.0 + 2.0*mo.y, rz );
  vec3 ta = vec3( -0.5, -0.4, 0.5 );

  // camera tx
  vec3 cw = normalize( ta-ro );
  vec3 cp = vec3( 0.0, 1.0, 0.0 );
  vec3 cu = normalize( cross(cw, cp) );
  vec3 cv = normalize( cross(cu, cw) );
  vec3 rd = normalize( p.x*cu + p.y*cv + 2.5*cw );

  // pixel color
  vec3 col = render( ro, rd );
  col = pow( col, vec3(0.4545) );
  outColor=vec4( col, 1.0 );
}