codepens/curl-noise/dist/script.js

279 lines
9.3 KiB
JavaScript
Raw Normal View History

2023-10-06 23:12:53 +02:00
// curl noise
// https://petewerner.blogspot.jp/2015/02/intro-to-curl-noise.html
// inspired by
// https://www.clicktorelease.com/code/polygon-shredder/
window.onload = () => {
var webgl = new Webgl();
window.onresize = () => {
webgl.resize();
};
};
class Webgl {
constructor() {
this.size = 128;
this.widthW = document.body.clientWidth;
this.heightW = window.innerHeight;
this.init();
}
init() {
this.container = document.getElementById("wrapper");
this.renderer = new THREE.WebGLRenderer({ antialias: true });
// renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setSize(this.widthW, this.heightW);
this.container.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
this.colorPallete = [
new THREE.Color(0x0d0232),
new THREE.Color(0xe50061),
new THREE.Color(0x1cafc0),
new THREE.Color(0xefcb03)];
this.camera = new THREE.PerspectiveCamera(45, this.widthW / this.heightW, .01, 10000);
this.scene.add(this.camera);
this.camera.position.set(-0.1, 4.0, 0.1);
var controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
this.sim = new Simulation(this.renderer, this.size);
this.setLight();
this.createObj();
this.time = new THREE.Clock();
this.render();
}
setLight() {
this.light = new THREE.DirectionalLight(0xFFAA55);
this.light.position.set(-4, -6, 10);
this.light.castShadow = true;
this.shadowCamera = this.light.shadow.camera;
// this.shadowCamera.position.set(-4, -6, 10);
this.shadowCamera.lookAt(this.scene.position);
this.light.shadow.matrix.set(
0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0);
this.light.shadow.matrix.multiply(this.shadowCamera.projectionMatrix);
this.light.shadow.matrix.multiply(this.shadowCamera.matrixWorldInverse);
if (this.light.shadow.map === null) {
this.light.shadow.mapSize.x = 2048;
this.light.shadow.mapSize.y = 2048;
var pars = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
this.light.shadow.map = new THREE.WebGLRenderTarget(this.light.shadow.mapSize.x, this.light.shadow.mapSize.y, pars);
// light.shadow.map.texture.name = light.name + ".shadowMap";
}
console.log(this.light);
}
createObj() {
// var originalG = new THREE.BoxBufferGeometry(1, 1, 1);
var originalG = new THREE.OctahedronBufferGeometry(1, 0);
var geometry = new THREE.InstancedBufferGeometry();
// vertex
var vertices = originalG.attributes.position.clone();
geometry.addAttribute("position", vertices);
var normals = originalG.attributes.normal.clone();
geometry.addAttribute("normal", normals);
// uv
var uvs = originalG.attributes.uv.clone();
geometry.addAttribute("uv", uvs);
// index
// var indices = originalG.index.clone();
// geometry.setIndex(indices);
geometry.maxInstancedCount = this.sim.size * this.sim.size;
var nums = new THREE.InstancedBufferAttribute(new Float32Array(this.sim.size * this.sim.size * 1), 1, 1);
var randoms = new THREE.InstancedBufferAttribute(new Float32Array(this.sim.size * this.sim.size * 1), 1, 1);
var colors = new THREE.InstancedBufferAttribute(new Float32Array(this.sim.size * this.sim.size * 3), 3, 1);
for (var i = 0; i < nums.count; i++) {
var _color = this.colorPallete[Math.floor(Math.random() * this.colorPallete.length)];
nums.setX(i, i);
randoms.setX(i, Math.random() * 0.5 + 1);
colors.setXYZ(i, _color.r, _color.g, _color.b);
}
geometry.addAttribute("aNum", nums);
geometry.addAttribute("aRandom", randoms);
geometry.addAttribute("aColor", colors);
var scale = {
x: 2,
y: 8,
z: 2 };
this.material = new THREE.ShaderMaterial({
uniforms: {
posMap: { type: "t", value: this.sim.gpuCompute.getCurrentRenderTarget(this.sim.pos).texture },
velMap: { type: "t", value: this.sim.gpuCompute.getCurrentRenderTarget(this.sim.vel).texture },
size: { type: "f", value: this.sim.size },
timer: { type: 'f', value: 0 },
boxScale: { type: 'v3', value: new THREE.Vector3(scale.x, scale.y, scale.z) },
meshScale: { type: 'f', value: 0.7 },
shadowMap: { type: 't', value: this.light.shadow.map },
shadowMapSize: { type: "v2", value: this.light.shadow.mapSize },
shadowBias: { type: "f", value: this.light.shadow.bias },
shadowRadius: { type: "f", value: this.light.shadow.radius },
// Line 217 in https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLShadowMap.js
shadowMatrix: { type: 'm4', value: this.light.shadow.matrix },
lightPosition: { type: 'v3', value: this.light.position } },
vertexShader: document.getElementById('vs-particles').textContent,
fragmentShader: document.getElementById('fs-particles').textContent,
side: THREE.DoubleSide,
shading: THREE.FlatShading });
this.mesh = new THREE.Mesh(geometry, this.material);
this.scene.add(this.mesh);
this.shadowMaterial = new THREE.ShaderMaterial({
uniforms: {
posMap: { type: "t", value: this.sim.gpuCompute.getCurrentRenderTarget(this.sim.pos).texture },
velMap: { type: "t", value: this.sim.gpuCompute.getCurrentRenderTarget(this.sim.vel).texture },
size: { type: "f", value: this.sim.size },
timer: { type: 'f', value: 0 },
boxScale: { type: 'v3', value: new THREE.Vector3(scale.x, scale.y, scale.z) },
meshScale: { type: 'f', value: 0.7 },
shadowMatrix: { type: 'm4', value: this.light.shadow.matrix },
lightPosition: { type: 'v3', value: this.light.position } },
vertexShader: document.getElementById('vs-particles').textContent,
fragmentShader: document.getElementById('fs-particles-shadow').textContent,
side: THREE.DoubleSide });
}
render() {
var delta = this.time.getDelta() * 4;
var time = this.time.elapsedTime;
this.sim.velUniforms.timer.value = time;
this.sim.velUniforms.delta.value = delta;
this.sim.gpuCompute.compute();
this.material.uniforms.posMap.value = this.sim.gpuCompute.getCurrentRenderTarget(this.sim.pos).texture;
this.material.uniforms.velMap.value = this.sim.gpuCompute.getCurrentRenderTarget(this.sim.vel).texture;
this.shadowMaterial.uniforms.posMap.value = this.sim.gpuCompute.getCurrentRenderTarget(this.sim.pos).texture;
this.shadowMaterial.uniforms.velMap.value = this.sim.gpuCompute.getCurrentRenderTarget(this.sim.vel).texture;
this.material.uniforms.timer.value = this.shadowMaterial.uniforms.timer.value = time;
this.mesh.material = this.shadowMaterial;
this.renderer.render(this.scene, this.shadowCamera, this.light.shadow.map);
this.renderer.setClearColor(0x2e0232);
this.mesh.material = this.material;
this.renderer.render(this.scene, this.camera);
requestAnimationFrame(this.render.bind(this));
}
resize() {
this.widthW = document.body.clientWidth;
this.heightW = window.innerHeight;
this.camera.aspect = this.widthW / this.heightW;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.widthW, this.heightW);
}}
class Simulation {
constructor(renderer, size) {
this.renderer = renderer;
this.size = size;
this.init();
}
init() {
this.gpuCompute = new GPUComputationRenderer(this.size, this.size, this.renderer);
this.dataPos = this.gpuCompute.createTexture();
this.dataVel = this.gpuCompute.createTexture();
this.dataDef = this.gpuCompute.createTexture();
var posArray = this.dataPos.image.data;
var velArray = this.dataVel.image.data;
var defArray = this.dataDef.image.data;
for (var i = 0, il = posArray.length; i < il; i += 4) {
var phi = Math.random() * 2 * Math.PI;
var theta = Math.random() * Math.PI;
var r = 0.8 + Math.random() * 2;
defArray[i + 0] = posArray[i + 0] = r * Math.sin(theta) * Math.cos(phi);
defArray[i + 1] = posArray[i + 1] = r * Math.sin(theta) * Math.sin(phi);
defArray[i + 2] = posArray[i + 2] = r * Math.cos(theta);
velArray[i + 3] = Math.random() * 100; // frames life
// if(i < 50) console.log(velArray[ i + 3 ])
}
this.def = this.gpuCompute.addVariable("defTex", document.getElementById('simulation_def').textContent, this.dataDef);
this.vel = this.gpuCompute.addVariable("velTex", document.getElementById('simulation_vel').textContent, this.dataVel);
this.pos = this.gpuCompute.addVariable("posTex", document.getElementById('simulation_pos').textContent, this.dataPos);
this.gpuCompute.setVariableDependencies(this.def, [this.pos, this.vel, this.def]);
this.gpuCompute.setVariableDependencies(this.vel, [this.pos, this.vel, this.def]);
this.gpuCompute.setVariableDependencies(this.pos, [this.pos, this.vel, this.def]);
// var posUniforms = this.pos.material.uniforms;
this.velUniforms = this.vel.material.uniforms;
this.velUniforms.timer = { value: 0.0 };
this.velUniforms.delta = { value: 0.0 };
this.velUniforms.speed = { value: 0.5 };
this.velUniforms.factor = { value: 0.5 };
this.velUniforms.evolution = { value: 0.5 };
this.velUniforms.radius = { value: 2.0 };
var error = this.gpuCompute.init();
if (error !== null) {
console.error(error);
}
}}