Sfoglia il codice sorgente

fix(core): fixed camera aspect ratio and renderer container issues

Alvaro 2 anni fa
parent
commit
eb0c516c61

+ 0 - 1
packages/tres/src/components/TheExperience.vue

@@ -28,7 +28,6 @@ const state = reactive({
   toneMapping: NoToneMapping,
   toneMapping: NoToneMapping,
 })
 })
 
 
-const boxRef = ref()
 const sphereRef = ref()
 const sphereRef = ref()
 
 
 const { pane } = useTweakPane()
 const { pane } = useTweakPane()

+ 29 - 0
packages/tres/src/components/TheSmallExperience.vue

@@ -0,0 +1,29 @@
+<script setup lang="ts">
+import { OrbitControls } from '../../../cientos/src/'
+</script>
+<template>
+  <div class="container">
+    <TresCanvas>
+      <TresPerspectiveCamera :position="[5, 5, 5]" :fov="75" :aspect="1" :near="0.1" :far="1000" />
+      <OrbitControls />
+      <TresScene>
+        <TresAmbientLight :color="0xffffff" :intensity="0.5" />
+        <TresMesh ref="sphereRef" :scale="1" cast-shadow>
+          <TresSphereGeometry :args="[1, 500, 500]" />
+          <TresMeshToonMaterial color="#FBB03B" />
+        </TresMesh>
+      </TresScene>
+    </TresCanvas>
+  </div>
+</template>
+
+<style scoped>
+.container {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  aspect-ratio: 16/9;
+  background: white;
+  width: 50%;
+}
+</style>

+ 8 - 9
packages/tres/src/core/useCamera/index.ts

@@ -1,7 +1,6 @@
 import { useTres } from '/@/core/'
 import { useTres } from '/@/core/'
 import { PerspectiveCamera, OrthographicCamera } from 'three'
 import { PerspectiveCamera, OrthographicCamera } from 'three'
 
 
