219 lines
4.8 KiB
GLSL
219 lines
4.8 KiB
GLSL
/*by mu6k, Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
|
|
|
I have no idea how I ended up here, but it demosceneish enough to publish.
|
|
You can use the mouse to rotate the camera around the 'object'.
|
|
If you can't see the shadows, increase occlusion_quality.
|
|
If it doesn't compile anymore decrease object_count and render_steps.
|
|
|
|
15/06/2013:
|
|
- published
|
|
|
|
16/06/2013:
|
|
- modified for better performance and compatibility
|
|
|
|
muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuusk!*/
|
|
|
|
#define occlusion_enabled
|
|
#define occlusion_quality 4
|
|
// #define occlusion_preview
|
|
|
|
#define noise_use_smoothstep
|
|
|
|
#define light_color vec3(0.3,0.4,0.6)
|
|
#define light_direction normalize(vec3(.2,1.0,-0.2))
|
|
#define light_speed_modifier 1.0
|
|
|
|
#define object_color vec3(0.93,0.2,0.1)
|
|
#define object_count 19
|
|
#define object_speed_modifier 1.0
|
|
|
|
#define render_steps 33
|
|
|
|
float hash(float x)
|
|
{
|
|
return fract(sin(x*.0127863)*17143.321);
|
|
}
|
|
|
|
float hash(vec2 x)
|
|
{
|
|
return fract(cos(dot(x.xy,vec2(2.31,53.21))*124.123)*412.0);
|
|
}
|
|
|
|
vec3 cc(vec3 color, float factor,float factor2) //a wierd color modifier
|
|
{
|
|
float w = color.x+color.y+color.z;
|
|
return mix(color,vec3(w)*factor,w*factor2);
|
|
}
|
|
|
|
float hashmix(float x0, float x1, float interp)
|
|
{
|
|
x0 = hash(x0);
|
|
x1 = hash(x1);
|
|
#ifdef noise_use_smoothstep
|
|
interp = smoothstep(0.0,1.0,interp);
|
|
#endif
|
|
return mix(x0,x1,interp);
|
|
}
|
|
|
|
float noise(float p) // 1D noise
|
|
{
|
|
float pm = mod(p,1.0);
|
|
float pd = p-pm;
|
|
return hashmix(pd,pd+1.0,pm);
|
|
}
|
|
|
|
vec3 rotate_y(vec3 v, float angle)
|
|
{
|
|
float ca = cos(angle); float sa = sin(angle);
|
|
return v*mat3(
|
|
+ca, +.0, -sa,
|
|
+.0,+1.0, +.0,
|
|
+sa, +.0, +ca);
|
|
}
|
|
|
|
vec3 rotate_x(vec3 v, float angle)
|
|
{
|
|
float ca = cos(angle); float sa = sin(angle);
|
|
return v*mat3(
|
|
+1.0, +.0, +.0,
|
|
+.0, +ca, -sa,
|
|
+.0, +sa, +ca);
|
|
}
|
|
|
|
float max3(float a, float b, float c)//returns the maximum of 3 values
|
|
{
|
|
return max(a,max(b,c));
|
|
}
|
|
|
|
vec3 bpos[object_count];//position for each metaball
|
|
|
|
float dist(vec3 p)//distance function
|
|
{
|
|
float d=1024.0;
|
|
float nd;
|
|
for (int i=0 ;i<object_count; i++)
|
|
{
|
|
vec3 np = p+bpos[i];
|
|
float shape0 = max3(abs(np.x),abs(np.y),abs(np.z))-1.0;
|
|
float shape1 = length(np)-1.0;
|
|
nd = shape0+(shape1-shape0)*2.0;
|
|
d = mix(d,nd,smoothstep(-1.0,+1.0,d-nd));
|
|
}
|
|
return d;
|
|
}
|
|
|
|
vec3 normal(vec3 p,float e) //returns the normal, uses the distance function
|
|
{
|
|
float d=dist(p);
|
|
return normalize(vec3(dist(p+vec3(e,0,0))-d,dist(p+vec3(0,e,0))-d,dist(p+vec3(0,0,e))-d));
|
|
}
|
|
|
|
vec3 light = light_direction; //global variable that holds light direction
|
|
|
|
vec3 background(vec3 d)//render background
|
|
{
|
|
float t=iGlobalTime*0.5*light_speed_modifier;
|
|
float qq = dot(d,light)*.5+.5;
|
|
float bgl = qq;
|
|
float q = (bgl+noise(bgl*6.0+t)*.85+noise(bgl*12.0+t)*.85);
|
|
q+= pow(qq,32.0)*2.0;
|
|
vec3 sky = vec3(0.1,0.4,0.6)*q;
|
|
return sky;
|
|
}
|
|
|
|
float occlusion(vec3 p, vec3 d)//returns how much a point is visible from a given direction
|
|
{
|
|
float occ = 1.0;
|
|
p=p+d;
|
|
for (int i=0; i<occlusion_quality; i++)
|
|
{
|
|
float dd = dist(p);
|
|
p+=d*dd;
|
|
occ = min(occ,dd);
|
|
}
|
|
return max(.0,occ);
|
|
}
|
|
|
|
vec3 object_material(vec3 p, vec3 d)
|
|
{
|
|
vec3 color = normalize(object_color*light_color);
|
|
vec3 n = normal(p,0.1);
|
|
vec3 r = reflect(d,n);
|
|
|
|
float reflectance = dot(d,r)*.5+.5;reflectance=pow(reflectance,2.0);
|
|
float diffuse = dot(light,n)*.5+.5; diffuse = max(.0,diffuse);
|
|
|
|
#ifdef occlusion_enabled
|
|
float oa = occlusion(p,n)*.4+.6;
|
|
float od = occlusion(p,light)*.95+.05;
|
|
float os = occlusion(p,r)*.95+.05;
|
|
#else
|
|
float oa=1.0;
|
|
float ob=1.0;
|
|
float oc=1.0;
|
|
#endif
|
|
|
|
#ifndef occlusion_preview
|
|
color =
|
|
color*oa*.2 + //ambient
|
|
color*diffuse*od*.7 + //diffuse
|
|
background(r)*os*reflectance*.7; //reflection
|
|
#else
|
|
color=vec3((oa+od+os)*.3);
|
|
#endif
|
|
|
|
return color;
|
|
}
|
|
|
|
#define offset1 4.7
|
|
#define offset2 4.6
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
|
{
|
|
vec2 uv = fragCoord.xy / iResolution.xy - 0.5;
|
|
uv.x *= iResolution.x/iResolution.y; //fix aspect ratio
|
|
vec3 mouse = vec3(iMouse.xy/iResolution.xy - 0.5,iMouse.z-.5);
|
|
|
|
float t = iGlobalTime*.5*object_speed_modifier + 2.0;
|
|
|
|
for (int i=0 ;i<object_count; i++) //position for each metaball
|
|
{
|
|
bpos[i] = 1.3*vec3(
|
|
sin(t*0.967+float(i)*42.0),
|
|
sin(t*.423+float(i)*152.0),
|
|
sin(t*.76321+float(i)));
|
|
}
|
|
|
|
//setup the camera
|
|
vec3 p = vec3(.0,0.0,-4.0);
|
|
p = rotate_x(p,mouse.y*9.0+offset1);
|
|
p = rotate_y(p,mouse.x*9.0+offset2);
|
|
vec3 d = vec3(uv,1.0);
|
|
d.z -= length(d)*.5; //lens distort
|
|
d = normalize(d);
|
|
d = rotate_x(d,mouse.y*9.0+offset1);
|
|
d = rotate_y(d,mouse.x*9.0+offset2);
|
|
|
|
//and action!
|
|
float dd;
|
|
vec3 color;
|
|
for (int i=0; i<render_steps; i++) //raymarch
|
|
{
|
|
dd = dist(p);
|
|
p+=d*dd*.7;
|
|
if (dd<.04 || dd>4.0) break;
|
|
}
|
|
|
|
if (dd<0.5) //close enough
|
|
color = object_material(p,d);
|
|
else
|
|
color = background(d);
|
|
|
|
//post procesing
|
|
color *=.85;
|
|
color = mix(color,color*color,0.3);
|
|
color -= hash(color.xy+uv.xy)*.015;
|
|
color -= length(uv)*.1;
|
|
color =cc(color,.5,.6);
|
|
fragColor = vec4(color,1.0);
|
|
} |