Skip to content

Instantly share code, notes, and snippets.

@s4y
Created September 23, 2019 12:16
Show Gist options
  • Save s4y/28ccf14a7eb3629f238ffad27d6ac38d to your computer and use it in GitHub Desktop.
Save s4y/28ccf14a7eb3629f238ffad27d6ac38d to your computer and use it in GitHub Desktop.
A ray marched cube (runs in Pythonista)
# coding: utf-8
import scene
import motion
preamble = """
precision highp float;
varying vec2 v_tex_coord;
uniform vec2 u_sprite_size;
uniform sampler2D u_texture;
uniform float u_time;
uniform vec3 u_tilt;
float aspect =
u_sprite_size.x / u_sprite_size.y;
"""
shader = scene.Shader(preamble + """
float sdBox(vec3 p, vec3 b) {
vec3 d = abs(p) - b;
return length(max(d,0.0)) + min(max(d.x,max(d.y,d.z)),0.0);
}
mat4 rotX(float angle) {
return mat4(
1, 0, 0, 0,
0, cos(angle), -sin(angle), 0,
0, sin(angle), cos(angle), 0,
0, 0, 0, 1
);
}
mat4 rotY(float angle) {
return mat4(
cos(angle), 0, sin(angle), 0,
0, 1, 0, 0,
-sin(angle), 0, cos(angle), 0,
0, 0, 0, 1
);
}
mat4 rotZ(float angle) {
return mat4(
cos(angle), -sin(angle), 0, 0,
sin(angle), cos(angle), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
}
vec3 transform(vec3 p, mat4 t) {
vec4 p4 = t * vec4(p, 1.0);
return p4.xyz / p4.w;
}
float ease(float t) {
return t*t/(2.*(t*t-t)+1.);
}
vec2 sceneDistance(vec3 p, vec3 tilt) {
vec3 boxP = (rotX(-u_tilt.y) * rotY(u_tilt.x) * vec4(p, 1.0)).xyz;
float dist = 1e10;
float color = 0.;
const int imax = 3;
for (int i=0; i<imax;i++) {
float slc = float(i)/float(imax)-1./float(imax);
float ezR = ease(clamp(mod(u_time+slc*0.5, 1.0)*2.0,0.,1.));
bool which = mod(u_time+1./3., 2.0)>1.0;
float ezTot = ease(clamp(mod(u_time+(1./float(imax)), 1.0)*1.0,0.,1.));
float rotAmt = ezR*(atan(-1.)*2.0);
vec3 sliceP = (rotX(rotAmt) * rotZ(which?atan(-1.)*2.:0.) * vec4(boxP, 1.0)).xyz;
sliceP.x += slc*(0.5+(0.5-abs(0.5-ezTot))*0.25);
float ndist = sdBox(
sliceP, vec3(0.25/float(imax),0.25,0.25));
if (ndist < dist) {
dist = ndist;
color = 0.25+pow(abs(sliceP.x)*8.0, 4.)*(0.5-abs(0.5-ezTot))*1.0;
}
}
return vec2(dist, color);
}
const int kMarchSteps = 40;
const float kEpsilon = 0.0001;
void main() {
vec3 p = vec3(v_tex_coord, 0.5) * 2.0 - 1.0;
vec3 tilt = u_tilt;
p.x *= aspect;
p.z += 1.0;
float dist = 0.0;
float ldist = 1.0/0.0;
float color = 0.0;
for (int i = 0; i < kMarchSteps; i++) {
vec2 ret = sceneDistance(p + vec3(0.0, 0.0, -dist) , tilt);
ldist = ret[0];
color = ret[1];
dist += ldist;
if (dist > 10.)
discard;
if (ldist < kEpsilon)
break;
}
float bri = max(dist, 0.0);
bri=max(0.0,1.8-dist);
bri=pow(bri,0.5);
bri = pow(bri, 2.0);
gl_FragColor = vec4(color, 1.0-color, 1.0, 1.0) * bri;
}
""")
class Scene (scene.Scene):
def setup(self):
motion.start_updates()
self.sprite = scene.SpriteNode(parent=self)
self.sprite.shader = shader
self.did_change_size()
self.background_color = 'black';
def update(self):
self.sprite.shader.set_uniform(
'u_tilt', motion.get_attitude())
def did_change_size(self):
self.sprite.position = self.size/2
self.sprite.size = self.size
s = Scene()
scene.run(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment