From 6040b6f44d6cff365ac21fb4273442d8e515a82b Mon Sep 17 00:00:00 2001 From: Kevin Levron Date: Wed, 16 Sep 2020 23:27:29 +0200 Subject: [PATCH] add effects --- src/core/Renderer.js | 7 ++++- src/core/useThree.js | 47 ++++++++++++++++++++++++++-------- src/effects/BokehPass.js | 43 +++++++++++++++++++++++++++++++ src/effects/EffectComposer.js | 27 +++++++++++++++++++ src/effects/EffectPass.js | 11 ++++++++ src/effects/RenderPass.js | 17 ++++++++++++ src/effects/UnrealBloomPass.js | 38 +++++++++++++++++++++++++++ src/effects/index.js | 4 +++ src/index.js | 2 ++ 9 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 src/effects/BokehPass.js create mode 100644 src/effects/EffectComposer.js create mode 100644 src/effects/EffectPass.js create mode 100644 src/effects/RenderPass.js create mode 100644 src/effects/UnrealBloomPass.js create mode 100644 src/effects/index.js diff --git a/src/core/Renderer.js b/src/core/Renderer.js index b39ed1b..68004c1 100644 --- a/src/core/Renderer.js +++ b/src/core/Renderer.js @@ -60,7 +60,8 @@ export default { if (this.three.init(params)) { this.three.renderer.shadowMap.enabled = this.shadow; - this.animate(); + if (this.three.composer) this.animateC(); + else this.animate(); }; }, beforeUnmount() { @@ -78,6 +79,10 @@ export default { if (this.raf) requestAnimationFrame(this.animate); this.three.render(); }, + animateC() { + if (this.raf) requestAnimationFrame(this.animateC); + this.three.renderC(); + }, }, render() { return h( diff --git a/src/core/useThree.js b/src/core/useThree.js index 2a2c9f0..614b917 100644 --- a/src/core/useThree.js +++ b/src/core/useThree.js @@ -33,6 +33,7 @@ export default function useThree() { }; // handlers + const afterInitHandlers = []; const afterResizeHandlers = []; const beforeRenderHandlers = []; @@ -55,7 +56,9 @@ export default function useThree() { init, dispose, render, + renderC, setSize, + onAfterInit, onAfterResize, onBeforeRender, }; @@ -108,9 +111,32 @@ export default function useThree() { obj.mouse_move_element.addEventListener('mouseleave', onMouseleave); } - return obj; + afterInitHandlers.forEach(c => c()); + + return true; }; + /** + * add after init handler + */ + function onAfterInit(callback) { + afterInitHandlers.push(callback); + } + + /** + * add after resize handler + */ + function onAfterResize(callback) { + afterResizeHandlers.push(callback); + } + + /** + * add before render handler + */ + function onBeforeRender(callback) { + beforeRenderHandlers.push(callback); + } + /** * default render */ @@ -121,10 +147,12 @@ export default function useThree() { } /** - * add before render handler + * composer render */ - function onBeforeRender(callback) { - beforeRenderHandlers.push(callback); + function renderC() { + if (obj.orbitCtrl) obj.orbitCtrl.update(); + beforeRenderHandlers.forEach(c => c()); + obj.composer.render(); } /** @@ -180,13 +208,6 @@ export default function useThree() { afterResizeHandlers.forEach(c => c()); } - /** - * add after resize handler - */ - function onAfterResize(callback) { - afterResizeHandlers.push(callback); - } - /** * update renderer size and camera */ @@ -199,6 +220,10 @@ export default function useThree() { obj.camera.aspect = size.ratio; obj.camera.updateProjectionMatrix(); + if (obj.composer) { + obj.composer.setSize(width, height); + } + const wsize = getCameraSize(); size.wWidth = wsize[0]; size.wHeight = wsize[1]; } diff --git a/src/effects/BokehPass.js b/src/effects/BokehPass.js new file mode 100644 index 0000000..1b086a3 --- /dev/null +++ b/src/effects/BokehPass.js @@ -0,0 +1,43 @@ +import { BokehPass } from 'three/examples/jsm/postprocessing/BokehPass.js'; +import EffectPass from './EffectPass.js'; + +export default { + extends: EffectPass, + props: { + focus: { + type: Number, + default: 1, + }, + aperture: { + type: Number, + default: 0.025, + }, + maxblur: { + type: Number, + default: 0.01, + }, + }, + // watch: { + // focus() { + // this.pass.focus = this.focus; + // }, + // aperture() { + // this.pass.aperture = this.aperture; + // }, + // maxblur() { + // this.pass.maxblur = this.maxblur; + // }, + // }, + mounted() { + if (!this.three.scene) { + console.error('Missing Scene'); + } + if (!this.three.camera) { + console.error('Missing Camera'); + } + const params = { ...this.$props, width: this.three.size.width, height: this.three.size.height }; + const pass = new BokehPass(this.three.scene, this.three.camera, params); + this.passes.push(pass); + this.pass = pass; + }, +}; diff --git a/src/effects/EffectComposer.js b/src/effects/EffectComposer.js new file mode 100644 index 0000000..a204291 --- /dev/null +++ b/src/effects/EffectComposer.js @@ -0,0 +1,27 @@ +import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'; + +export default { + setup() { + return { + passes: [], + }; + }, + inject: ['three'], + provide() { + return { + passes: this.passes, + }; + }, + mounted() { + this.three.onAfterInit(() => { + this.composer = new EffectComposer(this.three.renderer); + this.passes.forEach(pass => { + this.composer.addPass(pass); + }); + this.three.composer = this.composer; + }); + }, + render() { + return this.$slots.default(); + }, +}; diff --git a/src/effects/EffectPass.js b/src/effects/EffectPass.js new file mode 100644 index 0000000..1a9790f --- /dev/null +++ b/src/effects/EffectPass.js @@ -0,0 +1,11 @@ +export default { + inject: ['three', 'passes'], + beforeMount() { + if (!this.passes) { + console.error('Missing parent EffectComposer'); + } + }, + render() { + return []; + }, +}; diff --git a/src/effects/RenderPass.js b/src/effects/RenderPass.js new file mode 100644 index 0000000..510b953 --- /dev/null +++ b/src/effects/RenderPass.js @@ -0,0 +1,17 @@ +import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'; +import EffectPass from './EffectPass.js'; + +export default { + extends: EffectPass, + mounted() { + if (!this.three.scene) { + console.error('Missing Scene'); + } + if (!this.three.camera) { + console.error('Missing Camera'); + } + const pass = new RenderPass(this.three.scene, this.three.camera); + this.passes.push(pass); + this.pass = pass; + }, +}; diff --git a/src/effects/UnrealBloomPass.js b/src/effects/UnrealBloomPass.js new file mode 100644 index 0000000..331185e --- /dev/null +++ b/src/effects/UnrealBloomPass.js @@ -0,0 +1,38 @@ +import { Vector2 } from 'three'; +import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js'; +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, + }, + }, + // 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); + this.passes.push(pass); + this.pass = pass; + }, +}; diff --git a/src/effects/index.js b/src/effects/index.js new file mode 100644 index 0000000..a9dfc1d --- /dev/null +++ b/src/effects/index.js @@ -0,0 +1,4 @@ +export { default as EffectComposer } from './EffectComposer.js'; +export { default as RenderPass } from './RenderPass.js'; +export { default as BokehPass } from './BokehPass.js'; +export { default as UnrealBloomPass } from './UnrealBloomPass.js'; diff --git a/src/index.js b/src/index.js index 814c7be..e7ec967 100644 --- a/src/index.js +++ b/src/index.js @@ -4,3 +4,5 @@ export * from './lights/index.js'; export * from './materials/index.js'; export * from './meshes/index.js'; export * from './tools.js'; + +export * from './effects/index.js';