Created
August 29, 2016 12:37
-
-
Save baffo32/309a5df6e9d1c34cfda55292d5d4acc0 to your computer and use it in GitHub Desktop.
Rolling Sphere
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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