Skip to content

Instantly share code, notes, and snippets.

@baffo32
Created August 29, 2016 12:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baffo32/309a5df6e9d1c34cfda55292d5d4acc0 to your computer and use it in GitHub Desktop.
Save baffo32/309a5df6e9d1c34cfda55292d5d4acc0 to your computer and use it in GitHub Desktop.
Rolling Sphere
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform vec2 resolution;
#define FTIME_PERIOD 16.0
uniform float ftime;
uniform float subsecond;
uniform vec3 pointers[10];
const float PI = 3.141592653589793238;
const float INF = 1.0 / 0.0;
const float INCLINE = 0.5;
const float ROLL_DIST_HORIZONTAL = 3.0;
const float ROLL_DIST = sqrt(INCLINE*INCLINE+1.0)*ROLL_DIST_HORIZONTAL;
const float RADIUS = ROLL_DIST / (2.0 * PI);
const float ROLLS = 8.0;
struct Surf {
vec3 col;
float matte;
};
struct Checker {
Surf surf1;
Surf surf2;
};
struct Ray {
vec3 src;
vec3 dir;
float dist;
vec4 col;
Surf surf;
vec3 norm;
};
struct ParallelLight
{
vec3 dir;
float brt;
float amb;
};
struct Sphere {
vec3 pos;
float rad;
};
struct SolidSphere {
Sphere sph;
Surf surf;
};
struct CheckerSphere {
Sphere sph;
Checker chk;
};
struct Plane {
vec3 dir;
float dist;
};
struct CheckerPlane {
Plane pln;
Checker chk;
};
const ParallelLight sun = ParallelLight(
normalize(vec3(1,.1,0)),
0.8,
0.2
);
/*const SolidSphere sphere = SolidSphere(
Sphere(
vec3(0,1,0),
1.0
),
Surf(vec3(0.5), 0.75)
);*/
const CheckerSphere sphere = CheckerSphere(
Sphere(
vec3(0,RADIUS,0),
RADIUS
),
Checker(
Surf(vec3(0.1), 0.75),
Surf(vec3(0.8), 0.75)
)
);
const CheckerPlane plane = CheckerPlane(
Plane(
normalize(vec3(INCLINE,1,0)),
-0.0
),
Checker(
Surf(vec3(0.1), 1.0),
Surf(vec3(0.8), 1.0)
)
);
vec3 sky(inout Ray r)
{
return abs(r.dir);
}
Ray eyeRay(mat3 eyedir, float eyedist)
{
vec2 px = (2.0 * gl_FragCoord.xy - resolution)
/ min(resolution.xx, resolution.yy);
vec3 dir = eyedir * normalize(vec3(px, -1));
return Ray(
eyedir * vec3(0,RADIUS,eyedist+2.0*RADIUS),
dir,
INF,
vec4(0,0,0,1),
Surf(vec3(0),1.0),
vec3(0)
);
}
vec3 prep(Ray r, Sphere s)
{
vec3 rp = s.pos - r.src;
float A = dot(r.dir, r.dir);
float b = dot(rp, r.dir);
float C = dot(rp, rp) - s.rad * s.rad;
return vec3(A, b, b * b - A * C);
}
bool hit(Ray r, Sphere s)
{
return prep(r, s).z > 0.0;
}
float dist(Ray r, Sphere s)
{
vec3 p = prep(r, s);
if (p.z <= 0.0)
return -INF;
return (p.y - sqrt(p.z)) / p.x;
}
void apply(inout Ray r, SolidSphere s)
{
r.src += r.dir * r.dist;
r.surf = s.surf;
r.norm = (r.src - s.sph.pos) / s.sph.rad;
}
void apply(inout Ray r, CheckerSphere s, float angle) //mat3 d)
{
r.src += r.dir * r.dist;
vec3 rp = r.src - s.sph.pos;
vec3 chk = vec3(
rp.x*cos(angle)-rp.y*sin(angle),
rp.x*sin(angle)+rp.y*cos(angle),
rp.z
)*2.0;//atan(rp.yz, rp.xx) * 2.0;
if (mod(dot(floor(chk+vec3(.5)),vec3(1)),2.0)>0.0)
r.surf = s.chk.surf1;
else
r.surf = s.chk.surf2;
r.norm = rp / s.sph.rad;
}
float dist(Ray r, Plane p)
{
return (p.dist - dot(r.src, p.dir)) / dot(r.dir, p.dir);
}
void apply(inout Ray r, CheckerPlane p, vec3 o)
{
//float pixels =
// abs(dot(r.dir, p.pln.dir)) / r.dist *
// min(resolution.x, resolution.y);
float ratio = 1.0;//clamp(pixels, 0.5, 1.0);
r.src += r.dir * r.dist;
if (mod(dot(floor(r.src.xz+o.xz+vec2(.5)),vec2(1)),2.0)>0.0)
ratio = 1.0 - ratio;
r.surf.col = mix(p.chk.surf1.col, p.chk.surf2.col, ratio);
//r.surf.matte = mix(p.chk.surf1.matte, p.chk.surf2.matte, ratio);
//r.norm = p.pln.dir;
}
void refl(inout Ray r)
{
r.dir = reflect(r.dir, r.norm);
r.dist = INF;
}
void apply(inout Ray r, Surf s, ParallelLight l)
{
float brt = max(l.amb,dot(l.dir, r.norm)*l.brt);
r.col.xyz = mix(r.col.xyz, s.col*brt, r.col.w);
r.col.w -= r.col.w * s.matte;
}
void apply(inout Ray r, vec3 c)
{
r.col = vec4(mix(r.col.xyz, c, r.col.w), 0);
}
void apply(inout Ray r, Surf s)
{
r.col.xyz = mix(r.col.xyz, s.col, r.col.w);
r.col.w -= r.col.w * s.matte;
}
void main( void )
{
float yangle = ftime * PI +
pointers[0].x * PI / resolution.x;
float xangle =
atan(-plane.pln.dir.x,plane.pln.dir.y);
float dst = RADIUS * 4.0 *
(1.0 - pointers[0].y / resolution.y);
float ycos = cos(yangle);
float ysin = sin(yangle);
float xcos = cos(xangle);
float xsin = sin(xangle);
mat3 dir = mat3(
ycos, 0, ysin,
0,1,0,
-ysin, 0, ycos
) * mat3(
1, 0, 0,
0, xcos, xsin,
0,-xsin, xcos
);
Ray ray = eyeRay(dir, dst);
float tS = dist(ray, sphere.sph);
if (tS > 0.0) {
float rangle = ftime * PI * ROLLS;
//float rcos = cos(rangle);
//float rsin = sin(rangle);
//mat3 dir2 = mat3(
// rcos, rsin, 0,
// -rsin, rcos, 0,
// 0, 0, 1
//);
ray.dist = tS;
apply(ray, sphere, rangle);//dir2);
apply(ray, ray.surf, sun);
refl(ray);
}
ray.dist = dist(ray, plane.pln);
if (ray.dist > 0.0) {
vec3 off =
ftime * ROLLS * ROLL_DIST_HORIZONTAL
/ 2.0 * vec3(1,0,0);
apply(ray, plane, off);
ray.dir = sun.dir;
if (hit(ray, sphere.sph))
ray.surf.col *= sun.amb / sun.brt;
apply(ray, ray.surf);
} else {
apply(ray, sky(ray));
}
gl_FragColor = ray.col;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment