瀏覽代碼

refactor: streamline useRenderer and integrate render state management

Tino Koch 2 月之前
父節點
當前提交
c89a4ffa99

+ 0 - 1
src/composables/index.ts

@@ -6,7 +6,6 @@ export * from './useGraph'
 export * from './useLoader'
 export * from './useLoop'
 export * from './useRaycaster'
-export * from './useRenderer/'
 export * from './useRenderLoop'
 export * from './useSeek'
 export * from './useTexture'

+ 34 - 5
src/composables/useRenderer/index.ts

@@ -1,22 +1,32 @@
 import type { TresCanvasProps } from 'src/components/TresCanvas.vue'
 import { createRenderer } from 'src/core/createRenderer'
-import type { TresRendererSetupContext } from '../../composables'
 import { WebGLRenderer } from 'three'
 import { setupWebGLRenderer } from 'src/core/setupRenderer'
 import { onUnmounted } from 'vue'
+import type { RenderState, TresContext } from '../useTresContextProvider'
+import type { EmitEventFn } from 'types'
+
+export type TresRendererSetupContext = Pick< // TODO make this public
+  TresContext,
+  'sizes' | 'scene' | 'camera' | 'canvas' | 'invalidate' | 'advance' | 'loop'
+>
 
 export async function useRenderer({
-  contextParts: ctx,
+  emit,
   options,
+  renderState, // TODO think about embedding this in this composable
+  contextParts,
 }: {
-  contextParts: TresRendererSetupContext
+  emit: EmitEventFn
   options: TresCanvasProps
+  renderState: RenderState
+  contextParts: TresRendererSetupContext
 }) {
-  const renderer = await createRenderer(ctx, options)
+  const renderer = await createRenderer(contextParts, options)
 
   // For now we only support WebGLRenderer. If the user wants to use their own renderer, it is their responsibility to handle the disposal and stuff like that.
   if (renderer instanceof WebGLRenderer) {
-    setupWebGLRenderer(renderer, options, ctx) // TODO use contents directly
+    setupWebGLRenderer(renderer, options, contextParts) // TODO use contents directly
 
     onUnmounted(() => {
       renderer.dispose()
@@ -24,5 +34,24 @@ export async function useRenderer({
     })
   }
 
+  const { camera, scene } = contextParts
+
+  contextParts.loop.register(() => {
+    if (camera.value && renderState.frames.value > 0) {
+      renderer.render(scene.value, camera.value)
+      emit('render', renderer)
+    }
+
+    // Reset priority
+    renderState.priority.value = 0
+
+    if (renderState.mode.value === 'always') {
+      renderState.frames.value = 1
+    }
+    else {
+      renderState.frames.value = Math.max(0, renderState.frames.value - 1)
+    }
+  }, 'render')
+
   return renderer
 }

+ 12 - 34
src/composables/useTresContextProvider/index.ts

@@ -84,11 +84,6 @@ export interface TresContext {
   deregisterBlockingObjectAtPointerEventHandler?: (object: TresObject) => void
 }
 
-export type TresRendererSetupContext = Pick<
-  TresContext,
-  'sizes' | 'scene' | 'camera' | 'canvas' | 'invalidate' | 'advance'
->
-
 export async function useTresContextProvider({
   scene,
   canvas,
@@ -113,30 +108,29 @@ export async function useTresContextProvider({
     setCameraActive,
   } = useCamera({ sizes, scene })
 
-  // Render state
-
-  const render: RenderState = {
+  const renderState: RenderState = { // TODO rename // TODO make separate
     mode: ref(rendererOptions.renderMode || 'always') as Ref<'always' | 'on-demand' | 'manual'>,
     priority: ref(0),
     frames: ref(0),
-    maxFrames: 60,
-    canBeInvalidated: computed(() => render.mode.value === 'on-demand' && render.frames.value === 0),
+    maxFrames: 60, // TODO add issue for prop
+    canBeInvalidated: computed(() => renderState.mode.value === 'on-demand' && renderState.frames.value === 0),
   }
 
   function invalidate(frames = 1) {
     // Increase the frame count, ensuring not to exceed a maximum if desired
     if (rendererOptions.renderMode === 'on-demand') {
-      render.frames.value = Math.min(render.maxFrames, render.frames.value + frames)
+      renderState.frames.value = Math.min(renderState.maxFrames, renderState.frames.value + frames)
     }
   }
 
   function advance() {
     if (rendererOptions.renderMode === 'manual') {
-      render.frames.value = 1
+      renderState.frames.value = 1
     }
   }
 
-  // Renderer
+  const loop = createRenderLoop()
+
   const renderer = await useRenderer({
     contextParts: {
       sizes,
@@ -145,8 +139,11 @@ export async function useTresContextProvider({
       canvas,
       advance,
       invalidate,
+      loop,
     },
     options: rendererOptions,
+    emit,
+    renderState,
   })
 
   const ctx: TresContext = {
@@ -170,13 +167,13 @@ export async function useTresContextProvider({
         accumulator: [],
       },
     },
-    render,
+    render: renderState,
     advance,
     invalidate,
     registerCamera,
     setCameraActive,
     deregisterCamera,
-    loop: createRenderLoop(),
+    loop,
   }
 
   provide('useTres', ctx)
@@ -186,25 +183,6 @@ export async function useTresContextProvider({
     root: ctx,
   }
 
-  // The loop
-
-  ctx.loop.register(() => {
-    if (ctx.renderer.value && camera.value && render.frames.value > 0) {
-      ctx.renderer.value.render(scene, camera.value)
-      emit('render', ctx.renderer.value)
-    }
-
-    // Reset priority
-    render.priority.value = 0
-
-    if (render.mode.value === 'always') {
-      render.frames.value = 1
-    }
-    else {
-      render.frames.value = Math.max(0, render.frames.value - 1)
-    }
-  }, 'render')
-
   const { on: onTresReady, cancel: cancelTresReady } = useTresReady(ctx)!
 
   ctx.loop.setReady(false)

+ 1 - 1
src/core/createRenderer.ts

@@ -1,5 +1,5 @@
 import { WebGLRenderer } from 'three'
-import type { TresRendererSetupContext } from '../composables'
+import type { TresRendererSetupContext } from '../composables/useRenderer'
 import type { TresRenderer } from '../types'
 import type { TresCanvasProps } from '../components/TresCanvas.vue'
 import { toValue } from 'vue'