Published
Edited
Jul 19, 2019
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
funPart = `
vec4 sample = texture2D(positions, vec2(vUv.x, 1.0 - vUv.y));
vec3 pos = sample.xyz;
float lifetime = sample.a;

// increase lifetime by delta, cap it at 1 and start over
lifetime = mod(lifetime + delta, 1.0);

float x = floor(vUv.x * ${textureSize}.0);
float y = floor(vUv.y * ${textureSize}.0);
float index = x + y * ${textureSize}.0;
//lifetime = x;
float speed = 2.0;

if (x == 0.0) {
pos.x = cos(elapsedTime + index * speed) * (sin(elapsedTime * speed) * 40.0);
pos.z = sin(elapsedTime + index * speed) * (sin(elapsedTime * speed) * 40.0);
pos.y = -25.0;
pos.y += sin(elapsedTime * 2.0 + index * 3.25) * 2.0;

} else {
vec4 neighborLeft = texture2D(positions, vec2((vUv.x - (1.0 / ${textureSize}.0)), 1.0 - vUv.y));
pos.xyz = lerp(pos.xyz, neighborLeft.xyz, 0.003);
float gravity = 15.0;
pos.y -= gravity * delta - y/30.0;
}


gl_FragColor = vec4(pos.rgb, lifetime);`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function createRenderMaterial (textureSize) {
const textureLoader = new THREE.TextureLoader()
const material = new THREE.RawShaderMaterial( {
uniforms: {
time: { value: 1.0 },
orientation: {type: 'v4', value: new THREE.Quaternion()},
gpgpuOffsets: {type: 't', value: null },
mapper: textureLoader,
// map: new THREE.TextureLoader().load('https://i.imgur.com/h1v0P5s.jpg'),
colorBase: new THREE.Uniform(new THREE.Color(0xd9ff0e)),
colorStart: new THREE.Uniform(new THREE.Color(0x8674fd)),
colorPeak: new THREE.Uniform(new THREE.Color(0x0ed9ff)),
colorEnd: new THREE.Uniform(new THREE.Color(0x333333)),
},
// transparent: true,
// alpha: true,
side: THREE.DoubleSide,
// alphaTest: 0.1,
vertexShader: `
precision highp float;

#define PI 3.1415926536
#define PI2 6.28318530718

attribute vec3 position;
attribute vec3 offset;
attribute float scale;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;

uniform float time;

attribute vec2 uv;
varying vec2 vUv;
attribute float particleIndex;

uniform sampler2D gpgpuOffsets;
varying float vParticleIndex;

uniform vec4 orientation;
uniform sampler2D mapper;
varying vec4 vColor;

vec3 applyQuaternionToVector( vec4 q, vec3 v ){
return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );
}

void main(){
vec4 positions = texture2D(gpgpuOffsets, vec2(
mod(particleIndex-1.0, ${textureSize}.0)/${textureSize}.0,
floor((particleIndex-1.0)/${textureSize}.0)/${textureSize}.0)
);
float lifetime = positions.a;
float i = particleIndex - 1.0;
vec4 sample = texture2D(mapper, vec2(
mod(i, ${textureSize}.0) / ${textureSize}.0,
1.0 - i / ${textureSize}.0 / ${textureSize}.0
));
vec3 pos = position * vec3(scale * lifetime * 2.0, scale * lifetime * 2.0, 1.0);
pos = applyQuaternionToVector(orientation, pos);
pos = pos + offset + positions.xyz;

vParticleIndex = particleIndex;
vUv = vec2(uv.x, 1.0-uv.y);

vColor.xyz = sample.xyz;
// vColor.a = lifetime;
vColor.a = sample.a;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0 );
}
`,
fragmentShader: `
precision highp float;

varying vec4 vColor;
varying vec2 vUv;
varying float vParticleIndex;
varying vec2 vLifetime;

uniform float time;

uniform vec3 colorBase;
uniform vec3 colorStart;
uniform vec3 colorPeak;
uniform vec3 colorEnd;
uniform sampler2D mapper;

#define PI 3.1415926536
#define PI2 6.28318530718


float drawBase (in vec2 uv, in float min, in float max) {
float dist = sqrt(dot(uv, uv));
if (dist >= max || dist <= min) {
return 0.0;
}
float sm = smoothstep(max, max - 0.01, dist);
float sm2 = smoothstep(min, min - 0.01, dist);
float alpha = sm * sm2;
return (1.0-alpha);
}

void main() {
float alpha = drawBase(vUv - vec2(0.5), 0.0, 0.5);
// discard if not needed
if (alpha == 0.0) {
discard;
}

gl_FragColor = vColor;
}
`,
// side: THREE.DoubleSide,
side: THREE.FrontSide, // only front since the plane will always face the camera
transparent: true,
alphaTest: 0.1,
//blending: THREE.NormalBlending
//blending: THREE.MultiplyBlending
blending: THREE.AdditiveBlending
})
textureLoader.load(imageURI, (texture) => {
material.uniforms.mapper.value = texture
})
return material
}
Insert cell
Insert cell
Insert cell
Insert cell
THREE = {
const THREE = window.THREE = await require('three@0.105/build/three.min.js')
await require('three@0.105/examples/js/controls/OrbitControls.js').catch(() => {})
return THREE
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more