Pārlūkot izejas kodu

Merge branch 'main' into feature/474-vue-chrome-devtools-plugin

alvarosabu 1 gadu atpakaļ
vecāks
revīzija
baed8eeb07

+ 9 - 0
CHANGELOG.md

@@ -1,5 +1,14 @@
 
 
+## [3.6.1](https://github.com/Tresjs/tres/compare/3.6.0...3.6.1) (2024-01-16)
+
+
+### Bug Fixes
+
+* correct minor typos ([#438](https://github.com/Tresjs/tres/issues/438)) ([341faac](https://github.com/Tresjs/tres/commit/341faacb93fd347aced7f1bc7e0484ecbc12e6ce)), closes [#452](https://github.com/Tresjs/tres/issues/452)
+* incorrect MathRepresentation type ([#456](https://github.com/Tresjs/tres/issues/456)) ([314b088](https://github.com/Tresjs/tres/commit/314b0883b78ded0cad2bdf9f2506bbeac4a0817e))
+* **usetrescontextprovider:** fixed rendering issues caused when resize is triggered ([#512](https://github.com/Tresjs/tres/issues/512)) ([a16b12b](https://github.com/Tresjs/tres/commit/a16b12b160098e97993b14a7bb054103c88b6263)), closes [#511](https://github.com/Tresjs/tres/issues/511)
+
 ## [3.6.0](https://github.com/Tresjs/tres/compare/3.5.2...3.6.0) (2023-12-12)
 
 

+ 2 - 0
docs/.vitepress/config.ts

@@ -73,6 +73,8 @@ export default defineConfig({
           { text: 'Load Textures', link: '/examples/load-textures' },
           { text: 'Load Models', link: '/examples/load-models' },
           { text: 'Load Text', link: '/examples/text-3d' },
+          { text: 'Lights & Shadows', link: '/examples/lights-shadows' },
+          { text: 'Shaders', link: '/examples/shaders' },
         ],
       },
       {

+ 174 - 0
docs/examples/lights-shadows.md

@@ -0,0 +1,174 @@
+# Light-shadows
+
+This guide will help you get started with simple light and shadows in TresJS.
+
+We will build a simple scene with three meshes and a plane but only two will have shadows.
+<SandboxDemo url="https://play.tresjs.org/#eNqVVt1y2jwQfRUN30WSKdimhLbjL3Qo9GfaadpM4K7uhbAXUGpLGkn8pJm8e1eSDXZCMmRCGGv37NHZ1XrFXWuqQH+QMlivoBW3LnSqmDREg1lJklO+GCQto5PW+4SzQgplyB3RS5rnYnMNc3JP5koU5ASjT/6vQSzrmPI11W2y0nANPAP1XQhZBQwNIm50mArVjPypZsyMBTdK5HrHv4Mz4EboRsSIapZOljQTm0sq22Ry/WU0FrlQE0lTaJMfYio4oEsyvtgxmqUCOEl4wlPBtSGLnAzIXcIJSXOgyhHE5OS/d68/jsb9k7b1YOK4iY6JUStwFprLJY3JnObaGzwEN5veSogfarMIsTJyhRlWAuOHgi3I7BXHzQTQfb9XPRNbewyD2pmcnu3dd0RwW3XMetA8B4/y3tPTMzJ475Nn81PPGaxpvoIzZ6xbAiUMNUzw4Ja8GpAoiLoWgpruHWXCL0LfRNgyuDBQyJwawBUhF/u+IOvOjPEM22uRJy2ywWex6Wj21yMR2+yEsDJbiitQWkJq2BrGtABFSSyFZlYWEv7qt8nbwH/9Ru54LtZoPu/bZ+oCcdm1K45Hjc9R4FZzt+hGUYSrxoaXoJfNPTqv2wQ/kdugqol1RG1ySc0yuPrqvSVNlTye5BcQBRh1i2LUQtuYbpt0reCeZas2rm09FYIjKShGc5LaVsGosjXrUsMq4JF2BXMM8QeJESnVpuN7tZkWqrefR7pHYntAttVcfb1I+vln+3ec9LrWplisvz2Gx2oncglqX+ejZX0ejaLe6NiKpoD991QVO71DzdEpW4OErnkOab/CqXuoRRC8/3+i2BNDeUZV9jiz+Vv791Rmtdw+FDM7Y7+zxdKQmHEDHPO6LV+YxkvxkWENbGY09/Dnumr3rhym9HL8aEDDRVibG612yw/7TkFlcKMFx5vKDaakdOAFFfv5ZW31u8U6ktbSGKnjMEwzjvEZ5GytAg4m5LII6/BhL+gHUZgxbUJrRnTSchO5QexvoZdw+wikf1OnL83NXcwG6B+JTXAE/w47PA9wiJXMlTEomI2pc9tb7xheixsiY/8d6n0FuqiXAW97vEyOrm8NPuxGrsA47WEbFM3qljhsIAXZC4h9wHPUCOxkULAjSCuoTf48eBPmbFanrO467Emj8ZKds8WDjkxFIVkO6qe03d/sTHdHf3O23U8IF7OE9M8B+43eeslX2Cyg1lju/VHiZADj3Z8mP2CLzztnIbJVXh7OE85r0CJfWY0eNlrxDGXXcE7tV/eC4Q+Pqf60dW9umVRDqMFfO876q5pJu17zht+ucA7vjmP8TJX2mfWC3q7g9/8AWlN6bg==" />
+
+## Setting up the scene (optional)
+
+We import all the modules that we need, for comfort we can use the orbit-controls from cientos,
+[check here to know how](/examples/orbit-controls).
+
+Let's put four objects in our scene, one will be the plane that receive shadows, two of them will cast shadows and the last one will not cast any shadow at all.
+
+I'm going to use [MeshToonMaterial](https://threejs.org/docs/index.html?q=toon#api/en/materials/MeshToonMaterial). Simply because we can see the "soft shadow" easily.
+
+```vue
+<script setup lang="ts">
+import { TresCanvas } from '@tresjs/core'
+import { OrbitControls } from '@tresjs/cientos'
+</script>
+
+<template>
+  <TresCanvas
+    clear-color="#111"
+    window-size
+  >
+    <OrbitControls />
+    <TresPerspectiveCamera :position="[5, 7.5, 7.5]" />
+
+    <TresMesh
+      :position="[-2, 2, 0]"
+      :rotation="[0, Math.PI, 0]"
+    >
+      <TresConeGeometry :args="[1, 1.5, 3]" />
+      <TresMeshToonMaterial color="#82DBC5" />
+    </TresMesh>
+    <TresMesh
+      :position="[0, 0, 0]"
+    >
+      <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
+      <TresMeshToonMaterial color="#4F4F4F" />
+    </TresMesh>
+    <TresMesh
+      :position="[2, -2, 0]"
+    >
+      <TresSphereGeometry />
+      <TresMeshToonMaterial color="#FBB03B" />
+    </TresMesh>
+    <TresMesh
+      :position="[0, -3, 0]"
+      :rotation="[-Math.PI / 2, 0, 0]"
+    >
+      <TresPlaneGeometry :args="[10, 10, 10, 10]" />
+      <TresMeshStandardMaterial color="#f7f7f7" />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+
+## Lights (explanation)
+
+As you know every instance in [ThreeJs](https://threejs.org/) is available in **TresJs** so are all the light types, we just need to add the `Tres` prefix to use them.
+
+But not all lights can cast shadows, this definition comes directly from ThreeJs and makes sense, for example the purpose of an [ambientLight](https://threejs.org/docs/index.html?q=ambient#api/en/lights/AmbientLight) is to iluminate everysingle side of your scene, so it makes no sense for it to cast shadows, on the contrary, a [DirectionalLight](https://threejs.org/docs/index.html?q=light#api/en/helpers/DirectionalLightHelper) immitating the sun can and should cast shadows.
+
+## Shadows (explanation)
+
+There are also many types of shadows, for example the "soft shadow" is generated automatially when an object receives more light from one side, but in summary a "ThreeJS default shadow" that is directed towards another surface needs to be cast by a mesh and another mesh needs to receive it. As we see in our example, the `Plane` is receiving a shadow but not casting it. Please note that not all materials can cast or receive shadows.
+
+Internally, ThreeJS automatically generates a new mesh with a [ShadowMaterial](https://threejs.org/docs/index.html?q=shado#api/en/materials/ShadowMaterial) which gets updated in each frame, that is why if you apply animations, the shadow also is animated, but also why you have to use shadows carefully, because they could slow your performance down.
+
+::: warning
+The overuse of shadows in this way could drop your performance. However, there are ways to increase your performance, for more information please check out [this video](https://youtu.be/WGNvVGrS0kY?si=q7XyL5eABKUh3gbS&t=1256)
+:::
+
+## Enabling shadows
+
+We could divide this into three steps:
+
+### Activate shadows on the renderer
+
+```vue
+//...
+
+<template>
+  <TresCanvas
+    clear-color="#111"
+    shadows
+    window-size
+  />
+  //...
+</template>
+```
+### Set the light to cast shadows
+
+We can simple put the boolean `cast-shadow`, Vue understand this as a `prop` with `true` value
+
+_The AmbientLight doesn't generate any type of shadow here_
+
+```vue
+//...
+
+<template>
+  <TresAmbientLight :intensity="1" />
+  <TresDirectionalLight
+    cast-shadow
+    :position="[0, 2, 0]"
+    :intensity="1"
+  />
+  
+  //...
+</template>
+```
+### Set the objects to cast or receive shadows
+
+Similarly to the previous step, we set the mesh that we want to cast shadow (our sphere) with the `cast-shadow` prop, and set the object to receive shadow (our plane) with the `receive-shadow` prop.
+
+```vue
+//...
+
+<template>
+  <TresMesh
+    cast-shadow
+    :position="[2, -2, 0]"
+  >
+    <TresSphereGeometry />
+    <TresMeshToonMaterial color="#FBB03B" />
+  </TresMesh>
+  <TresMesh
+    receive-shadow
+    :position="[0, -3, 0]"
+    :rotation="[-Math.PI / 2, 0, 0]"
+  >
+    <TresPlaneGeometry :args="[10, 10, 10, 10]" />
+    <TresMeshStandardMaterial color="#f7f7f7" />
+  </TresMesh>
+  //...
+</template>
+```
+
+Now we have all the necessary steps to add shadows to our scene, and if we apply what we learned in [basic animations](/examples/basic-animations), and we add movement to our cube, you will see the shadow is animated as well 🤩
+
+```vue
+<script setup>
+import { shallowRef } from 'vue'
+import { TresCanvas, useRenderLoop } from '@tresjs/core'
+
+const boxRef = shallowRef()
+
+const { onLoop } = useRenderLoop()
+
+onLoop(() => {
+  if (boxRef.value) {
+    boxRef.value.rotation.y += 0.01
+  }
+})
+</script>
+
+<template>
+  //...
+  <TresMesh
+    ref="boxRef"
+    cast-shadow
+    :position="[0, 0, 0]"
+  >
+    <TresBoxGeometry :args="[1.5, 1.5, 1.5]" />
+    <TresMeshToonMaterial color="#4F4F4F" />
+  </TresMesh>
+  //...
+</template>
+```
+
+_Note that I intentionally did not apply `cast-shadow` to the `Cone` so it doesn't cast any shadow_

+ 7 - 9
docs/examples/load-models.md

@@ -10,6 +10,10 @@ For this guide we are going to focus on loading gLTF (GL Transmission Format) mo
 
 There are several ways to load models on TresJS:
 
+::: warning
+Please note that the examples above we use top level await, make sure you wrap it with a [Suspense](https://vuejs.org/guide/built-ins/suspense.html#suspense) component. See Suspense for more information. .
+:::
+
 ## Using `useLoader`
 
 The `useLoader` composable allows you to pass any type of three.js loader and a URL to load the resource from. It returns a `Promise` with the loaded resource.
@@ -25,11 +29,9 @@ const { scene } = await useLoader(GLTFLoader, '/models/AkuAku.gltf')
 
 Then you can pass the model scene to a TresJS [`primitive`](/advanced/primitive) component to render it:
 
-```html{3}
+```html{2}
 <TresCanvas>
-  <Suspense>
     <primitive :object="scene" />
-  </Suspense>
 </TresCanvas>
 ```
 
@@ -72,9 +74,7 @@ const { scene, nodes, animations, materials } = await useGLTF('/models/AkuAku.gl
   >
     <TresPerspectiveCamera :position="[11, 11, 11]" />
     <OrbitControls />
-    <Suspense>
-      <primitive :object="nodes.MyModel" />
-    </Suspense>
+    <primitive :object="nodes.MyModel" /> // please note that "MyModel" here is just a placeholder 
   </TresCanvas>
 </template>
 ```
@@ -113,11 +113,9 @@ const model = await useFBX('/models/AkuAku.fbx')
 
 Then is as straightforward as adding the scene to your scene:
 
-```html{3}
+```html{2}
 <TresCanvas shadows alpha>
-  <Suspense>
     <primitive :object="scene" />
-  </Suspense>
 </TresCanvas>
 ```
 

+ 174 - 0
docs/examples/shaders.md

@@ -0,0 +1,174 @@
+# Shaders
+
+This guide will help you get started with shaders in TresJS.
+
+We will build a simple scene with a blob. We will then animate the blob to softly distorted it.
+
+::: warning
+_Basic knowledge of how shaders work is necessary_
+:::
+
+<SandboxDemo url="https://play.tresjs.org/#eNqVVltv2zYU/iuE91BntSU7cYrBS4q0QTt0WNcgyfZSFxsjH9tMJVIjKdle4P++j9TFVJMU3oMDndvH71x4mIferSbzJs+jsqDetHdmEi1yywzZImcpl8vzWc+aWe/1TIosV9qyB2ZWPE3V+poWbMcWWmXsBaJf/By4ONRLLktuBqwwdE1yTvo3pfI24sLC5d7EidLd0E/6TthLJa1WqXnsLkhaZToRf1JilT5ufe1KE72YyZlMlDSW3aXqzpE9D5j3ZZGmR0BpnAopFkpnBl4PM8lYcSsymgK95GmBjxHbDbz+TZanwhbz0Chp3bDoj6LxgOHPURPwXtM/Bclk+0zA8WjATivv3Z5PSdrS5mbFUThw+nsma4awJMcBDeTQtbTnBZZFqjhydDn5nEuut0Iuq4jyj7JSKjFnGReyf1TVgDn7hGVqTumVMsIKJcHFyx+51WLDfvQu/by2Dtg4GrmyuuBOXLRlL9EAgHfVDmJPGeKwonnk9G2S0eZJzI3DTJT5BnPbxdw+g+kKFKRZCloHWTqxTbKDX1NZpn8F7rlW92gohH1lAsA6BqWGb+HqjV6jqU27F5ovM4x22PBcUyKMg89oLoosr9qI2EPbB4rvAXypUuUwfavQoIGLibZuTE/bjlV8KjYPTMn6toJteH/71Z2pzP3+A0NdLB8wSnluaM52R+z8dX28WLB+ffciP/ctr442yrglLXgaNXcw8t2qrCBQY7tQkNw5BmdxtaiwliBYQk8BAomxs/3uYUlKXA8Tlz722A/j8XjWc0tgrtaG8TRfcbYWEtLQiH+rcAB0N1DcqB3uFWmTuzaXdMkz0pxNm9HHAZ/HuPrV7wsOmi5UCe3k1H1zHwfRUZhK8MI31oT388J4NBpB6pz3kcyKaVrAXNfM+YdHopkTNBLn1XF15E2+Ik2/kMrI6i3O10vj/I8H7MT/HMPmrCbGDx/m17eDTcMdhNhQ9LQ7MwuHrsK5NB2FsfkMU4ybHH0fu1lPtbK8yXIIUqvo6gOLGcgj58cJX+G1eiLfMZz3vyeSdoe95UYkbd7tvEwmk+fYNmI1aFCcxcEU9ga96nUaZjyP7o2SeFv97M9qA8qA56ACnvXCx9AZZr2VtbmZxnEyl4jHJROljiTZWOZZHLpfnESn0SieC2Njp4b3rOcfng5w9Wz+H+wqAvCvQvha3T3Frol/zVH+A/Bb34tJhPGvkRtllAkXE2K7x/wQXOd3AcTTn8D3JZksLAP+P8EaO7i+gfvFGEsSiFgTtImybnVrP2wUjf10OHAV8D1oOA7nlIkDQBtXl/wkehWn4i6EbNYmZtIarPeFWH4zkYnKcpGS/pS769adTP//0q9eZ3VBLb9kRcnXJ/T3ZlNRvsKwkC5R7n0rcSfJVuZ3N7/TBt+tES9skdbNecZ4TUalheNYub0t5By0Az/P9oO/YHgeb827jSXpXtDHRO02J6/93GyDdtYqxRdfOO/v23H5nSrtMzuJTtqC7/4DVvHLxg==" />
+
+## Setting up the scene (optional)
+
+We import all the modules that we need, for comfort we can use the orbit-controls from cientos,
+[look here to see how](/examples/orbit-controls).
+
+Now, let's put our camera in the `[11,11,11]` position.
+
+Lastly just to help us with the location, let's add a simple plane, rotated in the X axis, with `[10, 10]` units.
+
+```vue
+<script setup lang="ts">
+import { TresCanvas } from '@tresjs/core'
+import { OrbitControls } from '@tresjs/cientos'
+</script>
+
+<template>
+  <TresCanvas
+    clear-color="#111"
+    window-size
+  >
+    <OrbitControls />
+    <TresPerspectiveCamera :position="[11, 11, 11]" />
+
+    <TresMesh :rotation="[-Math.PI / 2, 0, 0]">
+      <TresPlaneGeometry :args="[10, 10]" />
+      <TresMeshBasicMaterial color="#444" />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+
+## ShaderMaterial
+
+As you know every instance in [ThreeJs](https://threejs.org/) is available in **TresJs**, so is the `ShaderMaterial`, we just need to add the `Tres` prefix to use it.
+
+For our blob, we could use a simple `SphereGeometry` adding some widthSegments and heightSegments to create a smooth effect, and put our blob 4 units in the Y positive axis
+
+```vue
+<TresMesh :position="[0, 4, 0]">
+  <TresSphereGeometry :args="[2, 32, 32]" />
+  <TresShaderMaterial />
+</TresMesh>
+```
+
+The `ShaderMaterial` accepts special properties, like `uniforms` `vertexShader` and `fragmentShader`, so we can create it in our script section and make the bind with our instance.
+
+For this example, our uniforms look like this:
+
+```ts
+import { Vector2 } from 'three'
+
+//...
+const uniforms = {
+  uTime: { value: 0 },
+  uAmplitude: { value: new Vector2(0.1, 0.1) },
+  uFrequency: { value: new Vector2(20, 5) },
+}
+//..
+```
+
+Our fragment shader looks like this:
+
+```ts
+//...
+const fragmentShader = `
+precision mediump float;
+varying vec2 vUv;
+
+void main() {
+    gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
+}
+`
+//..
+```
+
+And lastly our vertexShader:
+
+```ts
+const vertexShader = `
+uniform vec2 uAmplitude;
+uniform vec2 uFrequency;
+uniform float uTime;
+
+varying vec2 vUv;
+
+void main() {
+    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
+    modelPosition.y += sin(modelPosition.x * uFrequency.x - uTime) * uAmplitude.x;
+    modelPosition.x += cos(modelPosition.y * uFrequency.y - uTime) * uAmplitude.y;
+
+    vec4 viewPosition = viewMatrix * modelPosition;
+    gl_Position = projectionMatrix * viewPosition;
+    vUv = uv;
+}
+`
+//..
+```
+
+## Animating the blob
+
+Similar to what we learn in the [Basic animations](/examples/basic-animations) example, we start by referencing our blob, using [Template Ref](https://vuejs.org/guide/essentials/template-refs.html)
+
+```vue
+<script setup lang="ts">
+import { shallowRef } from 'vue'
+import { TresCanvas } from '@tresjs/core'
+import { OrbitControls } from '@tresjs/cientos'
+
+const blobRef = shallowRef(null)
+//...
+</script>
+
+<template>
+  <TresCanvas
+    clear-color="#111"
+    window-size
+  >
+    <OrbitControls />
+    <TresPerspectiveCamera :position="[11, 11, 11]" />
+    <TresMesh
+      ref="blobRef"
+      :position="[0, 4, 0]"
+    >
+      <TresSphereGeometry :args="[2, 32, 32]" />
+      <TresShaderMaterial />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+ Once we have got that, we could use the `onLoop` callback to animate our `uTime`.
+
+ ```ts
+import { TresCanvas, useRenderLoop } from '@tresjs/core'
+ 
+ //...
+ const { onLoop } = useRenderLoop()
+ 
+onLoop(({ elapsed }) => {
+   if (blobRef.value) {
+     blobRef.value.material.uniforms.uTime.value = elapsed
+   }
+})
+ //...
+```
+
+And that it is, we have our basic shader running smoothly.
+
+## Using GLSL vite-pluging (optional)
+
+_This step is completly optional and is out of the scope of the **TresJs** team_
+
+Defining our shader inline is not always the best idea, but if you're using [vite](https://vitejs.dev/) you can put your `GLSL` files in a different file just by using the [vite-plugin-glsl](https://www.npmjs.com/package/vite-plugin-glsl) (check out the link for the official documentation).
+
+And you could have a structure similar to this:
+
+```
+├── src/
+│   ├── myTresJsComponent.vue
+│   ├── shaders/
+│       ├── vertexShader.glsl
+│       ├── fragmentShader.glsl
+```

+ 1 - 1
docs/guide/index.md

@@ -81,7 +81,7 @@ We have a brand new [StackBlitz](https://stackblitz.com/) starter to try TresJS
 
 We also have a playground where you can try TresJS online. Check it out [here](https://playground.tresjs.org/).
 
-![](/public/playground.png)
+![](/playground.png)
 
 ## Motivation
 

+ 1 - 1
docs/package.json

@@ -9,7 +9,7 @@
     "preview": "vitepress preview"
   },
   "dependencies": {
-    "@tresjs/core": "workspace:3.6.0"
+    "@tresjs/core": "workspace:*"
   },
   "devDependencies": {
     "unocss": "^0.58.0",

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "@tresjs/core",
   "type": "module",
-  "version": "3.6.0",
+  "version": "3.6.1",
   "packageManager": "pnpm@8.10.2",
   "description": "Declarative ThreeJS using Vue Components",
   "author": "Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)",

+ 1 - 1
pnpm-lock.yaml

@@ -130,7 +130,7 @@ importers:
   docs:
     dependencies:
       '@tresjs/core':
-        specifier: workspace:3.6.0
+        specifier: workspace:*
         version: link:..
     devDependencies:
       unocss:

+ 2 - 0
src/components/TresCanvas.vue

@@ -21,6 +21,7 @@ import {
   h, 
   getCurrentInstance,
 } from 'vue'
+import pkg from '../../package.json'
 import {
   useTresContextProvider,
   useLogger,
@@ -192,6 +193,7 @@ onMounted(() => {
     ref="canvas"
     :data-scene="scene.uuid"
     :class="$attrs.class"
+    :data-tres="`tresjs ${pkg.version}`"
     :style="{
       display: 'block',
       width: '100%',

+ 27 - 17
src/composables/useTresContextProvider/index.ts

@@ -1,5 +1,5 @@
-import { toValue, useElementSize, useFps, useMemory, useRafFn, useWindowSize } from '@vueuse/core'
-import { inject, provide, readonly, shallowRef, computed, ref, onUnmounted } from 'vue'
+import { toValue, useElementSize, useFps, useMemory, useRafFn, useWindowSize, refDebounced } from '@vueuse/core'
+import { inject, provide, readonly, shallowRef, computed, ref, onUnmounted, watchEffect } from 'vue'
 import type { Camera, EventDispatcher, Scene, WebGLRenderer } from 'three'
 import { Raycaster } from 'three'
 import type { ComputedRef, DeepReadonly, MaybeRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue'
@@ -55,14 +55,23 @@ export function useTresContextProvider({
       : useElementSize(toValue(canvas).parentElement),
   )
 
-  const width = computed(() => elementSize.value.width.value)
-  const height = computed(() => elementSize.value.height.value)
+  const reactiveSize = shallowRef({
+    width: 0,
+    height: 0,
+  })
+  const debouncedReactiveSize = refDebounced(reactiveSize, 10)
+  const unWatchSize = watchEffect(() => {
+    reactiveSize.value = {
+      width: elementSize.value.width.value,
+      height: elementSize.value.height.value,
+    }
+  })
 
-  const aspectRatio = computed(() => width.value / height.value)
+  const aspectRatio = computed(() => debouncedReactiveSize.value.width / debouncedReactiveSize.value.height)
 
   const sizes = {
-    height,
-    width,
+    height: computed(() => debouncedReactiveSize.value.height),
+    width: computed(() => debouncedReactiveSize.value.width),
     aspectRatio,
   }
   const localScene = shallowRef<Scene>(scene)
@@ -113,7 +122,7 @@ export function useTresContextProvider({
 
   // Performance
   const updateInterval = 100 // Update interval in milliseconds
-  const fps = useFps({ every: updateInterval }) 
+  const fps = useFps({ every: updateInterval })
   const { isSupported, memory } = useMemory({ interval: updateInterval })
   const maxFrames = 160
   let lastUpdateTime = performance.now()
@@ -125,7 +134,7 @@ export function useTresContextProvider({
     if (toProvide.scene.value) {
       toProvide.perf.memory.allocatedMem = calculateMemoryUsage(toProvide.scene.value as unknown as TresObject)
     }
-    
+
     // Update memory usage
     if (timestamp - lastUpdateTime >= updateInterval) {
       lastUpdateTime = timestamp
@@ -147,9 +156,9 @@ export function useTresContextProvider({
           toProvide.perf.memory.accumulator.shift()
         }
 
-        toProvide.perf.memory.currentMem 
+        toProvide.perf.memory.currentMem
         = toProvide.perf.memory.accumulator.reduce((a, b) => a + b, 0) / toProvide.perf.memory.accumulator.length
-        
+
       }
     }
   }
@@ -157,25 +166,26 @@ export function useTresContextProvider({
   // Devtools
   let accumulatedTime = 0
   const interval = 1 // Interval in milliseconds, e.g., 1000 ms = 1 second
-    
+
   const { pause, resume } = useRafFn(({ delta }) => {
     if (!window.__TRES__DEVTOOLS__) return
 
     updatePerformanceData({ timestamp: performance.now() })
-    
+
     // Accumulate the delta time
     accumulatedTime += delta
-    
+
     // Check if the accumulated time is greater than or equal to the interval
     if (accumulatedTime >= interval) {
       window.__TRES__DEVTOOLS__.cb(toProvide)
-    
+
       // Reset the accumulated time
       accumulatedTime = 0
     }
-  }, { immediate: true }) 
-  
+  }, { immediate: true })
+
   onUnmounted(() => {
+    unWatchSize()
     pause()
   })