Skip to content

Instantly share code, notes, and snippets.

@vkuchinov
Last active July 17, 2022 09:23
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 vkuchinov/56aebc7ef741ea6a544c36a22e572d54 to your computer and use it in GitHub Desktop.
Save vkuchinov/56aebc7ef741ea6a544c36a22e572d54 to your computer and use it in GitHub Desktop.
THREE.JS | GLSL Downshifted version of Polygon Shredder by by Jaume Sanchez

A donwshifted version of Polygon Shredder by Jaume Sanchez. https://github.com/spite/polygon-shredder

I have switched polygon boxes (There are 3 faces * 2 triangles * 3 vertices, so it's 18 vertices per each box) to simple THREE.Points() geometry with just one vertex.

/*
GENERATIVE ABSTRACT BACKGROUND PROOF-OF-CONCEPT
based on https://github.com/spite/polygon-shredder by Jaume Sanchez
@author Vladimir V. KUCHINOV
@helloworld@vkuchinov.co.uk
*/
var config = {
camera: new THREE.Vector3(0, 0, -5),
background: "#1D3557",
colors: ["#457B9D", "#A8DADC", "#F1FAEE", "#E63946"]
};
var scale = 0, nScale = 1;
var params = {
type: 2,
spread: 4,
factor: .5,
evolution: .5,
rotation: .5,
radius: 2,
pulsate: false,
scaleX: 1.0,
scaleY: 1.0,
scaleZ: 1.0,
scale: 1.0
};
var blob = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFyGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNi4wLWMwMDIgNzkuMTY0MzYwLCAyMDIwLzAyLzEzLTAxOjA3OjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTA4LTEwVDExOjI2OjIwKzAzOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTA4LTEwVDExOjI2OjIwKzAzOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMC0wOC0xMFQxMToyNjoyMCswMzowMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxYmM1YTk4OC0yYWFmLTc0NGQtYmZiMS1mMWQ4YmZhZDgxM2EiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo4YTg0NjRlNC1mYTVmLWRmNGYtOWY0Yy04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";
var t = new THREE.Clock();
var m = new THREE.Matrix4();
var v = new THREE.Vector3();
var nOffset = new THREE.Vector3( 0, 0, 0 );
var tmpVector = new THREE.Vector3();
var isMobile = false;
var current = "intro", renderer, scene, camera, controls, curlNoiseModel, particles, particleGLSL, pointGLSL, points, shadowParticleGLSL, shadowCamera, shadowBuffer, shadowBufferSize = 128;
var diffuseData, diffuseTexture, light, encasing;
function CurlNoise(renderer_, width_, height_ ) {
this.width = width_;
this.height = height_;
this.renderer = renderer_;
this.targetPos = 0;
this.data = new Float32Array( this.width * this.height * 4 );
var r = 1;
for( var i = 0, l = this.width * this.height; i < l; i ++ ) {
var phi = Math.random() * 2 * Math.PI;
var costheta = Math.random() * 2 -1;
var theta = Math.acos( costheta );
r = .85 + .15 * Math.random();
this.data[ i * 4 ] = r * Math.sin( theta) * Math.cos( phi );
this.data[ i * 4 + 1 ] = r * Math.sin( theta) * Math.sin( phi );
this.data[ i * 4 + 2 ] = r * Math.cos( theta );
this.data[ i * 4 + 3 ] = Math.random() * 100; // frames life
}
var floatType = isMobile ? THREE.HalfFloatType : THREE.FloatType;
this.texture = new THREE.DataTexture( this.data, this.width, this.height, THREE.RGBAFormat, THREE.FloatType );
this.texture.minFilter = THREE.NearestFilter;
this.texture.magFilter = THREE.NearestFilter;
this.texture.needsUpdate = true;
this.rtTexturePos = new THREE.WebGLRenderTarget( this.width, this.height, {
wrapS: THREE.ClampToEdgeWrapping,
wrapT: THREE.ClampToEdgeWrapping,
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat,
type: floatType,
stencilBuffer: false,
depthBuffer: false,
generateMipmaps: false
});
this.targets = [ this.rtTexturePos, this.rtTexturePos.clone() ];
this.simulationShader = new THREE.ShaderMaterial({
uniforms: {
active: { type: 'f', value: 1 },
width: { type: "f", value: this.width },
height: { type: "f", value: this.height },
oPositions: { type: "t", value: this.texture },
tPositions: { type: "t", value: null },
timer: { type: "f", value: 0 },
delta: { type: "f", value: 0 },
speed: { type: "f", value: .5 },
reset: { type: 'f', value: 0 },
offset: { type: 'v3', value: new THREE.Vector3( 0, 0, 0 ) },
genScale: { type: 'f', value: 1 },
factor: { type: 'f', value: .5 },
evolution: { type: 'f', value: .5 },
inverseModelViewMatrix: { type: 'm4', value: new THREE.Matrix4() },
radius: { type: 'f', value: 2 }
},
vertexShader: document.getElementById('texture_vertex_simulation_shader').textContent,
fragmentShader: document.getElementById('texture_fragment_simulation_shader').textContent,
side: THREE.DoubleSide
});
this.simulationShader.uniforms.tPositions.value = this.texture;
this.rtScene = new THREE.Scene();
this.rtCamera = new THREE.OrthographicCamera( -this.width / 2, this.width / 2, -this.height / 2, this.height / 2, -500, 1000 );
this.rtQuad = new THREE.Mesh(
new THREE.PlaneBufferGeometry( this.width, this.height ),
this.simulationShader
);
this.rtScene.add( this.rtQuad );
this.renderer.setRenderTarget(this.rtTexturePos)
this.renderer.render( this.rtScene, this.rtCamera);
this.renderer.setRenderTarget(null);
this.plane = new THREE.Mesh( new THREE.PlaneGeometry( 64, 64 ), new THREE.MeshBasicMaterial( { map: this.rtTexturePos.texture, side: THREE.DoubleSide } ) );
}
CurlNoise.prototype.render = function( time_, delta_ ) {
this.simulationShader.uniforms.timer.value = time_;
this.simulationShader.uniforms.delta.value = delta_;
this.simulationShader.uniforms.tPositions.value = this.targets[ this.targetPos ].texture;
this.targetPos = 1 - this.targetPos;
this.renderer.setRenderTarget( this.targets[ this.targetPos ] );
this.renderer.render( this.rtScene, this.rtCamera);
this.renderer.setRenderTarget(null);
}
inits();
function inits(){
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.background = new THREE.Color(config.background);
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(config.camera.x, config.camera.y, config.camera.z);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enabled = false;
var s = 15;
shadowCamera = new THREE.OrthographicCamera( -s, s, s, -s, .1, 20 );
shadowCamera.position.set( 10, 4, 10 );
shadowCamera.lookAt( scene.position );
shadowBuffer = new THREE.WebGLRenderTarget( shadowBufferSize, shadowBufferSize, {
wrapS: THREE.ClampToEdgeWrapping,
wrapT: THREE.ClampToEdgeWrapping,
minFilter: isMobile.any? THREE.NearestFilter : THREE.LinearMipMapLinear,
magFilter: isMobile.any? THREE.NearestFilter : THREE.LinearFilter,
format: THREE.RGBAFormat
});
curlNoiseModel = new CurlNoise( renderer, shadowBufferSize, shadowBufferSize);
particles = new THREE.Object3D();
//scene.add(particles);
var N = shadowBufferSize * shadowBufferSize * 3, vertices = [], colors = [];
for (let i = 0; i < N; i += 3 ) {
vertices.push(...[0.0, 0.0, 0.0]);
var c = new THREE.Color(interpolateColors(i / 3, N / 3));
colors.push(...[c.r, c.g, c.b]);
}
var inUVs = [];
for(var x = 0; x < shadowBufferSize; x++){
for(var y = 0; y < shadowBufferSize; y++){
inUVs.push(remapFloat(x, 0, shadowBufferSize, 0.0, 1.0));
inUVs.push(remapFloat(y, 0, shadowBufferSize, 0.0, 1.0));
}
}
var pointsGeometry = new THREE.BufferGeometry();
pointsGeometry.addAttribute("position", new THREE.BufferAttribute(new Float32Array(vertices), 3));
pointsGeometry.addAttribute("inUV", new THREE.BufferAttribute(new Float32Array(inUVs), 2));
pointsGeometry.addAttribute("color", new THREE.BufferAttribute(new Float32Array(colors), 3));
var pointGLSL = new THREE.ShaderMaterial({
uniforms: {
blob: {
type: "t",
value: new THREE.TextureLoader().load(blob)
},
updatedPosition: {
type: "t",
value:curlNoiseModel.rtTexturePos.texture
},
size: {
type: "f",
value: 0.15
},
scale: {
value: window.innerHeight / 2
}
},
vertexShader: document.getElementById('vs-points').textContent,
fragmentShader: document.getElementById('fs-points').textContent,
transparent: true,
depthTest : true,
alphaTest: 0.9
});
//pointGLSL.extensions.fragDepth = true;
//pointGLSL.extensions.drawBuffers = true;
points = new THREE.Points(pointsGeometry, pointGLSL);
scene.add(points);
window.addEventListener( 'resize', onWindowResize, false );
animate();
}
function animate(){
controls.update();
scale += ( nScale - scale ) * .1;
var delta = t.getDelta() * 10;
var time = t.elapsedTime;
var r = 3;
nOffset.set( r * Math.sin( time ), r * Math.cos( .9 * time ), 0 );
tmpVector.copy( nOffset );
tmpVector.sub( curlNoiseModel.simulationShader.uniforms.offset.value );
tmpVector.multiplyScalar( .1 );
curlNoiseModel.simulationShader.uniforms.offset.value.add( tmpVector );
curlNoiseModel.simulationShader.uniforms.factor.value = params.factor;
curlNoiseModel.simulationShader.uniforms.evolution.value = params.evolution;
curlNoiseModel.simulationShader.uniforms.radius.value = params.pulsate ? ( .5 + .5 * Math.cos( time ) ) * params.radius : params.radius;
if( curlNoiseModel.simulationShader.uniforms.active.value ) { particles.rotation.y = params.rotation * time; }
m.copy( particles.matrixWorld );
curlNoiseModel.simulationShader.uniforms.inverseModelViewMatrix.value.getInverse( m );
curlNoiseModel.simulationShader.uniforms.genScale.value = scale;
if( curlNoiseModel.simulationShader.uniforms.active.value === 1 ) { curlNoiseModel.render( time, delta ); }
points.material.uniforms.updatedPosition.value = curlNoiseModel.targets[ curlNoiseModel.targetPos ].texture;
renderer.setClearColor( 0 );
particles.material = shadowParticleGLSL;
renderer.setRenderTarget(shadowBuffer);
renderer.render(scene, shadowCamera);
renderer.setRenderTarget(null);
tmpVector.copy( scene.position );
tmpVector.sub( shadowCamera.position );
tmpVector.normalize();
m.makeRotationY( -particles.rotation.y );
v.copy( shadowCamera.position );
v.applyMatrix4( m );
renderer.setClearColor( 0xFFFFFF );
renderer.render( scene, camera );
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function interpolateColors(i_, n_){
var colorPosition = remapFloat(i_, 0, n_, 0, 3);
var startColor = Math.floor(colorPosition);
var endColor = Math.ceil(colorPosition);
var t = colorPosition - startColor;
return lerpHexColors(config.colors[startColor], config.colors[endColor], t);
}
function lerpHexColors(hex0_, hex1_, t_) {
var ah = parseInt(hex0_.replace(/#/g, ''), 16),
ar = ah >> 16, ag = ah >> 8 & 0xff, ab = ah & 0xff,
bh = parseInt(hex1_.replace(/#/g, ''), 16),
br = bh >> 16, bg = bh >> 8 & 0xff, bb = bh & 0xff,
rr = ar + t_ * (br - ar),
rg = ag + t_ * (bg - ag),
rb = ab + t_ * (bb - ab);
return '#' + ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1);
}
function remapFloat(v_, min0_, max0_, min1_, max1_) { return min1_ + (v_ - min0_) / (max0_ - min0_) * (max1_ - min1_); }
function hexToRGB(hex_) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex_);
return result ? {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255
} : null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Particle Clover [PoC] downshifted version of Polygon Shredder by Jaume Sanchez</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src="https://unpkg.com/three@0.106.0/build/three.min.js"></script>
<script src="https://unpkg.com/three@0.106.0/examples/js/controls/OrbitControls.js"></script>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script id="texture_vertex_simulation_shader" type="x-shader/x-vertex">
varying vec2 vUv;
varying vec3 vOffset;
uniform vec3 offset;
uniform mat4 inverseModelViewMatrix;
void main() {
vOffset = ( inverseModelViewMatrix * vec4( offset, 1. ) ).xyz;
vUv = vec2(uv.x, 1.0 - uv.y);
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="texture_fragment_simulation_shader" type="x-shader/x-fragment">
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
//
vec3 mod289(vec3 x_) { return x_ - floor(x_ * (1.0 / 289.0)) * 289.0; }
vec4 mod289(vec4 x_) { return x_ - floor(x_ * (1.0 / 289.0)) * 289.0; }
vec4 permute(vec4 x_) { return mod289(((x_ * 34.0) + 1.0) * x_); }
vec4 taylorInvSqrt(vec4 r_){ return 1.79284291400159 - 0.85373472095314 * r_; }
float snoise(vec3 v_) {
const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
vec3 i = floor(v_ + dot(v_, C.yyy) );
vec3 x0 = v_ - i + dot(i, C.xxx);
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy;
vec3 x3 = x0 - D.yyy;
i = mod289(i);
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
float n_ = 0.142857142857;
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z);
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ );
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
vec4 s0 = floor(b0) * 2.0 + 1.0;
vec4 s1 = floor(b1) * 2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww ;
vec3 p0 = vec3(a0.xy, h.x);
vec3 p1 = vec3(a0.zw, h.y);
vec3 p2 = vec3(a1.xy, h.z);
vec3 p3 = vec3(a1.zw, h.w);
vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
}
vec3 snoiseVec3( vec3 x_ ){
float s = snoise(vec3( x_ ));
float s1 = snoise(vec3( x_.y - 19.1 , x_.z + 33.4 , x_.x + 47.2 ));
float s2 = snoise(vec3( x_.z + 74.2 , x_.x - 124.5 , x_.y + 99.4 ));
vec3 c = vec3( s , s1 , s2 );
return c;
}
vec3 curlNoise( vec3 p_ ){
const float e = .1;
vec3 dx = vec3( e , 0.0 , 0.0 );
vec3 dy = vec3( 0.0 , e , 0.0 );
vec3 dz = vec3( 0.0 , 0.0 , e );
vec3 p_x0 = snoiseVec3( p_ - dx );
vec3 p_x1 = snoiseVec3( p_ + dx );
vec3 p_y0 = snoiseVec3( p_ - dy );
vec3 p_y1 = snoiseVec3( p_ + dy );
vec3 p_z0 = snoiseVec3( p_ - dz );
vec3 p_z1 = snoiseVec3( p_ + dz );
float x = p_y1.z - p_y0.z - p_z1.y + p_z0.y;
float y = p_z1.x - p_z0.x - p_x1.z + p_x0.z;
float z = p_x1.y - p_x0.y - p_y1.x + p_y0.x;
const float divisor = 1.0 / ( 2.0 * e );
return normalize( vec3( x , y , z ) * divisor );
}
varying vec2 vUv;
varying vec3 vOffset;
uniform float active;
uniform sampler2D tPositions;
uniform sampler2D oPositions;
uniform float width;
uniform float height;
uniform vec3 offset;
uniform float timer;
uniform float delta;
uniform float speed;
uniform float reset;
uniform float genScale;
uniform float factor;
uniform float evolution;
uniform float radius;
mat4 rotationMatrix(vec3 axis_, float angle_) {
axis_ = normalize(axis_);
float s = sin(angle_);
float c = cos(angle_);
float oc = 1.0 - c;
return mat4(oc * axis_.x * axis_.x + c, oc * axis_.x * axis_.y - axis_.z * s, oc * axis_.z * axis_.x + axis_.y * s, 0.0,
oc * axis_.x * axis_.y + axis_.z * s, oc * axis_.y * axis_.y + c, oc * axis_.y * axis_.z - axis_.x * s, 0.0,
oc * axis_.z * axis_.x - axis_.y * s, oc * axis_.y * axis_.z + axis_.x * s, oc * axis_.z * axis_.z + c, 0.0,
0.0, 0.0, 0.0, 1.0);
}
void main() {
vec4 c = texture2D( tPositions, vUv );
vec3 pos = c.xyz;
float life = c.a;
float s = vUv.x * life / 100.;
float speedInc = 1.;
if( s > .95 ) speedInc = .75;
else if( s > .9 ) speedInc = .85;
else speedInc = 1.;
vec3 v = factor * speedInc * delta * speed * ( curlNoise( .2 * pos + factor * evolution * .1 * timer ));
pos += v;
life -= factor * 1.;
if( length( pos ) < radius ) { pos = normalize( pos ) * radius; }
if( life <= 0. || reset == 1. ) {
pos = ( rotationMatrix( vec3( 1., 0., 0. ), timer ) * texture2D( oPositions, vUv ) ).xyz + vOffset;
life = 100.;
}
gl_FragColor = vec4( pos, life );
}
</script>
<script type='x-shader/x-vertex' id='vs-points'>
attribute vec3 color;
attribute vec2 inUV;
uniform float size;
uniform float scale;
uniform sampler2D updatedPosition;
varying vec3 vColor;
void main() {
vColor = color;
vec3 pos = texture2D(updatedPosition, inUV).xyz;
vec4 mvPosition = modelViewMatrix * vec4( pos, 1.0 );
gl_PointSize = size * ( scale / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type='x-shader/x-fragment' id='fs-points'>
varying vec3 vColor;
uniform sampler2D blob;
void main() {
gl_FragColor = vec4(vColor, 1.0);
gl_FragColor = gl_FragColor * texture2D(blob, gl_PointCoord);
if (gl_FragColor.a < 0.1) discard;
}
</script>
<script src="app.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment