1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-25 04:42:01 +08:00
trois/src/core/Renderer.ts

151 lines
4.1 KiB
TypeScript
Raw Normal View History

2021-04-19 09:22:02 +08:00
import { WebGLRenderer } from 'three'
2021-04-19 04:27:53 +08:00
import { defineComponent } from 'vue'
2021-04-19 09:22:02 +08:00
import useThree, { ThreeConfigInterface, ThreeInterface } from './useThree'
2021-04-16 07:56:52 +08:00
2021-04-19 09:22:02 +08:00
type CallbackType<T> = (e: T) => void
interface EventInterface<T> {
renderer: T
}
interface RenderEventInterface<T> extends EventInterface<T> {
time: number
}
export interface RendererInterface {
canvas: HTMLCanvasElement
three: ThreeInterface
renderer: WebGLRenderer
renderFn(): void
raf: boolean
onMountedCallbacks: CallbackType<EventInterface<this>>[]
beforeRenderCallbacks: CallbackType<RenderEventInterface<this>>[]
afterRenderCallbacks: CallbackType<RenderEventInterface<this>>[]
2021-04-19 04:27:53 +08:00
}
2021-04-19 09:22:02 +08:00
type MountedCallbackType = CallbackType<EventInterface<RendererInterface>>
type RenderCallbackType = CallbackType<RenderEventInterface<RendererInterface>>
2021-04-19 04:27:53 +08:00
2021-04-16 07:56:52 +08:00
export default defineComponent({
name: 'Renderer',
props: {
antialias: Boolean,
alpha: Boolean,
autoClear: { type: Boolean, default: true },
orbitCtrl: { type: [Boolean, Object], default: false },
pointer: { type: [Boolean, Object], default: false },
resize: { type: [Boolean, String], default: false },
shadow: Boolean,
width: String,
height: String,
xr: Boolean,
2021-04-19 04:27:53 +08:00
onReady: Function,
2021-04-19 09:22:02 +08:00
// onFrame: Function,
2021-04-16 07:56:52 +08:00
},
2021-04-19 09:22:02 +08:00
setup(props): RendererInterface {
2021-04-19 04:27:53 +08:00
const canvas = document.createElement('canvas')
const config: ThreeConfigInterface = {
canvas,
antialias: props.antialias,
alpha: props.alpha,
autoClear: props.autoClear,
orbitCtrl: props.orbitCtrl,
pointer: props.pointer,
resize: props.resize,
}
if (props.width) config.width = parseInt(props.width)
if (props.height) config.height = parseInt(props.height)
const three = useThree(config)
const renderFn: {(): void} = () => {}
2021-04-16 07:56:52 +08:00
const onMountedCallbacks: {(): void}[] = []
const beforeRenderCallbacks: {(): void}[] = []
const afterRenderCallbacks: {(): void}[] = []
return {
2021-04-19 04:27:53 +08:00
canvas,
three,
renderer: three.renderer,
renderFn,
2021-04-16 07:56:52 +08:00
raf: true,
onMountedCallbacks,
beforeRenderCallbacks,
afterRenderCallbacks,
}
},
provide() {
return {
renderer: this,
three: this.three,
}
},
mounted() {
2021-04-19 04:27:53 +08:00
// appendChild won't work on reload
this.$el.parentNode.insertBefore(this.canvas, this.$el)
2021-04-16 07:56:52 +08:00
2021-04-19 04:27:53 +08:00
if (this.three.init()) {
this.onReady?.(this)
2021-04-16 07:56:52 +08:00
this.renderer.shadowMap.enabled = this.shadow
2021-04-19 04:27:53 +08:00
this.renderFn = this.three.composer ? this.three.renderC : this.three.render
2021-04-16 07:56:52 +08:00
if (this.xr) {
this.renderer.xr.enabled = true
this.renderer.setAnimationLoop(this.render)
} else {
requestAnimationFrame(this.renderLoop)
}
2021-04-16 10:12:41 +08:00
}
2021-04-16 07:56:52 +08:00
2021-04-19 09:22:02 +08:00
this.onMountedCallbacks.forEach(c => c({ renderer: this }))
2021-04-16 07:56:52 +08:00
},
beforeUnmount() {
2021-04-19 04:27:53 +08:00
this.canvas.remove()
2021-04-16 07:56:52 +08:00
this.beforeRenderCallbacks = []
this.afterRenderCallbacks = []
this.raf = false
this.three.dispose()
},
methods: {
onMounted(cb: {(): void}) {
this.onMountedCallbacks.push(cb)
},
onBeforeRender(cb: {(): void}) {
this.beforeRenderCallbacks.push(cb)
},
offBeforeRender(cb: {(): void}) {
this.beforeRenderCallbacks = this.beforeRenderCallbacks.filter(c => c !== cb)
},
onAfterRender(cb: {(): void}) {
this.afterRenderCallbacks.push(cb)
},
offAfterRender(cb: {(): void}) {
this.afterRenderCallbacks = this.afterRenderCallbacks.filter(c => c !== cb)
},
onAfterResize(cb: {(): void}) {
this.three.onAfterResize(cb)
},
offAfterResize(cb: {(): void}) {
this.three.offAfterResize(cb)
},
render(time: number) {
2021-04-19 04:27:53 +08:00
const cbParams = { time, renderer: this }
this.beforeRenderCallbacks.forEach(cb => cb(cbParams))
2021-04-19 09:22:02 +08:00
// this.onFrame?.(cbParams)
2021-04-19 04:27:53 +08:00
this.renderFn()
this.afterRenderCallbacks.forEach(cb => cb(cbParams))
2021-04-16 07:56:52 +08:00
},
renderLoop(time: number) {
if (this.raf) requestAnimationFrame(this.renderLoop)
this.render(time)
},
},
render() {
2021-04-19 04:27:53 +08:00
return this.$slots.default ? this.$slots.default() : []
2021-04-16 07:56:52 +08:00
},
__hmrId: 'Renderer',
})