Skip to content

Instantly share code, notes, and snippets.

@Ashon-G
Created August 22, 2024 01:42
Show Gist options
  • Save Ashon-G/34bf94d2927aebd4cc6223736e0bc972 to your computer and use it in GitHub Desktop.
Save Ashon-G/34bf94d2927aebd4cc6223736e0bc972 to your computer and use it in GitHub Desktop.
Stripe header - wtc-gl
<script type="text/fragment" id="fragShader">#version 300 es
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
uniform sampler2D s_noise;
uniform sampler2D b_noise;
in vec2 v_uv;
in vec3 c;
in vec3 v_n;
in vec3 v_pos;
out vec4 colour;
vec2 getScreenSpace() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x);
return uv;
}
void main() {
vec2 uv = getScreenSpace();
uv *= 1.;
colour = vec4(c,1);
/*
vec3 lightPos = vec3(3., -3., 1.);
vec3 ray = normalize(vec3(uv, 1.));
vec3 normal = normalize( cross( dFdx( v_pos ), dFdy( v_pos ) ) );
vec3 lightV = lightPos - v_pos;
float lightDist = max(length(lightV), 0.001);
lightV /= lightDist;
vec3 lightColour = vec3(.8, .8, 1.);
float shininess = .3;
float brightness = .3;
float roughness = 2.;
float falloff = 0.6;
float attenuation = 1./(1.0 + lightDist*lightDist*falloff);
float diffuse = max(dot(normal, lightV), 0.);
float specular = pow(max(dot( reflect(-lightV, normal), -ray), 0.), 10.) * shininess;
// colour *= min(1., diffuse + .9);
*/
}
</script>
<script type="text/vertex" id="vertShader">#version 300 es
in vec3 position;
in vec2 uv;
in vec3 normal;
out vec2 v_uv;
out vec3 v_n;
out vec3 v_pos;
out vec3 c;
uniform float u_time;
uniform vec2 u_resolution;
uniform vec2 u_position;
uniform float u_zoom;
vec3 pal( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d )
{
return a + b*cos( 6.28318*(c*t+d) );
}
/* discontinuous pseudorandom uniformly distributed in [-0.5, +0.5]^3 */
vec3 random3(vec3 c) {
float j = 4096.0*sin(dot(c,vec3(17.0, 59.4, 15.0)));
vec3 r;
r.z = fract(512.0*j);
j *= .125;
r.x = fract(512.0*j);
j *= .125;
r.y = fract(512.0*j);
return r-0.5;
}
/* skew constants for 3d simplex functions */
const float F3 = 0.3333333;
const float G3 = 0.1666667;
/* 3d simplex noise */
float simplex3d(vec3 p) {
/* 1. find current tetrahedron T and it's four vertices */
/* s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices */
/* x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertices*/
/* calculate s and x */
vec3 s = floor(p + dot(p, vec3(F3)));
vec3 x = p - s + dot(s, vec3(G3));
/* calculate i1 and i2 */
vec3 e = step(vec3(0.0), x - x.yzx);
vec3 i1 = e*(1.0 - e.zxy);
vec3 i2 = 1.0 - e.zxy*(1.0 - e);
/* x1, x2, x3 */
vec3 x1 = x - i1 + G3;
vec3 x2 = x - i2 + 2.0*G3;
vec3 x3 = x - 1.0 + 3.0*G3;
/* 2. find four surflets and store them in d */
vec4 w, d;
/* calculate surflet weights */
w.x = dot(x, x);
w.y = dot(x1, x1);
w.z = dot(x2, x2);
w.w = dot(x3, x3);
/* w fades from 0.6 at the center of the surflet to 0.0 at the margin */
w = max(0.6 - w, 0.0);
/* calculate surflet components */
d.x = dot(random3(s), x);
d.y = dot(random3(s + i1), x1);
d.z = dot(random3(s + i2), x2);
d.w = dot(random3(s + 1.0), x3);
/* multiply d by w^4 */
w *= w;
w *= w;
d *= w;
/* 3. return the sum of the four surflets */
return dot(d, vec4(52.0));
}
vec2 getScreenSpace() {
vec2 uv = (position.xy * u_resolution.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x);
return uv;
}
void main() {
vec2 tuv = getScreenSpace()*.8*u_zoom+u_position*2.;
// tuv = floor(tuv*5.)/5.;
float n = simplex3d(vec3(tuv, u_time*2.));
float nc = n;
n += simplex3d(vec3(tuv+4.7, u_time)*2.)*.5;
n *= .9;
// float n1 = simplex3d(vec3(tuv+10., u_time*2.));
vec3 pos = position * vec3(u_resolution.xy, 1.);
pos.z -= n*.5+.5;
// pos /= vec3(u_resolution.xy, 1.);
pos.y += n/u_zoom*.5*min(u_resolution.y, u_resolution.x);
// pos.x += nc/u_zoom*.5*min(u_resolution.y, u_resolution.x);
pos /= vec3(u_resolution.xy, 1.);
c = pal( nc*%%rn%%+(pos.y+u_position.y/u_zoom)*.15+u_time, vec3(.7),vec3(.3),vec3(1.0,.95,.9),vec3(0.0,0.33,0.67) );
gl_Position = vec4(pos, 1.0);
v_uv = uv;
v_pos = pos.xyz;
// v_n = normal + vec3(0,0,n);
}
</script>
import {
Renderer,
Program,
Mesh,
Plane,
Uniform,
} from 'https://cdn.skypack.dev/[email protected]';
import { Vec2, Vec3, Vec4, Mat2, Mat3, Mat4, Quat } from 'https://cdn.skypack.dev/wtc-math';
const vertex = document.getElementById('vertShader').innerText.replace('%%rn%%', `${.1+Math.random()*.3}+${Math.random()*Math.PI}`);
const fragment = document.getElementById('fragShader').innerText;
console.clear()
class StripeHeader {
uniforms
dimensions
autoResize = true
onBeforeRender
onAfterRender
u_time
u_resolution
gl
renderer
program
mesh
lastTime = 0
constructor({
vertex,
fragment,
dimensions = new Vec2(window.innerWidth, window.innerHeight),
container = document.body,
autoResize = true,
uniforms = {},
onInit = (renderer) => {},
onBeforeRender = (t) => {},
onAfterRender = (t) => {},
rendererProps = {}
} = {}) {
this.onBeforeRender = onBeforeRender.bind(this)
this.onAfterRender = onAfterRender.bind(this)
this.render = this.render.bind(this)
this.resize = this.resize.bind(this)
this.autoResize = autoResize
this.dimensions = dimensions
this.u_time = new Uniform({ name: 'time', value: 0, kind: 'float' })
this.u_resolution = new Uniform({
name: 'resolution',
value: this.dimensions.array,
kind: 'float_vec2'
})
this.uniforms = Object.assign({}, uniforms, {
u_time: this.u_time,
u_resolution: this.u_resolution
})
this.renderer = new Renderer(rendererProps)
onInit(this.renderer)
this.gl = this.renderer.gl
container.appendChild(this.gl.canvas)
this.gl.clearColor(1, 1, 1, 1)
if (this.autoResize) {
window.addEventListener('resize', this.resize, false)
this.resize()
} else {
this.renderer.dimensions = dimensions
this.u_resolution.value = this.dimensions.scaleNew(
this.renderer.dpr
).array
}
const geometry = new Plane(this.gl, {
width: 3,
height: 3,
widthSegments: Math.floor(window.innerWidth / 5),
heightSegments: Math.floor(window.innerHeight / 5),
});
this.program = new Program(this.gl, {
vertex,
fragment,
uniforms: this.uniforms
})
this.mesh = new Mesh(this.gl, { geometry, program: this.program })
this.playing = true
}
resize() {
this.dimensions = new Vec2(window.innerWidth, window.innerHeight)
this.u_resolution.value = this.dimensions.scaleNew(this.renderer.dpr).array
this.renderer.dimensions = this.dimensions
const geometry = new Plane(this.gl, {
width: 3,
height: 3,
widthSegments: Math.floor(window.innerWidth / 5),
heightSegments: Math.floor(window.innerHeight / 5),
});
this.mesh = new Mesh(this.gl, { geometry, program: this.program })
}
resetTime() {
this.lastTime = 0;
}
render(t) {
const diff = t - this.lastTime
this.lastTime = t
if (this.playing) {
requestAnimationFrame(this.render)
}
const v = this.u_time.value
this.u_time.value = v + diff * 0.00005
// console.log(this.u_time)
this.onBeforeRender(t)
if (this.post) this.post.render(this.renderer, { scene: this.mesh })
else this.renderer.render({ scene: this.mesh })
this.onAfterRender(t)
}
#post
set post(p) {
if (p.render) {
this.#post = p
}
}
get post() {
return this.#post || null
}
_playing = false;
set playing(v) {
if (this._playing !== true && v === true) {
requestAnimationFrame(this.render)
this._playing = true
} else {
this.lastTime = 0
this._playing = false
}
}
get playing() {
return this._playing === true
}
}
// Create the fragment shader wrapper
const FSWrapper = new StripeHeader({
fragment,
vertex
});
const { gl, uniforms } = FSWrapper;
let angle = 0.;
uniforms.u_position = new Uniform({
name: "position",
value: [0,2],
kind: "vec2"
});
uniforms.u_zoom = new Uniform({
name: "zoom",
value: 1.,
kind: "float"
});
uniforms.u_rotation = new Uniform({
name: "rotation",
value: angle,
kind: "float"
});
let zoom = uniforms.u_zoom.value;
let tzoom = 1.;
let velocity = new Vec2(0,0);
let lastmouse = new Vec2(0,0);
let startmouse = new Vec2(0,0);
let startrotation = angle;
let rotation = angle;
let rotationVelocity;
let pointerdown = false;
let keys = {
rotation: false
}
let rotating = false;
let zooming = false;
window.addEventListener('keydown', (e) => {
// console.log(e.key)
if(e.key === 'Control') {
keys.rotation = true;
}
e.preventDefault();
});
window.addEventListener('keyup', (e) => {
if(e.key === 'Control') {
keys.rotation = false;
}
e.preventDefault();
});
// window.addEventListener('wheel', (e) => {
// tzoom += e.deltaY * 0.001 * (uniforms.u_zoom.value);
// tzoom = Math.min(5., Math.max(tzoom, .01));
// });
window.addEventListener('pointerdown', (e)=> {
if(!keys.rotation) {
pointerdown = true;
lastmouse = new Vec2(e.x,e.y);
} else {
rotating = true;
const thismouse = new Vec2(e.x,e.y);
startrotation = rotation + new Vec2(window.innerWidth*.5, window.innerHeight*.5).subtract(thismouse).angle;
}
startmouse = lastmouse.clone();
});
window.addEventListener('pointerup', (e)=> {
pointerdown = false;
rotating = false;
});
window.addEventListener('pointermove', (e)=> {
if(zooming) return;
if(rotating) {
const thismouse = new Vec2(e.x,e.y);
rotation = startrotation - new Vec2(window.innerWidth*.5, window.innerHeight*.5).subtract(thismouse).angle;
// rotation = (thismouse.subtractNew(new Vec2(window.innerWidth, window.innerHeight))).angle;
} else if(pointerdown) {
const thismouse = new Vec2(e.x,e.y);
let dd = 1./Math.min(window.innerWidth, window.innerHeight);
dd *= uniforms.u_zoom.value;
const diff = lastmouse.subtract(thismouse);
const c = Math.cos(uniforms.u_rotation.value);
const s = Math.sin(uniforms.u_rotation.value);
const mat = new Mat2(c, s, -s, c);
// velocity.transformByMat2(mat);
velocity = diff.clone();
uniforms.u_position.value = new Vec2(...uniforms.u_position.value).add(diff.transformByMat2New(mat).multiply(new Vec2(dd, -dd))).array;
lastmouse = thismouse;
}
});
const runmouse = function(d) {
const scalar = pointerdown ? .1 : .98;
if(velocity.length > 0.01) {
velocity.scale(scalar);
const c = Math.cos(uniforms.u_rotation.value);
const s = Math.sin(uniforms.u_rotation.value);
const mat = new Mat2(c, s, -s, c);
// velocity.transformByMat2(mat);
let dd = 1./Math.min(window.innerWidth, window.innerHeight);
dd *= uniforms.u_zoom.value;
uniforms.u_position.value = new Vec2(...uniforms.u_position.value).add(velocity.transformByMat2New(mat).multiplyNew(new Vec2(dd, -dd))).array;
}
zoom += (tzoom - zoom) * .1;
uniforms.u_zoom.value = zoom;
// uniforms.u_rotation.value += (velocity.angle-Math.PI) * .0001 * Math.min(velocity.length, 1.);
uniforms.u_rotation.value = rotation;
requestAnimationFrame(runmouse);
}
requestAnimationFrame(runmouse);
body {
background: #333;
color: #fff;
font-family: sans-serif;
}
body,
html {
margin: 0;
overflow: hidden;
padding: 0;
}
canvas { width:100%; height: 100%; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment