Skip to content

Instantly share code, notes, and snippets.

@ahmadiqbal1
Created October 15, 2020 12:37
Show Gist options
  • Save ahmadiqbal1/a45d6d3a1c88e41925868bb6871c26ef to your computer and use it in GitHub Desktop.
Save ahmadiqbal1/a45d6d3a1c88e41925868bb6871c26ef to your computer and use it in GitHub Desktop.
Arrow Truchet
<canvas id="webgl" width="500" height="1758"></canvas>
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_position;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
void main() {
gl_Position = a_position;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
uniform sampler2D u_noise;
vec2 getScreenSpace() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x);
return uv;
}
float hash2(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}
#define PI 3.14159265359
// Distance field functions by Inigo Quilez - https://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
float sdEquilateralTriangle( in vec2 p ) {
const float k = sqrt(3.0);
p.x = abs(p.x) - 1.0;
p.y = p.y + 1.0/k;
if( p.x+k*p.y>0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
p.x -= clamp( p.x, -2.0, 0.0 );
return -length(p)*sign(p.y);
}
float sdBox( in vec2 p, in vec2 b ) {
vec2 d = abs(p)-b;
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
vec4 truchet(vec2 uv, float w) {
vec2 grid = fract(uv)-.5;
vec2 id = floor(uv);
float r = hash2(id)+.012;
float r1 = hash2(id+vec2(50., -50.*r));
grid.x *= sign(r-.5);
if(r1 >= .0) {
vec2 p = grid - .5 * sign(grid.x + grid.y + .0001);
float f = length(p);
float a = atan(p.y, p.x);
float checker = sign(mod(id.x+id.y, 2.) - .5);
if(checker == 0.) checker = 1.;
return vec4(
vec2(
fract(checker * a / (PI / 4.) - u_time * 5.),
abs((f - (.5-w)) / (2. * w) - .5) * 2.
),
floor(checker * a / (PI / 4.) - u_time * 5.),
f
);
}
}
void main() {
vec2 uv = getScreenSpace();
vec3 colour = vec3(0);
// uv *= 40.;
uv *= 12. + sin(u_time*.6) * 10.;
uv += vec2(u_time*2., sin(u_time*.5)*2.);
float w = .2;
vec4 t = truchet(uv, w);
vec2 luv = t.xy;
float luvid = t.z;
float field = t.a;
float arrowfield = sdEquilateralTriangle(luv*2.+vec2(0., .5));
if(mod(luvid, 2.) == 0.) {
arrowfield = 2.;
arrowfield = min(arrowfield, sdBox(luv*2.-vec2(1.5, 0.), vec2(.5, .2)));
}
float mask = smoothstep(w, w-.01, abs(field-.5));
colour = vec3((smoothstep(.05, 0., arrowfield)+luv.y*.5)*mask);
gl_FragColor = vec4(colour,1.0);
}
</script>
console.clear();
const twodWebGL = new WTCGL(
document.querySelector('canvas#webgl'),
document.querySelector('script#vertexShader').textContent,
document.querySelector('script#fragmentShader').textContent,
window.innerWidth,
window.innerHeight,
2
);
twodWebGL.startTime = -100 + (Math.random()-.5) * 50;
window.addEventListener('resize', () => {
twodWebGL.resize(window.innerWidth, window.innerHeight);
});
// track mouse move
let mousepos = [0,0];
const u_mousepos = twodWebGL.addUniform('mouse', WTCGL.TYPE_V2, mousepos);
window.addEventListener('pointermove', (e) => {
let ratio = window.innerHeight / window.innerWidth;
if(window.innerHeight > window.innerWidth) {
mousepos[0] = (e.pageX - window.innerWidth / 2) / window.innerWidth;
mousepos[1] = (e.pageY - window.innerHeight / 2) / window.innerHeight * -1 * ratio;
} else {
mousepos[0] = (e.pageX - window.innerWidth / 2) / window.innerWidth / ratio;
mousepos[1] = (e.pageY - window.innerHeight / 2) / window.innerHeight * -1;
}
twodWebGL.addUniform('mouse', WTCGL.TYPE_V2, mousepos);
});
// Load all our textures. We only initiate the instance once all images are loaded.
const textures = [
{
name: 'noise',
url: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/982762/noise.png',
type: WTCGL.IMAGETYPE_TILE,
img: null
}
];
const loadImage = function (imageObject) {
let img = document.createElement('img');
img.crossOrigin="anonymous";
return new Promise((resolve, reject) => {
img.addEventListener('load', (e) => {
imageObject.img = img;
resolve(imageObject);
});
img.addEventListener('error', (e) => {
reject(e);
});
img.src = imageObject.url
});
}
const loadTextures = function(textures) {
return new Promise((resolve, reject) => {
const loadTexture = (pointer) => {
if(pointer >= textures.length || pointer > 10) {
resolve(textures);
return;
};
const imageObject = textures[pointer];
const p = loadImage(imageObject);
p.then(
(result) => {
twodWebGL.addTexture(result.name, result.type, result.img);
},
(error) => {
console.log('error', error)
}).finally((e) => {
loadTexture(pointer+1);
});
}
loadTexture(0);
});
}
loadTextures(textures).then(
(result) => {
twodWebGL.initTextures();
// twodWebGL.render();
twodWebGL.running = true;
},
(error) => {
console.log('error');
}
);
<script src="https://codepen.io/shubniggurath/pen/aPxLMx"></script>
body {
margin:0;
}
canvas {
position: fixed;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment