265 lines
No EOL
7.3 KiB
GLSL
265 lines
No EOL
7.3 KiB
GLSL
// Credit to iq: https://www.shadertoy.com/view/XdjXWK
|
|
//
|
|
// 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
|
|
//
|
|
|
|
#define NUMPASES 1
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
// sphere related functions
|
|
//-------------------------------------------------------------------------------------------
|
|
|
|
vec3 sphNormal( in vec3 pos, in vec4 sph )
|
|
{
|
|
return normalize(pos-sph.xyz);
|
|
}
|
|
|
|
float sphIntersect( in vec3 ro, in vec3 rd, in vec4 sph )
|
|
{
|
|
vec3 oc = ro - sph.xyz;
|
|
float b = dot( oc, rd );
|
|
float c = dot( oc, oc ) - sph.w*sph.w;
|
|
float h = b*b - c;
|
|
if( h<0.0 ) return -1.0;
|
|
return -b - sqrt( h );
|
|
}
|
|
|
|
float sphShadow( in vec3 ro, in vec3 rd, in vec4 sph )
|
|
{
|
|
vec3 oc = ro - sph.xyz;
|
|
float b = dot( oc, rd );
|
|
float c = dot( oc, oc ) - sph.w*sph.w;
|
|
return step( min( -b, min( c, b*b - c ) ), 0.0 );
|
|
}
|
|
|
|
vec2 sphDistances( in vec3 ro, in vec3 rd, in vec4 sph )
|
|
{
|
|
vec3 oc = ro - sph.xyz;
|
|
float b = dot( oc, rd );
|
|
float c = dot( oc, oc ) - sph.w*sph.w;
|
|
float h = b*b - c;
|
|
float d = sqrt( max(0.0,sph.w*sph.w-h)) - sph.w;
|
|
return vec2( d, -b-sqrt(max(h,0.0)) );
|
|
}
|
|
|
|
float sphSoftShadow( in vec3 ro, in vec3 rd, in vec4 sph )
|
|
{
|
|
float s = 1.0;
|
|
vec2 r = sphDistances( ro, rd, sph );
|
|
if( r.y>0.0 )
|
|
s = max(r.x,0.0)/r.y;
|
|
return s;
|
|
}
|
|
|
|
float sphOcclusion( in vec3 pos, in vec3 nor, in vec4 sph )
|
|
{
|
|
vec3 r = sph.xyz - pos;
|
|
float l = length(r);
|
|
float d = dot(nor,r);
|
|
float res = d;
|
|
|
|
if( d<sph.w ) res = pow(clamp((d+sph.w)/(2.0*sph.w),0.0,1.0),1.5)*sph.w;
|
|
|
|
return clamp( res*(sph.w*sph.w)/(l*l*l), 0.0, 1.0 );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
// rendering functions
|
|
//-------------------------------------------------------------------------------------------
|
|
|
|
#define NUMSPHEREES 16
|
|
|
|
vec4 sphere[NUMSPHEREES];
|
|
|
|
float shadow( in vec3 ro, in vec3 rd )
|
|
{
|
|
float res = 1.0;
|
|
for( int i=0; i<NUMSPHEREES; i++ )
|
|
res = min( res, 8.0*sphSoftShadow(ro,rd,sphere[i]) );
|
|
return res;
|
|
}
|
|
|
|
float occlusion( in vec3 pos, in vec3 nor )
|
|
{
|
|
float res = 1.0;
|
|
for( int i=0; i<NUMSPHEREES; i++ )
|
|
res *= 1.0 - sphOcclusion( pos, nor, sphere[i] );
|
|
return res;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
// utlity functions
|
|
//-------------------------------------------------------------------------------------------
|
|
|
|
|
|
vec3 hash3( float n ) { return fract(sin(vec3(n,n+1.0,n+2.0))*43758.5453123); }
|
|
vec3 textureBox( sampler2D sam, in vec3 pos, in vec3 nor )
|
|
{
|
|
vec3 w = abs(nor);
|
|
return (w.x*texture( sam, pos.yz ).xyz +
|
|
w.y*texture( sam, pos.zx ).xyz +
|
|
w.z*texture( sam, pos.xy ).xyz ) / (w.x+w.y+w.z);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
// SCENE
|
|
//-------------------------------------------------------------------------------------------
|
|
|
|
vec3 lig = normalize( vec3( -0.8, 0.3, -0.5 ) );
|
|
|
|
vec3 shade( in vec3 rd, in vec3 pos, in vec3 nor, in float id, in vec3 uvw, in float dis )
|
|
{
|
|
vec3 ref = reflect(rd,nor);
|
|
float occ = occlusion( pos, nor );
|
|
float fre = clamp(1.0+dot(rd,nor),0.0,1.0);
|
|
|
|
occ = occ*0.5 + 0.5*occ*occ;
|
|
|
|
vec3 lin = vec3(0.0);
|
|
lin += 1.0*vec3(0.6,0.6,0.6)*occ;
|
|
lin += 0.5*vec3(0.3,0.3,0.3)*(0.2+0.8*occ);
|
|
lin += 0.3*vec3(0.5,0.4,0.3)*pow( fre, 2.0 )*occ;
|
|
lin += 0.1*nor.y + 0.1*nor;
|
|
|
|
float dif = clamp( nor.y, 0.0, 1.0 ) * shadow( pos, vec3(0.0,1.0,0.0) );
|
|
|
|
lin = lin*0.7 + 0.8*dif;
|
|
|
|
vec3 mate = 0.6 + 0.4*cos( 10.0*sin(id) + vec3(0.0,0.5,1.0) + 2. );
|
|
vec3 te = vec3(0);//textureBox( iChannel0, 0.25*uvw, nor );
|
|
vec3 qe = te;
|
|
te = 0.5 + 0.5*te;
|
|
mate *= te*1.7;
|
|
|
|
float h = id / float(NUMSPHEREES);
|
|
mate *= 1.0-smoothstep(0.5,0.6,sin(50.0*uvw.x*(1.0-0.95*h))*
|
|
sin(50.0*uvw.y*(1.0-0.95*h))*
|
|
sin(50.0*uvw.z*(1.0-0.95*h)) );
|
|
|
|
vec3 col = mate*lin;
|
|
|
|
float r = clamp(qe.x,0.0,1.0);
|
|
col += 0.2 * r * pow( clamp(dot(-rd,nor), 0.0, 1.0 ), 4.0 ) * occ;
|
|
col += 0.4 * r * pow( clamp(reflect(rd,nor).y, 0.0, 1.0 ), 8.0 ) * dif;
|
|
|
|
|
|
//col *= 1.5*exp( -0.05*dis*dis );
|
|
|
|
return col;
|
|
}
|
|
|
|
|
|
vec3 trace(in vec3 ro, in vec3 rd)
|
|
{
|
|
vec3 col;
|
|
float tmin = 1e20;
|
|
|
|
float t = tmin;
|
|
float id = -1.0;
|
|
vec4 obj = vec4(0.0);
|
|
for( int i=0; i<NUMSPHEREES; i++ )
|
|
{
|
|
vec4 sph = sphere[i];
|
|
float h = sphIntersect( ro, rd, sph );
|
|
if( h>0.0 && h<t )
|
|
{
|
|
t = h;
|
|
obj = sph;
|
|
id = float(i);
|
|
}
|
|
}
|
|
|
|
if( id>-0.5 )
|
|
{
|
|
vec3 pos = ro + t*rd;
|
|
vec3 nor = sphNormal( pos, obj );
|
|
col = shade( rd, pos, nor, float(NUMSPHEREES-1)-id, pos-obj.xyz, t );
|
|
} else {
|
|
discard;
|
|
}
|
|
|
|
return col;
|
|
}
|
|
|
|
|
|
vec3 animate( float time )
|
|
{
|
|
|
|
// animate
|
|
vec3 cen = vec3(0.0);
|
|
for( int i=0; i<NUMSPHEREES; i++ )
|
|
{
|
|
float id = float(NUMSPHEREES-1-i);
|
|
float ra = pow(id/float(NUMSPHEREES-1),3.0);
|
|
vec3 pos = 1.0*cos( 6.2831*hash3(id*16.0) + 1.5*(1.0-0.7*ra)*sin(id)*time*2.0 );
|
|
ra = 0.2 + 0.8*ra;
|
|
|
|
// repell
|
|
#if NUMPASES>0
|
|
#if NUMPASES>1
|
|
for( int k=0; k<NUMPASES; k++ )
|
|
#endif
|
|
for( int j=0; j<NUMSPHEREES; j++ )
|
|
{
|
|
if( j<i )
|
|
{
|
|
vec3 di = pos.xyz - sphere[j].xyz;
|
|
float rr = ra + sphere[j].w;
|
|
if( dot(di,di) < rr*rr )
|
|
{
|
|
float l = length(di);
|
|
pos += di*(rr-l)/l;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
sphere[i] = vec4( pos, ra );
|
|
cen += pos;
|
|
}
|
|
|
|
cen /= float(NUMSPHEREES);
|
|
return cen;
|
|
}
|
|
|
|
vec3 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 *= 5.8405;
|
|
ro.y *= 5.7778;
|
|
ro.z *= 4.8456;
|
|
ro.x += 0.1064;
|
|
ro.y += -0.0180;
|
|
ro.z += 0.3291;
|
|
eye.x *= 5.8405;
|
|
eye.y *= 5.7778;
|
|
eye.z *= 4.8456;
|
|
eye.x += 0.1064;
|
|
eye.y += -0.0180;
|
|
eye.z += 0.3291;
|
|
|
|
vec3 rd = normalize(ro - eye); // ray from camera eye to ro
|
|
|
|
animate(iGlobalTime*0.5);
|
|
return trace(eye, rd);
|
|
}
|
|
|
|
|
|
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;
|
|
} |