Skip to content

Instantly share code, notes, and snippets.

@strangerintheq
Last active January 2, 2019 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save strangerintheq/73ad4b97ac498bf7ae607f262d6b6ff5 to your computer and use it in GitHub Desktop.
Save strangerintheq/73ad4b97ac498bf7ae607f262d6b6ff5 to your computer and use it in GitHub Desktop.
christmas tree
license: gpl-3.0
height: 600
scrolling: no
border: yes
vcs.xml
.idea/

christmas tree

raymarching

happy new year

const float PI =3.141592;
const float PI2=6.2831853;
const float maxd=256.0; //Max depth
float nearestD = maxd;
vec3 color = vec3(0.0,0.0,1.0);
float flakes(vec3 p) {
const float snowflakeMaxDist = 20.0;
if ( (abs(p.x) > snowflakeMaxDist) ||
(abs(p.y) > snowflakeMaxDist) ||
(abs(p.z) > snowflakeMaxDist) )
return 9999.9;
float snowPush = 0.25*time;
p.x += snowPush*-3.0;
p.y += snowPush*1.5;
p.z += snowPush*-0.25;
const float modDist = 2.0;
float stepX = floor(p.x/modDist);
float stepY = floor(p.y/modDist);
float stepZ = floor(p.z/modDist);
vec3 flakeP = vec3(
mod(p.x,modDist),
mod(p.y,modDist),
mod(p.z,modDist)
);
vec3 flakePos = vec3(modDist*0.5);
flakePos.x += sin(snowPush+stepY*1.0)*(2.0/5.0)*modDist;
flakePos.y += sin(snowPush+stepZ*1.3)*(2.0/5.0)*modDist;
flakePos.z += sin(snowPush+stepX*1.7)*(2.0/5.0)*modDist;
return sdSphere(flakeP- flakePos, 0.03);
}
<!DOCTYPE html>
<html>
<style>
body {
margin: 0;
overflow: hidden
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<body>
<script src="https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.3/js/glx.js"></script>
<script src="https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.3/js/ShaderLoader.js"></script>
<script src="https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.3/js/FullScreenTriangle.js"></script>
<script src="https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.3/js/mouse3d.js"></script>
<script>
ShaderLoader.load('tree.glsl', init);
function init(fragCode) {
let fst = FullScreenTriangle(fragCode);
let resolution = fst.triangleProgram.uniform('2f', 'resolution');
let lightPos = fst.triangleProgram.uniform('3f', 'lightPos');
let time = fst.triangleProgram.uniform('1f', 'time');
let eye = fst.triangleProgram.uniform('3f', 'eye');
let lookAt = fst.triangleProgram.uniform('3f', 'lookAt');
let started = new Date().getTime();
Mouse3D.init(fst.canvas, 12);
animate();
function animate() {
requestAnimationFrame(animate);
drawFrame();
}
function drawFrame() {
let t = (new Date().getTime() - started)/1000;
resolution.set(fst.gl.drawingBufferWidth, fst.gl.drawingBufferHeight);
time.set(t);
lightPos.set(Math.cos(t/10)*10,10,Math.sin(t/10)*10);
eye.set(Mouse3D.eye[0], Mouse3D.eye[1], Mouse3D.eye[2]);
lookAt.set(Mouse3D.lookAt[0], Mouse3D.lookAt[1], Mouse3D.lookAt[2]);
fst.draw();
}
}
</script>
</body>
</html>
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.3/glsl/lighting/phong.glsl
/**
* Lighting via Phong illumination.
*
* The vec3 returned is the RGB color of that point after lighting is applied.
* k_a: Ambient color
* k_d: Diffuse color
* k_s: Specular color
* alpha: Shininess coefficient
* p: position of point being lit
* eye: the position of the camera
*
* See https://en.wikipedia.org/wiki/Phong_reflection_model#Description
*/
vec3 phongIllumination(vec3 k_a, vec3 k_d, vec3 k_s, float alpha, vec3 p, vec3 nor, vec3 eye, vec3 materialColor) {
const vec3 lightIntensity = vec3(0.7, 0.7, 0.7);
vec3 color = materialColor * k_a;
color += phongContribForLight(k_d, k_s, alpha, p, nor, eye, lightPos, lightIntensity);
//color += phongContribForLight(k_d, k_s, alpha, p, eye, light2Pos, light2Intensity);
return color;
}
vec3 decodeMaterial(float material) {
if (material < 0.) {
return vec3(0.,1.,0.);
}
float r = material * 10.;
r = r - fract(r);
r = r/10.;
float g = material * 100. - r * 100.;
g = g - fract(g);
g = g/10.;
float b = material * 1000. - r * 1000. - g * 100.;
b = b - fract(b);
b = b/10.;
return vec3(r, g, b);
}
vec3 phong(vec3 p, vec3 nor, vec3 eye, float material) {
const vec3 K_a = vec3(.3, .2, .2);
const vec3 K_d = vec3(.2, .4, .7);
const vec3 K_s = vec3(.1, .1, .1);
const float shininess = 3.5;
vec3 materialColor = decodeMaterial(material);
return phongIllumination(K_a, K_d, K_s, shininess, p, nor, eye, materialColor);
}
const float VERY_FAR = 1e11;
float ground(vec3 p){
float d = -0.50 ;
p.y += noise(p)*.33 ;
d = sdPlane(p, d);
return d;
}
vec2 star(vec3 p) {
p.y -=1.5;
p.xy = repeatAng(p.xy, 5.0); // 3. Clone five cornders radially about Z axis
p.xz = abs(p.xz); // 2. Symmetrical about XoY and ZoY
vec3 n = vec3(0.5, 0.25, 0.8);
float d = plane(p, normalize(n), 0.065); // 1. A plane cutting the corner of X+Y+Z+
return vec2(d, .900 );
}
vec2 green(vec3 p) {
float d = VERY_FAR;
float k = .12;
d = sdCappedCone( p - vec3(.0, .99, .0), .4, 0.45, .0);
d = opSmoothU(d, sdCappedCone( p - vec3(.0, .55, .0), .5, 0.55, .0), k);
d = opSmoothU(d, sdCappedCone( p - vec3(.0, .11, .0), .6, 0.65, .0), k);
return vec2( d, -2. );
}
vec2 trunk(vec3 p) {
float d = VERY_FAR;
d = sdCylinder(p-vec3(.0, -.5,.0), vec2(0.1, 0.6));
return vec2( d, 0.000 );
}
vec2 toy(vec3 p, float col) {
float d = VERY_FAR;
d = sdSphere(p, 0.07);
return vec2( d, col );
}
vec2 toys(vec3 p) {
vec2 res = vec2(VERY_FAR, -1);
float r = .42;
float h = -0.57;
res = opU( res, toy(p-vec3(-r, h, -r), 0.990) );
res = opU( res, toy(p-vec3(-r, h, r), 0.099) );
res = opU( res, toy(p-vec3( r, h, -r), 0.999) );
res = opU( res, toy(p-vec3( r, h, r), 0.555) );
r = .3;
h = 0.5;
res = opU( res, toy(p-vec3(-r, h, -r), 0.990) );
res = opU( res, toy(p-vec3(-r, h, r), 0.099) );
res = opU( res, toy(p-vec3( r, h, -r), 0.999) );
res = opU( res, toy(p-vec3( r, h, r), 0.555) );
r = .5;
h = -0.05;
res = opU( res, toy(p-vec3(-r, h, 0.), 0.990) );
res = opU( res, toy(p-vec3( 0, h, -r), 0.099) );
res = opU( res, toy(p-vec3( r, h, 0.), 0.999) );
res = opU( res, toy(p-vec3( 0, h, r), 0.555) );
return res;
}
vec2 tree(vec3 p) {
vec2 res = vec2(VERY_FAR, -1);
res = opU( res, green(p) );
res = opU( res, trunk(p) );
res = opU( res, star(p) );
res = opU( res, toys(p) );
// res = opU( res, lamps(p) );
return res;
}
float snowmans(vec3 p) {
// mirror 3
p.xz = repeatAng(p.xz, 3.0);
p.xz = abs(p.xz);
float k = .12;
float d = sdSphere( p - vec3(1.5, 0.7, 3.0), .2);
d = opSmoothU(d, sdSphere( p - vec3(1.5, 0.2, 3.0), .3), k);
d = opSmoothU(d, sdSphere( p - vec3(1.5, -0.4, 3.0), .4), k);
return d;
}
float snowfall(vec3 p) {
vec3 q = vec3(mod(p.x, 3.0) - 1.5, p.yz);
return sdSphere( q - vec3(1.5, 0.7, 3.0), .02);
}
vec2 snow(vec3 p) {
float k = .12;
float d = ground(p);
d = opSmoothU(d, snowmans( p ), k);
// d = opSmoothU(d, snowfall( p ), k);
d = opSmoothU( d, flakes(p), k );
return vec2( d, .999 );
}
vec2 snowmans_accesories(vec3 p) {
// mirror 3
p.xz = repeatAng(p.xz, 3.0);
p.xz = abs(p.xz);
float k = .12;
vec2 res = vec2(sdSphere( p - vec3(1.50, 0.70, 3.20), .02), 0.00 );
res = opU(res, vec2(sdSphere( p - vec3(1.44, 0.75, 3.18), .02), 0.00 ));
res = opU(res, vec2(sdSphere( p - vec3(1.56, 0.75, 3.18), .02), 0.00 ));
res = opU(res, vec2(sdSphere( p - vec3(1.50, 0.25, 3.30), .02), 0.00 ));
res = opU(res, vec2(sdSphere( p - vec3(1.50, -0.40, 3.40), .02), 0.00 ));
return res;
}
vec2 map(vec3 p) {
vec2 res = vec2(VERY_FAR, -1);
res = opU( res, snow(p) );
res = opU( res, snowmans_accesories(p) );
res = opU( res, tree(p) );
return res;
}
// distance to bezier curve
float det( vec2 a, vec2 b ) {
return a.x*b.y-b.x*a.y;
}
vec3 getClosest( vec2 b0, vec2 b1, vec2 b2 ) {
float a = det(b0,b2);
float b = det(b1,b0)*2.;
float d = det(b2,b1)*2.;
float f = b*d - a*a;
vec2 d21 = b2-b1;
vec2 d10 = b1-b0;
vec2 d20 = b2-b0;
vec2 gf = 2.0*(b*d21+d*d10+a*d20); gf = vec2(gf.y,-gf.x);
vec2 pp = -f*gf/dot(gf,gf);
vec2 d0p = b0-pp;
float ap = det(d0p,d20);
float bp = 2.0*det(d10,d0p);
float t = clamp( (ap+bp)/(2.0*a+b+d), 0.0 ,1.0 );
return vec3( mix(mix(b0,b1,t), mix(b1,b2,t),t), t );
}
vec2 sdBezier( vec3 a, vec3 b, vec3 c, vec3 p, float thickness ) {
vec3 w = normalize( cross( c-b, a-b ) );
vec3 u = normalize( c-b );
vec3 v = normalize( cross( w, u ) );
vec2 a2 = vec2( dot(a-b,u), dot(a-b,v) );
vec2 b2 = vec2( 0.0 );
vec2 c2 = vec2( dot(c-b,u), dot(c-b,v) );
vec3 p3 = vec3( dot(p-b,u), dot(p-b,v), dot(p-b,w) );
vec3 cp = getClosest( a2-p3.xy, b2-p3.xy, c2-p3.xy );
return vec2( 0.85*(sqrt(dot(cp.xy,cp.xy)+p3.z*p3.z) - thickness), cp.z );
}
// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
// distance functions
float dot2( in vec2 v ) {
return dot(v,v);
}
float sdCappedCone( in vec3 p, in float h, in float r1, in float r2 ){
vec2 q = vec2( length(p.xz), p.y );
vec2 k1 = vec2(r2,h);
vec2 k2 = vec2(r2-r1,2.0*h);
vec2 ca = vec2(q.x-min(q.x,(q.y < 0.0)?r1:r2), abs(q.y)-h);
vec2 cb = q - k1 + k2*clamp( dot(k1-q,k2)/dot2(k2), 0.0, 1.0 );
float s = (cb.x < 0.0 && ca.y < 0.0) ? -1.0 : 1.0;
return s*sqrt( min(dot2(ca),dot2(cb)) );
}
// vertical
float sdCylinder( vec3 p, vec2 h ){
vec2 d = abs(vec2(length(p.xz),p.y)) - h;
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
}
float sdSphere( vec3 p, float s ){
return length(p)-s;
}
// horizontal
float sdPlane( vec3 p , float down){
return p.y - down;
}
float plane(vec3 p, vec3 n, float offs) {
return dot(p, n) - offs;
}
// distance functions operations
float opS( float d1, float d2 ){
return max(-d2,d1);
}
vec2 opU( vec2 d1, vec2 d2 ){
return (d1.x<d2.x) ? d1 : d2;
}
vec3 opRep( vec3 p, vec3 c ){
return mod(p,c)-0.5*c;
}
vec3 opTwist( vec3 p ){
float c = cos(10.0*p.y+10.0);
float s = sin(10.0*p.y+10.0);
mat2 m = mat2(c,-s,s,c);
return vec3(m*p.xz,p.y);
}
float opSmoothU( float d1, float d2, float k ) {
float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
return mix( d2, d1, h ) - k*h*(1.0-h);
}
vec2 rotate(vec2 p, float ang) {
float c = cos(ang), s = sin(ang);
return vec2(p.x*c - p.y*s, p.x*s + p.y*c);
}
vec2 repeatAng(vec2 p, float n) {
float ang = 2.0*3.14/n;
float sector = floor(atan(p.x, p.y)/ang + 0.5);
p = rotate(p, sector*ang);
return p;
}
precision highp float;
// christmas tree
// by stranger in the q
// at 2018-dec-29
uniform vec2 resolution;
uniform vec3 eye;
uniform vec3 lookAt;
uniform vec3 lightPos;
uniform float time;
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/noise.glsl
#pragma import sdf.glsl
#pragma import flakes.glsl
#pragma import scene.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/rayDirection.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/viewMatrix.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/castRay.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/normal.glsl
#pragma import phong.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/softShadow.glsl
#pragma import https://cdn.jsdelivr.net/gh/strangerintheq/glx@0.0.2/glsl/ao.glsl
void drawSky() {
gl_FragColor = vec4(0.9, 0.9, 0.9, 1.0);
}
void drawScene(vec3 pt, float material) {
vec3 nor = estimateNormal( pt );
float occ = ao( pt, nor );
float shadow = softShadow( pt, normalize(lightPos-pt), 0.1, 22.2);
vec3 color = phong(pt, nor, eye, material)*sqrt(occ);
color += color * shadow;
gl_FragColor = vec4(color, 1.0);
}
void main(void) {
vec3 direction = rayDirection(60.0, resolution);
mat4 viewToWorld = viewMatrix(eye, lookAt, vec3(0.0, 1.0, 0.0));
vec3 worldDir = (viewToWorld * vec4(direction, 0.0)).xyz;
vec2 dist = castRay(eye, worldDir);
if (dist.x > 32.) {
drawSky();
} else {
drawScene(eye + dist.x * worldDir, dist.y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment