codepens/curl-noise/dist/script.js

279 lines
9.3 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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);
}
}}