A Pen by Vashon Gonzales on CodePen.
Created
August 22, 2024 01:42
-
-
Save Ashon-G/34bf94d2927aebd4cc6223736e0bc972 to your computer and use it in GitHub Desktop.
Stripe header - wtc-gl
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
<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> |
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
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); |
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
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