179 lines
4.9 KiB
JavaScript
179 lines
4.9 KiB
JavaScript
|
console.clear();
|
||
|
|
||
|
import { Vec2, Vec3, Vec4, Mat2, Mat3, Mat4, Quat } from 'https://cdn.skypack.dev/wtc-math';
|
||
|
import {
|
||
|
Camera,
|
||
|
Renderer,
|
||
|
Mesh,
|
||
|
Program,
|
||
|
Geometry,
|
||
|
Triangle,
|
||
|
FragmentShader,
|
||
|
RenderTarget,
|
||
|
GeometryAttribute,
|
||
|
Framebuffer,
|
||
|
Uniform, Texture,
|
||
|
ParticleSimulation } from 'https://cdn.skypack.dev/wtc-gl@1.0.0-beta.33';
|
||
|
|
||
|
const setup = function () {
|
||
|
// Simulation dimensions
|
||
|
const px = Math.min(window.devicePixelRatio, 2);
|
||
|
const dimensions = [window.innerWidth, window.innerHeight];
|
||
|
|
||
|
const t = new ParticleSimulation({
|
||
|
rendererProps: {},
|
||
|
textureSize: 128,
|
||
|
simDimensions: 2,
|
||
|
vertex: document.querySelector('#vertexShader_particle').innerText,
|
||
|
fragment: document.querySelector('#fragmentShader_particle').innerText,
|
||
|
uniforms: {
|
||
|
'b_position': new Uniform({
|
||
|
name: 'position',
|
||
|
value: null,
|
||
|
kind: 'texture' }),
|
||
|
|
||
|
'b_velocity': new Uniform({
|
||
|
name: 'velocity',
|
||
|
value: null,
|
||
|
kind: 'texture' }) },
|
||
|
|
||
|
|
||
|
onBeforeRender: function (t, system) {
|
||
|
|
||
|
this.uniforms['b_position'].value = positionBuffer.read.texture;
|
||
|
|
||
|
// this.uniforms['s_data'] = new Uniform({ name: 'data', value: particleTexture, type: 'texture' });
|
||
|
|
||
|
this.uniforms['u_resolution'].value = [positionBuffer.width, positionBuffer.height];
|
||
|
// positionBuffer.read;
|
||
|
positionBuffer.render(this.renderer, { scene: positionMesh });
|
||
|
|
||
|
this.uniforms['u_resolution'].value = this.dimensions.array;
|
||
|
} });
|
||
|
|
||
|
|
||
|
t.program.depthTest = false;
|
||
|
t.transparent = true;
|
||
|
t.program.setBlendFunc(t.gl.SRC_ALPHA, t.gl.ONE_MINUS_SRC_ALPHA);
|
||
|
|
||
|
window.addEventListener('keyup', e => {
|
||
|
if (e.key === " ") {
|
||
|
t.playing = !t.playing;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const { gl, textureSize, particles, uniforms, renderer } = t;
|
||
|
|
||
|
const dpr = renderer.dpr;
|
||
|
|
||
|
// gl.clearColor(0.08, 0.1, 0.15, 0.);
|
||
|
gl.clearColor(0.98, 0.99, 0.35, 1.);
|
||
|
|
||
|
const positionData = new Float32Array(particles * 4).fill(0);
|
||
|
const particleData = new Float32Array(particles * 4).fill(0);
|
||
|
for (let i = 0; i < positionData.length; i += 4) {
|
||
|
positionData[i] = window.innerWidth * .5 * dpr;
|
||
|
positionData[i + 1] = Math.random() * 200 - 100 + window.innerHeight * .5 * dpr;
|
||
|
positionData[i + 2] = Math.random() - .5;
|
||
|
positionData[i + 3] = Math.random() - .5;
|
||
|
|
||
|
particleData[i] = Math.random();
|
||
|
particleData[i + 1] = 1. - Math.random() * 1.5;
|
||
|
particleData[i + 2] = 0;
|
||
|
particleData[i + 3] = 0;
|
||
|
}
|
||
|
|
||
|
const particleTexture = new Texture(gl, {
|
||
|
data: particleData,
|
||
|
width: textureSize,
|
||
|
height: textureSize,
|
||
|
minFilter: gl.NEAREST,
|
||
|
magFilter: gl.NEAREST,
|
||
|
generateMipmaps: false,
|
||
|
type: gl.FLOAT,
|
||
|
internalFormat: gl.RGBA16F });
|
||
|
|
||
|
uniforms.s_data = new Uniform({ name: 'data', value: particleTexture, kind: 'texture' });
|
||
|
const positionBuffer = new Framebuffer(gl, {
|
||
|
name: 'position',
|
||
|
width: textureSize,
|
||
|
height: textureSize,
|
||
|
dpr: 1,
|
||
|
data: positionData,
|
||
|
texdepth: Framebuffer.TEXTYPE_FLOAT,
|
||
|
minFilter: gl.NEAREST });
|
||
|
|
||
|
const defaultShaderV = `
|
||
|
attribute vec3 position;
|
||
|
attribute vec2 uv;
|
||
|
varying vec2 v_uv;
|
||
|
void main() {
|
||
|
gl_Position = vec4(position, 1.0);
|
||
|
v_uv = uv;
|
||
|
}`;
|
||
|
const geometry = new Triangle(gl);
|
||
|
const positionProgram = new Program(gl, {
|
||
|
vertex: defaultShaderV,
|
||
|
fragment: document.getElementById('fragmentShader_position').innerText,
|
||
|
uniforms: uniforms });
|
||
|
|
||
|
const bufferResolution = new Uniform({
|
||
|
name: 'resolution',
|
||
|
value: [textureSize, textureSize],
|
||
|
kind: "vec2" });
|
||
|
|
||
|
positionProgram.uniforms.u_resolution = bufferResolution;
|
||
|
uniforms.u_screen = new Uniform({
|
||
|
name: 'screen',
|
||
|
value: [window.innerWidth, window.innerHeight],
|
||
|
kind: "vec2" });
|
||
|
|
||
|
window.addEventListener('resize', e => {
|
||
|
uniforms.u_screen.value = [window.innerWidth, window.innerHeight];
|
||
|
});
|
||
|
|
||
|
const positionMesh = new Mesh(gl, { geometry, program: positionProgram });
|
||
|
|
||
|
// Set up mouse uniforms
|
||
|
(function () {
|
||
|
const tarmouse = new Vec4(0, 0, 0, 0);
|
||
|
const curmouse = tarmouse.clone();
|
||
|
let pointerdown = false;
|
||
|
|
||
|
uniforms.u_mouse = new Uniform({
|
||
|
name: 'mouse',
|
||
|
value: tarmouse.array,
|
||
|
kind: 'vec4' });
|
||
|
|
||
|
document.body.addEventListener('pointermove', e => {
|
||
|
tarmouse.x = e.x;
|
||
|
tarmouse.y = window.innerHeight - e.y;
|
||
|
if (pointerdown) {
|
||
|
}
|
||
|
});
|
||
|
document.body.addEventListener('pointerdown', e => {
|
||
|
pointerdown = true;
|
||
|
if (e.button == 0) {
|
||
|
curmouse.z = 1.;
|
||
|
}
|
||
|
});
|
||
|
document.body.addEventListener('pointerup', e => {
|
||
|
pointerdown = false;
|
||
|
if (e.button == 0) {
|
||
|
curmouse.z = 0.;
|
||
|
}
|
||
|
});
|
||
|
let oldTime;
|
||
|
const animouse = d => {
|
||
|
const factor = d - oldTime;
|
||
|
oldTime = d;
|
||
|
const diff = tarmouse.xy.subtractNew(curmouse.xy);
|
||
|
curmouse.xy = curmouse.xy.add(diff.scale(1. / factor * 2.));
|
||
|
uniforms.u_mouse.value = curmouse.array;
|
||
|
requestAnimationFrame(animouse);
|
||
|
};
|
||
|
requestAnimationFrame(animouse);
|
||
|
})();
|
||
|
};
|
||
|
|
||
|
setup();
|