From 16c21ef7f8352665cdaf95beda97eda4bd327e93 Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Mon, 21 Sep 2020 09:15:15 +0200 Subject: [PATCH] improve hmr (effects, mesh) --- README.md | 11 ++++++++++- src/effects/BokehPass.js | 16 +++++----------- src/effects/EffectComposer.js | 1 + src/effects/EffectPass.js | 3 +++ src/effects/HalftonePass.js | 29 +++++++++++++++++++++++++++++ src/effects/UnrealBloomPass.js | 31 ++++++++----------------------- src/effects/index.js | 2 ++ src/meshes/InstancedMesh.js | 7 +++++-- src/meshes/Mesh.js | 7 +++++-- src/plugin.js | 2 ++ 10 files changed, 70 insertions(+), 39 deletions(-) create mode 100644 src/effects/HalftonePass.js diff --git a/README.md b/README.md index 01f830d..5018689 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,22 @@ Thanks to VueJS/ViteJS, **TroisJS use watchers and HMR to update ThreeJS objects - [x] PerspectiveCamera : aspect, far, fov, near, position - [x] Light : castShadow, color, intensity, position, target - [x] SpotLight : angle, decay, distance, penumbra + - [ ] ... - [x] Material : color, depthTest, depthWrite, fog, opacity, transparent - [x] StandardMaterial : emissive, emissiveIntensity, metalness, roughness - - [x] Mesh : position, rotation, scale, castShadow, receiveShadow + - [ ] ... + - [x] Mesh : materialId, position, rotation, scale, castShadow, receiveShadow - [x] Box (geometry replace) : size, width, height, depth - [x] Plane (geometry replace) : width, height, widthSegments, heightSegments - [x] Sphere (geometry replace) : radius, widthSegments, heightSegments - [x] Text (geometry replace) : all props except fontSrc (wip) + - [ ] ... + - [ ] PostProcessing + - [x] BokehPass : focus, aperture, maxblur + - [x] FilmPass : noiseIntensity, scanlinesIntensity, scanlinesCount, grayscale + - [x] HalftonePass : shape, radius, rotateR, rotateG, rotateB, scatter + - [x] UnrealBloomPass : strength, radius, threshold + - [ ] ... - [ ] ... ## Features diff --git a/src/effects/BokehPass.js b/src/effects/BokehPass.js index 71aa06a..61481ff 100644 --- a/src/effects/BokehPass.js +++ b/src/effects/BokehPass.js @@ -17,17 +17,11 @@ export default { default: 0.01, }, }, - // watch: { - // focus() { - // this.pass.focus = this.focus; - // }, - // aperture() { - // this.pass.aperture = this.aperture; - // }, - // maxblur() { - // this.pass.maxblur = this.maxblur; - // }, - // }, + watch: { + focus() { this.pass.uniforms.focus.value = this.focus; }, + aperture() { this.pass.uniforms.aperture.value = this.aperture; }, + maxblur() { this.pass.uniforms.maxblur.value = this.maxblur; }, + }, mounted() { if (!this.three.scene) { console.error('Missing Scene'); diff --git a/src/effects/EffectComposer.js b/src/effects/EffectComposer.js index 3f71985..1f141a4 100644 --- a/src/effects/EffectComposer.js +++ b/src/effects/EffectComposer.js @@ -15,6 +15,7 @@ export default { mounted() { this.three.onAfterInit(() => { this.composer = new EffectComposer(this.three.renderer); + this.three.renderer.autoClear = false; this.passes.forEach(pass => { this.composer.addPass(pass); }); diff --git a/src/effects/EffectPass.js b/src/effects/EffectPass.js index e992dfd..e892fb0 100644 --- a/src/effects/EffectPass.js +++ b/src/effects/EffectPass.js @@ -5,6 +5,9 @@ export default { console.error('Missing parent EffectComposer'); } }, + unmounted() { + if (this.pass.dispose) this.pass.dispose(); + }, render() { return []; }, diff --git a/src/effects/HalftonePass.js b/src/effects/HalftonePass.js new file mode 100644 index 0000000..8be4ff6 --- /dev/null +++ b/src/effects/HalftonePass.js @@ -0,0 +1,29 @@ +import { HalftonePass } from 'three/examples/jsm/postprocessing/HalftonePass.js'; +import { watch } from 'vue'; +import EffectPass from './EffectPass.js'; + +export default { + extends: EffectPass, + props: { + shape: { type: Number, default: 1 }, + radius: { type: Number, default: 4 }, + rotateR: { type: Number, default: Math.PI / 12 * 1 }, + rotateG: { type: Number, default: Math.PI / 12 * 2 }, + rotateB: { type: Number, default: Math.PI / 12 * 3 }, + scatter: { type: Number, default: 0 }, + }, + mounted() { + const pass = new HalftonePass(this.three.size.width, this.three.size.height, {}); + + ['shape', 'radius', 'rotateR', 'rotateG', 'rotateB', 'scatter'].forEach(p => { + pass.uniforms[p].value = this[p]; + watch(() => this[p], () => { + pass.uniforms[p].value = this[p]; + }); + }); + + this.passes.push(pass); + this.pass = pass; + }, + __hmrId: 'HalftonePass', +}; diff --git a/src/effects/UnrealBloomPass.js b/src/effects/UnrealBloomPass.js index 027aec3..039597c 100644 --- a/src/effects/UnrealBloomPass.js +++ b/src/effects/UnrealBloomPass.js @@ -5,30 +5,15 @@ import EffectPass from './EffectPass.js'; export default { extends: EffectPass, props: { - strength: { - type: Number, - default: 1.5, - }, - radius: { - type: Number, - default: 0, - }, - threshold: { - type: Number, - default: 0, - }, + strength: { type: Number, default: 1.5 }, + radius: { type: Number, default: 0 }, + threshold: { type: Number, default: 0 }, + }, + watch: { + strength() { this.pass.strength = this.strength; }, + radius() { this.pass.radius = this.radius; }, + threshold() { this.pass.threshold = this.threshold; }, }, - // watch: { - // strength() { - // this.pass.strength = this.strength; - // }, - // radius() { - // this.pass.strength = this.radius; - // }, - // threshold() { - // this.pass.strength = this.threshold; - // }, - // }, mounted() { const size = new Vector2(this.three.size.width, this.three.size.height); const pass = new UnrealBloomPass(size, this.strength, this.radius, this.threshold); diff --git a/src/effects/index.js b/src/effects/index.js index e29909f..3d7cc8f 100644 --- a/src/effects/index.js +++ b/src/effects/index.js @@ -2,4 +2,6 @@ export { default as EffectComposer } from './EffectComposer.js'; export { default as RenderPass } from './RenderPass.js'; export { default as BokehPass } from './BokehPass.js'; export { default as FilmPass } from './FilmPass.js'; +export { default as HalftonePass } from './HalftonePass.js'; +export { default as SAOPass } from './SAOPass.js'; export { default as UnrealBloomPass } from './UnrealBloomPass.js'; diff --git a/src/meshes/InstancedMesh.js b/src/meshes/InstancedMesh.js index 1ef32e9..f843313 100644 --- a/src/meshes/InstancedMesh.js +++ b/src/meshes/InstancedMesh.js @@ -39,12 +39,15 @@ export default { useBindProp(this, 'rotation', this.mesh.rotation); useBindProp(this, 'scale', this.mesh.scale); - this.mesh.castShadow = this.castShadow; - this.mesh.receiveShadow = this.receiveShadow; ['castShadow', 'receiveShadow'].forEach(p => { + this.mesh[p] = this[p]; watch(() => this[p], () => { this.mesh[p] = this[p]; }); }); + // watch(() => this.materialId, () => { + // this.mesh.material = this.three.materials[this.materialId]; + // }); + this.scene.add(this.mesh); }, unmounted() { diff --git a/src/meshes/Mesh.js b/src/meshes/Mesh.js index 95e1d4a..2af1be6 100644 --- a/src/meshes/Mesh.js +++ b/src/meshes/Mesh.js @@ -37,12 +37,15 @@ export default { useBindProp(this, 'rotation', this.mesh.rotation); useBindProp(this, 'scale', this.mesh.scale); - this.mesh.castShadow = this.castShadow; - this.mesh.receiveShadow = this.receiveShadow; ['castShadow', 'receiveShadow'].forEach(p => { + this.mesh[p] = this[p]; watch(() => this[p], () => { this.mesh[p] = this[p]; }); }); + watch(() => this.materialId, () => { + this.mesh.material = this.three.materials[this.materialId]; + }); + this.scene.add(this.mesh); this.$emit('ready'); }, diff --git a/src/plugin.js b/src/plugin.js index 24f13e2..1c39bbc 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -37,7 +37,9 @@ export const TroisJSVuePlugin = { 'BokehPass', 'EffectComposer', 'FilmPass', + 'HalftonePass', 'RenderPass', + 'SAOPass', 'UnrealBloomPass', 'GLTFViewer',