1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00
This commit is contained in:
Kevin Levron 2021-04-21 21:05:02 +02:00
parent 3e9138d1db
commit 04890fc2fb
33 changed files with 158 additions and 203 deletions

View File

@ -8,16 +8,17 @@ import {
ShaderMaterial, ShaderMaterial,
Uniform, Uniform,
Vector2, Vector2,
WebGLRenderer,
WebGLRenderTarget, WebGLRenderTarget,
} from 'three'; } from 'three'
// shaders from https://github.com/evanw/webgl-water // shaders from https://github.com/evanw/webgl-water
function LiquidEffect(renderer) { function LiquidEffect(renderer) {
this.renderer = renderer; this.renderer = renderer
this.width = 512; this.width = 512
this.height = 512; this.height = 512
// this.delta = new Vector2(this.width / Math.pow(width, 2), this.height / Math.pow(height, 2)); // this.delta = new Vector2(this.width / Math.pow(width, 2), this.height / Math.pow(height, 2));
this.delta = new Vector2(1 / this.width, 1 / this.height); this.delta = new Vector2(1 / this.width, 1 / this.height)
const targetOptions = { const targetOptions = {
minFilter: NearestFilter, minFilter: NearestFilter,
@ -25,14 +26,14 @@ function LiquidEffect(renderer) {
type: FloatType, type: FloatType,
format: RGBAFormat, format: RGBAFormat,
depthBuffer: false, depthBuffer: false,
}; }
this.hMap = new WebGLRenderTarget(this.width, this.height, targetOptions); this.hMap = new WebGLRenderTarget(this.width, this.height, targetOptions)
this.hMap1 = new WebGLRenderTarget(this.width, this.height, targetOptions); this.hMap1 = new WebGLRenderTarget(this.width, this.height, targetOptions)
this.fsQuad = new FullScreenQuad(); this.fsQuad = new FullScreenQuad()
this.initShaders(); this.initShaders()
}; }
LiquidEffect.prototype.initShaders = function () { LiquidEffect.prototype.initShaders = function () {
const defaultVertexShader = ` const defaultVertexShader = `
@ -41,7 +42,7 @@ LiquidEffect.prototype.initShaders = function () {
vUv = uv; vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
} }
`; `
this.copyMat = new ShaderMaterial({ this.copyMat = new ShaderMaterial({
uniforms: { tDiffuse: { value: null } }, uniforms: { tDiffuse: { value: null } },
@ -53,7 +54,7 @@ LiquidEffect.prototype.initShaders = function () {
gl_FragColor = texture2D(tDiffuse, vUv); gl_FragColor = texture2D(tDiffuse, vUv);
} }
`, `,
}); })
this.updateMat = new ShaderMaterial({ this.updateMat = new ShaderMaterial({
uniforms: { uniforms: {
@ -83,7 +84,7 @@ LiquidEffect.prototype.initShaders = function () {
gl_FragColor = texel; gl_FragColor = texel;
} }
`, `,
}); })
this.normalsMat = new ShaderMaterial({ this.normalsMat = new ShaderMaterial({
uniforms: { uniforms: {
@ -103,7 +104,7 @@ LiquidEffect.prototype.initShaders = function () {
gl_FragColor = texel; gl_FragColor = texel;
} }
`, `,
}); })
this.dropMat = new ShaderMaterial({ this.dropMat = new ShaderMaterial({
uniforms: { uniforms: {
@ -129,35 +130,35 @@ LiquidEffect.prototype.initShaders = function () {
gl_FragColor = texel; gl_FragColor = texel;
} }
`, `,
}); })
}; }
LiquidEffect.prototype.update = function () { LiquidEffect.prototype.update = function () {
this.updateHMap(); this.updateHMap()
// this.updateHMap(); // this.updateHMap();
this.updateHMapNormals(); this.updateHMapNormals()
}; }
LiquidEffect.prototype.updateHMap = function () { LiquidEffect.prototype.updateHMap = function () {
this.updateMat.uniforms.tDiffuse.value = this.hMap.texture; this.updateMat.uniforms.tDiffuse.value = this.hMap.texture
this.renderShaderMat(this.updateMat, this.hMap1); this.renderShaderMat(this.updateMat, this.hMap1)
this.swapBuffers(); this.swapBuffers()
}; }
LiquidEffect.prototype.updateHMapNormals = function () { LiquidEffect.prototype.updateHMapNormals = function () {
this.normalsMat.uniforms.tDiffuse.value = this.hMap.texture; this.normalsMat.uniforms.tDiffuse.value = this.hMap.texture
this.renderShaderMat(this.normalsMat, this.hMap1); this.renderShaderMat(this.normalsMat, this.hMap1)
this.swapBuffers(); this.swapBuffers()
}; }
LiquidEffect.prototype.addDrop = function (x, y, radius, strength) { LiquidEffect.prototype.addDrop = function (x, y, radius, strength) {
this.dropMat.uniforms.tDiffuse.value = this.hMap.texture; this.dropMat.uniforms.tDiffuse.value = this.hMap.texture
this.dropMat.uniforms.center.value.set(x, y); this.dropMat.uniforms.center.value.set(x, y)
this.dropMat.uniforms.radius.value = radius; this.dropMat.uniforms.radius.value = radius
this.dropMat.uniforms.strength.value = strength; this.dropMat.uniforms.strength.value = strength
this.renderShaderMat(this.dropMat, this.hMap1); this.renderShaderMat(this.dropMat, this.hMap1)
this.swapBuffers(); this.swapBuffers()
}; }
// LiquidEffect.prototype.renderBuffer = function (buffer, target) { // LiquidEffect.prototype.renderBuffer = function (buffer, target) {
// this.copyMat.uniforms.tDiffuse.value = buffer.texture; // this.copyMat.uniforms.tDiffuse.value = buffer.texture;
@ -165,40 +166,40 @@ LiquidEffect.prototype.addDrop = function (x, y, radius, strength) {
// }; // };
LiquidEffect.prototype.renderShaderMat = function (mat, target) { LiquidEffect.prototype.renderShaderMat = function (mat, target) {
this.fsQuad.material = mat; this.fsQuad.material = mat
const oldTarget = this.renderer.getRenderTarget(); const oldTarget = this.renderer.getRenderTarget()
this.renderer.setRenderTarget(target); this.renderer.setRenderTarget(target)
this.fsQuad.render(this.renderer); this.fsQuad.render(this.renderer)
this.renderer.setRenderTarget(oldTarget); this.renderer.setRenderTarget(oldTarget)
}; }
LiquidEffect.prototype.swapBuffers = function () { LiquidEffect.prototype.swapBuffers = function () {
const temp = this.hMap; const temp = this.hMap
this.hMap = this.hMap1; this.hMap = this.hMap1
this.hMap1 = temp; this.hMap1 = temp
}; }
// from https://threejs.org/examples/js/postprocessing/EffectComposer.js // from https://threejs.org/examples/js/postprocessing/EffectComposer.js
const FullScreenQuad = (function () { const FullScreenQuad = (function () {
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1); const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1)
const geometry = new PlaneGeometry(2, 2); const geometry = new PlaneGeometry(2, 2)
const FullScreenQuad = function (material) { const FullScreenQuad = function (material) {
this._mesh = new Mesh(geometry, material); this._mesh = new Mesh(geometry, material)
}; }
Object.defineProperty(FullScreenQuad.prototype, 'material', { Object.defineProperty(FullScreenQuad.prototype, 'material', {
get: function () { return this._mesh.material; }, get: function () { return this._mesh.material },
set: function (value) { this._mesh.material = value; }, set: function (value) { this._mesh.material = value },
}); })
Object.assign(FullScreenQuad.prototype, { Object.assign(FullScreenQuad.prototype, {
render: function (renderer) { render: function (renderer) {
renderer.render(this._mesh, camera); renderer.render(this._mesh, camera)
}, },
}); })
return FullScreenQuad; return FullScreenQuad
})(); })()
export default LiquidEffect; export default LiquidEffect

View File

@ -16,7 +16,7 @@ export default defineComponent({
roughness: { type: Number, default: 0.25 }, roughness: { type: Number, default: 0.25 },
}, },
mounted() { mounted() {
this.liquidEffect = new LiquidEffect(this.three.renderer); this.liquidEffect = new LiquidEffect(this.renderer.renderer);
this.renderer.onMounted(() => { this.renderer.onMounted(() => {
this.liquidEffect.renderer = this.renderer.renderer; this.liquidEffect.renderer = this.renderer.renderer;
this.renderer.onBeforeRender(this.update); this.renderer.onBeforeRender(this.update);

View File

@ -64,7 +64,7 @@ export default defineComponent({
updateCubeRT() { updateCubeRT() {
this.mesh.visible = false; this.mesh.visible = false;
this.meshBack.visible = false; this.meshBack.visible = false;
this.cubeCamera.update(this.three.renderer, this.scene); this.cubeCamera.update(this.renderer.renderer, this.scene);
this.mesh.visible = true; this.mesh.visible = true;
this.meshBack.visible = true; this.meshBack.visible = true;
}, },

View File

@ -35,7 +35,7 @@ export default defineComponent({
}, },
updateCubeRT() { updateCubeRT() {
this.mesh.visible = false; this.mesh.visible = false;
this.cubeCamera.update(this.three.renderer, this.scene); this.cubeCamera.update(this.renderer.renderer, this.scene);
this.mesh.visible = true; this.mesh.visible = true;
}, },
}, },

View File

@ -40,7 +40,7 @@ export default defineComponent({
}, },
updateCubeRT() { updateCubeRT() {
this.mesh.visible = false; this.mesh.visible = false;
this.cubeCamera.update(this.three.renderer, this.scene); this.cubeCamera.update(this.renderer.renderer, this.scene);
this.mesh.visible = true; this.mesh.visible = true;
}, },
}, },

View File

@ -117,7 +117,7 @@ export default defineComponent({
this.renderMat(this.normMat, this.normRT); this.renderMat(this.normMat, this.normRT);
}, },
renderMat(mat, target) { renderMat(mat, target) {
const renderer = this.three.renderer; const renderer = this.renderer.renderer;
this.fsQuad.material = mat; this.fsQuad.material = mat;
const oldTarget = renderer.getRenderTarget(); const oldTarget = renderer.getRenderTarget();
renderer.setRenderTarget(target); renderer.setRenderTarget(target);

View File

@ -45,7 +45,7 @@ export default defineComponent({
}, },
unmounted() { unmounted() {
this.loader.dispose(); this.loader.dispose();
const domElement = this.three.renderer.domElement; const domElement = this.renderer.renderer.domElement;
domElement.removeEventListener('click', this.onClick); domElement.removeEventListener('click', this.onClick);
domElement.removeEventListener('wheel', this.onWheel); domElement.removeEventListener('wheel', this.onWheel);
document.removeEventListener('keyup', this.onKeyup); document.removeEventListener('keyup', this.onKeyup);
@ -65,26 +65,26 @@ export default defineComponent({
} }
); );
const domElement = this.three.renderer.domElement; const domElement = this.renderer.renderer.domElement;
if (this.events.click) domElement.addEventListener('click', this.onClick); if (this.events.click) domElement.addEventListener('click', this.onClick);
if (this.events.wheel) domElement.addEventListener('wheel', this.onWheel); if (this.events.wheel) domElement.addEventListener('wheel', this.onWheel);
if (this.events.keyup) document.addEventListener('keyup', this.onKeyup); if (this.events.keyup) document.addEventListener('keyup', this.onKeyup);
this.renderer.onBeforeRender(this.updateProgress); this.renderer.onBeforeRender(this.updateProgress);
this.renderer.onAfterResize(this.onResize); this.renderer.onResize(this.onResize);
}, },
initScene() { initScene() {
const renderer = this.three.renderer; const renderer = this.renderer.renderer;
const scene = this.$refs.scene.scene; const scene = this.$refs.scene.scene;
this.plane1 = new AnimatedPlane({ this.plane1 = new AnimatedPlane({
renderer, screen: this.three.size, renderer, screen: this.renderer.size,
size: 10, size: 10,
anim: 1, anim: 1,
texture: this.loader.textures[0], texture: this.loader.textures[0],
}); });
this.plane2 = new AnimatedPlane({ this.plane2 = new AnimatedPlane({
renderer, screen: this.three.size, renderer, screen: this.renderer.size,
size: 10, size: 10,
anim: 2, anim: 2,
texture: this.loader.textures[1], texture: this.loader.textures[1],
@ -109,7 +109,7 @@ export default defineComponent({
} }
}, },
onClick(e) { onClick(e) {
if (e.clientY < this.three.size.height / 2) { if (e.clientY < this.renderer.size.height / 2) {
this.navPrevious(); this.navPrevious();
} else { } else {
this.navNext(); this.navNext();

View File

@ -47,7 +47,7 @@ export default defineComponent({
}, },
unmounted() { unmounted() {
this.loader.dispose(); this.loader.dispose();
const domElement = this.three.renderer.domElement; const domElement = this.renderer.renderer.domElement;
domElement.removeEventListener('click', this.onClick); domElement.removeEventListener('click', this.onClick);
domElement.removeEventListener('wheel', this.onWheel); domElement.removeEventListener('wheel', this.onWheel);
document.removeEventListener('keyup', this.onKeyup); document.removeEventListener('keyup', this.onKeyup);
@ -66,19 +66,19 @@ export default defineComponent({
} }
); );
const domElement = this.three.renderer.domElement; const domElement = this.renderer.renderer.domElement;
if (this.events.click) domElement.addEventListener('click', this.onClick); if (this.events.click) domElement.addEventListener('click', this.onClick);
if (this.events.wheel) domElement.addEventListener('wheel', this.onWheel); if (this.events.wheel) domElement.addEventListener('wheel', this.onWheel);
if (this.events.keyup) document.addEventListener('keyup', this.onKeyup); if (this.events.keyup) document.addEventListener('keyup', this.onKeyup);
this.renderer.onBeforeRender(this.animate); this.renderer.onBeforeRender(this.animate);
this.renderer.onAfterResize(this.onResize); this.renderer.onResize(this.onResize);
}, },
initScene() { initScene() {
const scene = this.$refs.scene.scene; const scene = this.$refs.scene.scene;
this.image1 = new ZoomBlurImage(this.three); this.image1 = new ZoomBlurImage(this.renderer);
this.image1.setMap(this.loader.textures[0]); this.image1.setMap(this.loader.textures[0]);
this.image2 = new ZoomBlurImage(this.three); this.image2 = new ZoomBlurImage(this.renderer);
this.image2.setMap(this.loader.textures[1]); this.image2.setMap(this.loader.textures[1]);
this.setImagesProgress(0); this.setImagesProgress(0);
@ -86,7 +86,7 @@ export default defineComponent({
scene.add(this.image2.mesh); scene.add(this.image2.mesh);
}, },
animate() { animate() {
const { positionN } = this.three.pointer; const { positionN } = this.renderer.pointer;
this.center.copy(positionN).divideScalar(2).addScalar(0.5); this.center.copy(positionN).divideScalar(2).addScalar(0.5);
lerpv2(this.image1.uCenter.value, this.center, 0.1); lerpv2(this.image1.uCenter.value, this.center, 0.1);
lerpv2(this.image2.uCenter.value, this.center, 0.1); lerpv2(this.image2.uCenter.value, this.center, 0.1);
@ -106,7 +106,7 @@ export default defineComponent({
} }
}, },
onClick(e) { onClick(e) {
if (e.clientY < this.three.size.height / 2) { if (e.clientY < this.renderer.size.height / 2) {
this.navPrevious(); this.navPrevious();
} else { } else {
this.navNext(); this.navNext();

View File

@ -5,7 +5,7 @@ import {
Vector2, Vector2,
} from 'three'; } from 'three';
export default function ZoomBlurImage(three) { export default function ZoomBlurImage(renderer) {
let geometry, material, mesh; let geometry, material, mesh;
const uMap = { value: null }; const uMap = { value: null };
@ -94,7 +94,7 @@ export default function ZoomBlurImage(three) {
} }
function updateUV() { function updateUV() {
const ratio = three.size.ratio; const ratio = renderer.size.ratio;
const iRatio = uMap.value.image.width / uMap.value.image.height; const iRatio = uMap.value.image.width / uMap.value.image.height;
uUVOffset.value.set(0, 0); uUVOffset.value.set(0, 0);
uUVScale.value.set(1, 1); uUVScale.value.set(1, 1);

View File

@ -25,7 +25,7 @@ export default defineComponent({
const loader = new GLTFLoader(); const loader = new GLTFLoader();
loader.load(this.src, (gltf) => { loader.load(this.src, (gltf) => {
this.renderer.three.scene.add(gltf.scene); this.renderer.scene.add(gltf.scene);
}); });
}, },
}); });

View File

@ -1,5 +1,5 @@
import { defineComponent, inject } from 'vue' import { defineComponent, inject } from 'vue'
import { ThreeInterface } from './useThree' import { RendererInterface } from './Renderer'
// import Object3D from './Object3D' // import Object3D from './Object3D'
export default defineComponent({ export default defineComponent({
@ -8,13 +8,13 @@ export default defineComponent({
// don't work with typescript, bug ? // don't work with typescript, bug ?
// but works in sub components (injection, not typescript) // but works in sub components (injection, not typescript)
inject: ['three'], inject: ['renderer'],
setup() { setup() {
// this works with typescript in sub component // this works with typescript in sub component
// but setup is not called // but setup is not called
const three = inject('three') as ThreeInterface const renderer = inject('renderer') as RendererInterface
return { three } return { renderer }
}, },
render() { render() {
return this.$slots.default ? this.$slots.default() : [] return this.$slots.default ? this.$slots.default() : []

View File

@ -34,7 +34,7 @@ export default defineComponent({
return { camera } return { camera }
}, },
created() { created() {
this.three.camera = this.camera this.renderer.camera = this.camera
}, },
__hmrId: 'OrthographicCamera', __hmrId: 'OrthographicCamera',
}) })

View File

@ -36,7 +36,7 @@ export default defineComponent({
return { camera } return { camera }
}, },
created() { created() {
this.three.camera = this.camera this.renderer.camera = this.camera
}, },
__hmrId: 'PerspectiveCamera', __hmrId: 'PerspectiveCamera',
}) })

View File

@ -2,14 +2,12 @@ import { Object3D } from 'three'
import { defineComponent, inject, PropType } from 'vue' import { defineComponent, inject, PropType } from 'vue'
import usePointer, { IntersectObject, PointerInterface, PointerIntersectCallbackType } from './usePointer' import usePointer, { IntersectObject, PointerInterface, PointerIntersectCallbackType } from './usePointer'
import { RendererInterface } from './Renderer' import { RendererInterface } from './Renderer'
import { ThreeInterface } from './useThree'
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
const emptyCallBack: PointerIntersectCallbackType = () => {} const emptyCallBack: PointerIntersectCallbackType = () => {}
interface RaycasterSetupInterface { interface RaycasterSetupInterface {
renderer: RendererInterface renderer: RendererInterface
three: ThreeInterface
pointer?: PointerInterface pointer?: PointerInterface
} }
@ -25,22 +23,21 @@ export default defineComponent({
}, },
setup(): RaycasterSetupInterface { setup(): RaycasterSetupInterface {
const renderer = inject('renderer') as RendererInterface const renderer = inject('renderer') as RendererInterface
const three = inject('three') as ThreeInterface return { renderer }
return { renderer, three }
}, },
mounted() { mounted() {
this.renderer.onMounted(() => { this.renderer.onMounted(() => {
if (!this.three.camera) return if (!this.renderer.camera) return
this.pointer = usePointer({ this.pointer = usePointer({
camera: this.three.camera, camera: this.renderer.camera,
domElement: this.renderer.canvas, domElement: this.renderer.canvas,
intersectObjects: this.getIntersectObjects(), intersectObjects: this.getIntersectObjects(),
onIntersectEnter: (<PointerIntersectCallbackType> this.onPointerEnter), onIntersectEnter: this.onPointerEnter,
onIntersectOver: (<PointerIntersectCallbackType> this.onPointerOver), onIntersectOver: this.onPointerOver,
onIntersectMove: (<PointerIntersectCallbackType> this.onPointerMove), onIntersectMove: this.onPointerMove,
onIntersectLeave: (<PointerIntersectCallbackType> this.onPointerLeave), onIntersectLeave: this.onPointerLeave,
onIntersectClick: (<PointerIntersectCallbackType> this.onClick), onIntersectClick: this.onClick,
}) })
this.pointer.addListeners() this.pointer.addListeners()
@ -57,8 +54,8 @@ export default defineComponent({
}, },
methods: { methods: {
getIntersectObjects() { getIntersectObjects() {
if (this.three.scene) { if (this.renderer.scene) {
const children = this.three.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type)) const children = this.renderer.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type))
return children as IntersectObject[] return children as IntersectObject[]
} }
return [] return []

View File

@ -1,24 +1,25 @@
/* eslint-disable no-use-before-define */ /* eslint-disable no-use-before-define */
import { WebGLRenderer } from 'three' import { Camera, Scene, WebGLRenderer } from 'three'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { defineComponent, PropType } from 'vue' import { defineComponent, PropType } from 'vue'
import useThree, { SizeInterface, ThreeConfigInterface, ThreeInterface } from './useThree' import useThree, { SizeInterface, ThreeConfigInterface, ThreeInterface } from './useThree'
type CallbackType<T> = (event?: T) => void type CallbackType<T> = (event: T) => void
// type EventType = 'init' | 'mounted' | 'beforerender' | 'afterrender' | 'resize' // type EventType = 'init' | 'mounted' | 'beforerender' | 'afterrender' | 'resize'
interface EventInterface { export interface EventInterface {
type: 'init' | 'mounted' type: 'init' | 'mounted'
renderer: RendererInterface renderer: RendererInterface
} }
interface RenderEventInterface { export interface RenderEventInterface {
type: 'beforerender' | 'afterrender' type: 'beforerender' | 'afterrender'
renderer: RendererInterface renderer: RendererInterface
time: number time: number
} }
interface ResizeEventInterface { export interface ResizeEventInterface {
type: 'resize' type: 'resize'
renderer: RendererInterface renderer: RendererInterface
size: SizeInterface size: SizeInterface
@ -66,6 +67,10 @@ interface RendererSetupInterface {
} }
export interface RendererInterface extends RendererSetupInterface { export interface RendererInterface extends RendererSetupInterface {
scene?: Scene
camera?: Camera
composer?: EffectComposer
onInit(cb: InitCallbackType): void onInit(cb: InitCallbackType): void
onMounted(cb: MountedCallbackType): void onMounted(cb: MountedCallbackType): void
@ -135,6 +140,20 @@ export default defineComponent({
resizeCallbacks, resizeCallbacks,
} }
}, },
computed: {
camera: {
get: function(): Camera | undefined { return this.three.camera },
set: function(camera: Camera): void { this.three.camera = camera },
},
scene: {
get: function(): Scene | undefined { return this.three.scene },
set: function(scene: Scene): void { this.three.scene = scene },
},
composer: {
get: function(): EffectComposer | undefined { return this.three.composer },
set: function(composer: EffectComposer): void { this.three.composer = composer },
},
},
provide() { provide() {
return { return {
renderer: this, renderer: this,

View File

@ -1,22 +1,21 @@
import { defineComponent, inject, watch } from 'vue' import { defineComponent, inject, watch } from 'vue'
import { Scene, Color, Object3D } from 'three' import { Scene, Color, Object3D } from 'three'
import { ThreeInterface } from './useThree' import { RendererInterface } from './Renderer'
export default defineComponent({ export default defineComponent({
name: 'Scene', name: 'Scene',
// inject: ['three'],
props: { props: {
// id: String, // id: String,
background: [String, Number], background: [String, Number],
}, },
setup(props) { setup(props) {
const three = inject('three') as ThreeInterface const renderer = inject('renderer') as RendererInterface
const scene = new Scene() const scene = new Scene()
if (props.background) { if (props.background) {
scene.background = new Color(props.background) scene.background = new Color(props.background)
} }
watch(() => props.background, (value) => { if (scene.background instanceof Color && value) scene.background.set(value) }) watch(() => props.background, (value) => { if (scene.background instanceof Color && value) scene.background.set(value) })
return { three, scene } return { renderer, scene }
}, },
provide() { provide() {
return { return {
@ -24,8 +23,8 @@ export default defineComponent({
} }
}, },
created() { created() {
if (!this.three.scene) { if (!this.renderer.scene) {
this.three.scene = this.scene this.renderer.scene = this.scene
} }
}, },
methods: { methods: {

View File

@ -12,11 +12,11 @@ export default defineComponent({
extends: EffectPass, extends: EffectPass,
props, props,
created() { created() {
if (!this.three.scene) { if (!this.renderer.scene) {
console.error('Missing Scene') console.error('Missing Scene')
return return
} }
if (!this.three.camera) { if (!this.renderer.camera) {
console.error('Missing Camera') console.error('Missing Camera')
return return
} }
@ -25,11 +25,11 @@ export default defineComponent({
focus: this.focus, focus: this.focus,
aperture: this.aperture, aperture: this.aperture,
maxblur: this.maxblur, maxblur: this.maxblur,
width: this.three.size.width, width: this.renderer.size.width,
height: this.three.size.height, height: this.renderer.size.height,
} }
const pass = new BokehPass(this.three.scene, this.three.camera, params) const pass = new BokehPass(this.renderer.scene, this.renderer.camera, params)
Object.keys(props).forEach(p => { Object.keys(props).forEach(p => {
// @ts-ignore // @ts-ignore

View File

@ -28,7 +28,7 @@ export default defineComponent({
created() { created() {
const composer = new EffectComposer(this.renderer.renderer) const composer = new EffectComposer(this.renderer.renderer)
this.composer = composer this.composer = composer
this.renderer.three.composer = composer this.renderer.composer = composer
// this.renderer.onInit(() => { // this.renderer.onInit(() => {
this.renderer.addListener('init', () => { this.renderer.addListener('init', () => {

View File

@ -9,7 +9,7 @@ export default defineComponent({
created() { created() {
const pass = new ShaderPass(FXAAShader) const pass = new ShaderPass(FXAAShader)
// resize will be called in three init // resize will be first called in renderer init
this.renderer.addListener('resize', this.resize) this.renderer.addListener('resize', this.resize)
this.initEffectPass(pass) this.initEffectPass(pass)

View File

@ -15,7 +15,7 @@ export default defineComponent({
extends: EffectPass, extends: EffectPass,
props, props,
created() { created() {
const pass = new HalftonePass(this.three.size.width, this.three.size.height, {}) const pass = new HalftonePass(this.renderer.size.width, this.renderer.size.height, {})
Object.keys(props).forEach(p => { Object.keys(props).forEach(p => {
// @ts-ignore // @ts-ignore

View File

@ -5,15 +5,15 @@ import EffectPass from './EffectPass'
export default defineComponent({ export default defineComponent({
extends: EffectPass, extends: EffectPass,
created() { created() {
if (!this.three.scene) { if (!this.renderer.scene) {
console.error('Missing Scene') console.error('Missing Scene')
return return
} }
if (!this.three.camera) { if (!this.renderer.camera) {
console.error('Missing Camera') console.error('Missing Camera')
return return
} }
const pass = new RenderPass(this.three.scene, this.three.camera) const pass = new RenderPass(this.renderer.scene, this.renderer.camera)
this.initEffectPass(pass) this.initEffectPass(pass)
}, },
__hmrId: 'RenderPass', __hmrId: 'RenderPass',

View File

@ -5,8 +5,7 @@ import EffectPass from './EffectPass'
export default defineComponent({ export default defineComponent({
extends: EffectPass, extends: EffectPass,
created() { created() {
// three size is not set yet, but this pass will be resized by effect composer const pass = new SMAAPass(this.renderer.size.width, this.renderer.size.height)
const pass = new SMAAPass(this.three.size.width, this.three.size.height)
this.initEffectPass(pass) this.initEffectPass(pass)
}, },
__hmrId: 'SMAAPass', __hmrId: 'SMAAPass',

View File

@ -11,20 +11,20 @@ export default defineComponent({
}, },
}, },
created() { created() {
if (!this.three.scene) { if (!this.renderer.scene) {
console.error('Missing Scene') console.error('Missing Scene')
return return
} }
if (!this.three.camera) { if (!this.renderer.camera) {
console.error('Missing Camera') console.error('Missing Camera')
return return
} }
const pass = new SSAOPass( const pass = new SSAOPass(
this.three.scene, this.renderer.scene,
this.three.camera, this.renderer.camera,
this.three.size.width, this.renderer.size.width,
this.three.size.height this.renderer.size.height
) )
Object.keys(this.options).forEach(key => { Object.keys(this.options).forEach(key => {

View File

@ -13,7 +13,7 @@ export default defineComponent({
extends: EffectPass, extends: EffectPass,
props, props,
created() { created() {
const size = new Vector2(this.three.size.width, this.three.size.height) const size = new Vector2(this.renderer.size.width, this.renderer.size.height)
const pass = new UnrealBloomPass(size, this.strength, this.radius, this.threshold) const pass = new UnrealBloomPass(size, this.strength, this.radius, this.threshold)
Object.keys(props).forEach(p => { Object.keys(props).forEach(p => {

View File

@ -71,6 +71,7 @@ const Geometry = defineComponent({
export default Geometry export default Geometry
// @ts-ignore
export function geometryComponent(name, props, createGeometry) { export function geometryComponent(name, props, createGeometry) {
return defineComponent({ return defineComponent({
name, name,

View File

@ -32,7 +32,7 @@ export default defineComponent({
}, },
// update points (without using prop, faster) // update points (without using prop, faster)
updatePoints(points: Vector3[]) { updatePoints(points: Vector3[]) {
updateTubeGeometryPoints(this.geometry, points) updateTubeGeometryPoints(this.geometry as TubeGeometry, points)
}, },
}, },
}) })

View File

@ -64,8 +64,10 @@ export default defineComponent({
// @ts-ignore // @ts-ignore
watch(() => this[p], (value) => { watch(() => this[p], (value) => {
if (p === 'color') { if (p === 'color') {
// @ts-ignore
this.material.color.set(value) this.material.color.set(value)
} else { } else {
// @ts-ignore
this.material[p] = value this.material[p] = value
} }
}) })

View File

@ -32,10 +32,12 @@ export default defineComponent({
// TODO : use setProp, handle flatShading ? // TODO : use setProp, handle flatShading ?
Object.keys(props).forEach(p => { Object.keys(props).forEach(p => {
if (p === 'normalScale') return if (p === 'normalScale') return
// @ts-ignore
watch(() => this[p], (value) => { watch(() => this[p], (value) => {
if (p === 'emissive') { if (p === 'emissive') {
material[p].set(value) material[p].set(value)
} else { } else {
// @ts-ignore
material[p] = value material[p] = value
} }
}) })

View File

@ -1,9 +1,11 @@
import { defineComponent } from 'vue' import { meshComponent } from './Mesh'
import Mesh, { defaultSetup, meshComponent } from './Mesh'
import { props, createGeometry } from '../geometries/BoxGeometry' import { props, createGeometry } from '../geometries/BoxGeometry'
export default meshComponent('Box', props, createGeometry) export default meshComponent('Box', props, createGeometry)
// import { defineComponent } from 'vue'
// import Mesh, { meshComponent } from './Mesh'
//
// export default defineComponent({ // export default defineComponent({
// extends: Mesh, // extends: Mesh,
// props, // props,

View File

@ -101,6 +101,7 @@ const Mesh = defineComponent({
export default Mesh export default Mesh
// @ts-ignore
export function meshComponent(name, props, createGeometry) { export function meshComponent(name, props, createGeometry) {
return defineComponent({ return defineComponent({
name, name,

View File

@ -1,69 +0,0 @@
import { defineComponent, watch } from 'vue';
import { FontLoader, TextGeometry } from 'three';
import Mesh from './Mesh.js';
const props = {
text: String,
fontSrc: String,
size: { type: Number, default: 80 },
height: { type: Number, default: 5 },
depth: { type: Number, default: 1 },
curveSegments: { type: Number, default: 12 },
bevelEnabled: { type: Boolean, default: false },
bevelThickness: { type: Number, default: 10 },
bevelSize: { type: Number, default: 8 },
bevelOffset: { type: Number, default: 0 },
bevelSegments: { type: Number, default: 5 },
align: { type: [Boolean, String], default: false },
};
export default defineComponent({
extends: Mesh,
props,
data() {
return {
loading: true,
};
},
created() {
// add watchers
const watchProps = [
'text', 'size', 'height', 'curveSegments',
'bevelEnabled', 'bevelThickness', 'bevelSize', 'bevelOffset', 'bevelSegments',
'align',
];
watchProps.forEach(p => {
watch(() => this[p], () => {
if (this.font) this.refreshGeometry();
});
});
const loader = new FontLoader();
loader.load(this.fontSrc, (font) => {
this.loading = false;
this.font = font;
this.createGeometry();
this.initMesh();
});
},
methods: {
createGeometry() {
this.geometry = new TextGeometry(this.text, {
font: this.font,
size: this.size,
height: this.height,
depth: this.depth,
curveSegments: this.curveSegments,
bevelEnabled: this.bevelEnabled,
bevelThickness: this.bevelThickness,
bevelSize: this.bevelSize,
bevelOffset: this.bevelOffset,
bevelSegments: this.bevelSegments,
});
if (this.align === 'center') {
this.geometry.center();
}
},
},
});

View File

@ -1,7 +1,7 @@
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { TubeGeometry, Vector3 } from 'three'
import Mesh from './Mesh' import Mesh from './Mesh'
import { props, createGeometry, updateTubeGeometryPoints } from '../geometries/TubeGeometry' import { props, createGeometry, updateTubeGeometryPoints } from '../geometries/TubeGeometry'
import { Vector3 } from 'three'
export default defineComponent({ export default defineComponent({
extends: Mesh, extends: Mesh,
@ -16,7 +16,7 @@ export default defineComponent({
}, },
// update curve points (without using prop, faster) // update curve points (without using prop, faster)
updatePoints(points: Vector3[]) { updatePoints(points: Vector3[]) {
updateTubeGeometryPoints(this.geometry, points) updateTubeGeometryPoints(this.geometry as TubeGeometry, points)
}, },
}, },
__hmrId: 'Tube', __hmrId: 'Tube',

View File

@ -76,6 +76,7 @@ export const TroisJSVuePlugin = {
] ]
comps.forEach(comp => { comps.forEach(comp => {
// @ts-ignore
app.component(comp, TROIS[comp]) app.component(comp, TROIS[comp])
}) })
}, },