-import { useWindowSize } from '@vueuse/core'
 import { computed, ComputedRef, watch, inject, Ref } from 'vue'
 import { computed, ComputedRef, watch, inject, Ref } from 'vue'
 
 
 export enum CameraType {
 export enum CameraType {
@@ -45,7 +44,8 @@ const VERTICAL_FIELD_OF_VIEW = 45
 let camera: Camera
 let camera: Camera
 
 
 export function useCamera(): UseCameraReturn {
 export function useCamera(): UseCameraReturn {
-  const { width, height } = useWindowSize()
+  const aspectRatio = inject<ComputedRef<number>>('aspect-ratio')
+
   const { setState } = useTres()
   const { setState } = useTres()
 
 
   function createCamera(
   function createCamera(
@@ -58,7 +58,7 @@ export function useCamera(): UseCameraReturn {
         far: 1000,
         far: 1000,
         fov: VERTICAL_FIELD_OF_VIEW,
         fov: VERTICAL_FIELD_OF_VIEW,
       }
       }
-      camera = new PerspectiveCamera(fov, aspectRatio.value, near, far)
+      camera = new PerspectiveCamera(fov, aspectRatio?.value || 1, near, far)
       state.cameras.push(camera as PerspectiveCamera)
       state.cameras.push(camera as PerspectiveCamera)
     } else {
     } else {
       const { left, right, top, bottom, near, far } = (options as OrthographicCameraOptions) || {
       const { left, right, top, bottom, near, far } = (options as OrthographicCameraOptions) || {
@@ -77,12 +77,10 @@ export function useCamera(): UseCameraReturn {
     return camera
     return camera
   }
   }
 
 
-  const aspectRatio = computed(() => width.value / height.value)
-
   const activeCamera = computed(() => state.cameras[0])
   const activeCamera = computed(() => state.cameras[0])
 
 
   function updateCamera() {
   function updateCamera() {
-    if (activeCamera.value instanceof PerspectiveCamera) {
+    if (activeCamera.value instanceof PerspectiveCamera && aspectRatio) {
       activeCamera.value.aspect = aspectRatio.value
       activeCamera.value.aspect = aspectRatio.value
     }
     }
     activeCamera.value.updateProjectionMatrix()
     activeCamera.value.updateProjectionMatrix()
@@ -95,14 +93,15 @@ export function useCamera(): UseCameraReturn {
       setState('camera', currentCamera.value)
       setState('camera', currentCamera.value)
     }
     }
     state.cameras.push(camera)
     state.cameras.push(camera)
-    if (camera instanceof PerspectiveCamera) {
+    if (camera instanceof PerspectiveCamera && aspectRatio) {
       camera.aspect = aspectRatio.value
       camera.aspect = aspectRatio.value
     }
     }
     camera.updateProjectionMatrix()
     camera.updateProjectionMatrix()
   }
   }
 
 
-  watch(aspectRatio, updateCamera)
-
+  if (aspectRatio) {
+    watch(aspectRatio, updateCamera)
+  }
   return {
   return {
     activeCamera,
     activeCamera,
     createCamera,
     createCamera,

+ 11 - 4
packages/tres/src/core/useRenderer/component.ts

@@ -21,7 +21,7 @@ export const TresCanvas = defineComponent({
     powerPreference: Object as PropType<'high-performance' | 'low-power' | 'default'>,
     powerPreference: Object as PropType<'high-performance' | 'low-power' | 'default'>,
     preserveDrawingBuffer: Boolean,
     preserveDrawingBuffer: Boolean,
     clearColor: String,
     clearColor: String,
-    windowSize: Boolean,
+    windowSize: { type: Boolean, default: false },
   },
   },
   setup(props, { slots, attrs }) {
   setup(props, { slots, attrs }) {
     const { logError } = useLogger()
     const { logError } = useLogger()
@@ -31,11 +31,12 @@ export const TresCanvas = defineComponent({
 
 
     const { renderer, dispose, aspectRatio } = useRenderer(canvas, container, props)
     const { renderer, dispose, aspectRatio } = useRenderer(canvas, container, props)
 
 
+    provide('aspect-ratio', aspectRatio)
+    provide('renderer', renderer)
+
     const activeCamera = shallowRef()
     const activeCamera = shallowRef()
 
 
     provide('camera', activeCamera)
     provide('camera', activeCamera)
-    provide('renderer', renderer)
-    provide('aspect-ratio', aspectRatio)
 
 
     if (slots.default && !slots.default().some(node => (node.type as TresVNodeType).name === 'Scene')) {
     if (slots.default && !slots.default().some(node => (node.type as TresVNodeType).name === 'Scene')) {
       logError('TresCanvas must contain a Scene component.')
       logError('TresCanvas must contain a Scene component.')
@@ -62,7 +63,13 @@ export const TresCanvas = defineComponent({
           [
           [
             h('canvas', {
             h('canvas', {
               ref: canvas,
               ref: canvas,
-              style: { width: '100%', height: '100%', position: 'absolute', top: 0, left: 0 },
+              style: {
+                width: '100%',
+                height: '100%',
+                position: props.windowSize ? 'fixed' : 'absolute',
+                top: 0,
+                left: 0,
+              },
             }),
             }),
             slots.default(),
             slots.default(),
           ],
           ],

+ 2 - 1
packages/tres/src/core/useRenderer/index.ts

@@ -208,7 +208,8 @@ export function useRenderer(canvas: MaybeElementRef, container: MaybeElementRef,
     pause()
     pause()
   }
   }
 
 
-  watch([width, height, pixelRatio], updateRendererSize)
+  watch([aspectRatio, pixelRatio], updateRendererSize)
+
   watch(
   watch(
     [shadows, shadowMapType, outputEncoding, physicallyCorrectLights, toneMapping, toneMappingExposure, clearColor],
     [shadows, shadowMapType, outputEncoding, physicallyCorrectLights, toneMapping, toneMappingExposure, clearColor],
     updateRendererOptions,
     updateRendererOptions,