Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 591 move tresobject tres to a weakmap #593

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
224ab06
feat: 474 vue chrome devtools plugin (#479)
alvarosabu Dec 22, 2023
e760525
chore: release v4.0.0-next.0
alvarosabu Dec 22, 2023
c8e79bc
Merge branch 'main' into v4
alvarosabu Jan 2, 2024
5fad3b8
feat: update to three `v160` and vue `v3.4` (#488)
alvarosabu Jan 2, 2024
a63eb90
fix(types): added `Object3DEventMap` to `Object3D` generics for point…
alvarosabu Jan 2, 2024
83f0e06
Merge branch 'main' into v4
alvarosabu Jan 17, 2024
f688c64
feat: 140 on demand rendering (#497)
alvarosabu Jan 23, 2024
8bbafde
feat: remove default camera warning (#499)
alvarosabu Jan 23, 2024
c4547f9
feat: 492 set tone mapping default to acesfilmictonemapping (#498)
alvarosabu Jan 23, 2024
08717ef
feat: 516 localstate for custom renderer node instances instead of us…
alvarosabu Feb 1, 2024
898a8b1
Merge branch 'main' into v4
alvarosabu Feb 2, 2024
52dad5c
fix: camera aspect
andretchen0 Feb 5, 2024
79d8a76
feat: 503 conditional rendering of primitives (#514)
alvarosabu Feb 21, 2024
1fa9385
Merge branch 'main' into v4
alvarosabu Mar 4, 2024
1a705b1
Merge branch 'v4' into fix/camera-aspect
alvarosabu Mar 6, 2024
97dcd7b
Merge pull request #538 from Tresjs/fix/camera-aspect
andretchen0 Mar 6, 2024
ddc229e
fix: `nodeOps` is now a function (#579)
alvarosabu Mar 8, 2024
963e662
chore: next package json version
alvarosabu Mar 18, 2024
47713bc
chore: release v4.0.0-next.1
alvarosabu Mar 18, 2024
8efe6e0
Merge branch 'main' into v4
alvarosabu Mar 20, 2024
4d7cc05
feat: replacing `__tres` local state for a `WeakMap`
alvarosabu Mar 20, 2024
b023312
chore: fix lint
alvarosabu Mar 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@


## [3.7.0](https://github.com/Tresjs/tres/compare/3.6.1...3.7.0) (2024-01-29)
## [4.0.0-next.1](https://github.com/Tresjs/tres/compare/3.7.0...4.0.0-next.1) (2024-03-18)


### Features

* 140 on demand rendering ([#497](https://github.com/Tresjs/tres/issues/497)) ([f688c64](https://github.com/Tresjs/tres/commit/f688c6447be887c4675a57ecabb5182d8b7d02cf))
* 492 set tone mapping default to acesfilmictonemapping ([#498](https://github.com/Tresjs/tres/issues/498)) ([c4547f9](https://github.com/Tresjs/tres/commit/c4547f92615a43b7b56b34c0e1ee9f4b78a2230b))
* 503 conditional rendering of primitives ([#514](https://github.com/Tresjs/tres/issues/514)) ([79d8a76](https://github.com/Tresjs/tres/commit/79d8a762da6b6e23771a20314f7902eff4635acf))
* 516 localstate for custom renderer node instances instead of userdata ([#522](https://github.com/Tresjs/tres/issues/522)) ([08717ef](https://github.com/Tresjs/tres/commit/08717efd0f631c085340b1fea4eb6c154c63608b))
* remove default camera warning ([#499](https://github.com/Tresjs/tres/issues/499)) ([8bbafde](https://github.com/Tresjs/tres/commit/8bbafde48a33753f0b6560da36a4d128aaa83cc6))
* update to three `v160` and vue `v3.4` ([#488](https://github.com/Tresjs/tres/issues/488)) ([5fad3b8](https://github.com/Tresjs/tres/commit/5fad3b8095c09cfe758e2553da3df49b29b1ce1a))


### Bug Fixes

* `nodeOps` is now a function ([#579](https://github.com/Tresjs/tres/issues/579)) ([ddc229e](https://github.com/Tresjs/tres/commit/ddc229e6e492b9e7887add0fcc679a9ae4e47f5c))
* camera aspect ([52dad5c](https://github.com/Tresjs/tres/commit/52dad5c98271f80f4d454bbcce1bb5844960f943))
* **types:** added `Object3DEventMap` to `Object3D` generics for point event handling ([#491](https://github.com/Tresjs/tres/issues/491)) ([a63eb90](https://github.com/Tresjs/tres/commit/a63eb9099fcaf97b1c96abe5667ee71ca2fd611f))

## [4.0.0-next.0](https://github.com/Tresjs/tres/compare/3.7.0...4.0.0-next.1) (2023-12-22)


### Features

* 474 vue chrome devtools plugin ([#479](https://github.com/Tresjs/tres/issues/479)) ([224ab06](https://github.com/Tresjs/tres/commit/224ab06a4404e2ae5a0cbd2f43041961862b09fd))

## [3.7.0](https://github.com/Tresjs/tres/compare/3.6.1...3.7.0) (2024-01-29)

### Features

* 474 vue chrome devtools plugin ([#526](https://github.com/Tresjs/tres/issues/526)) ([0185bfa](https://github.com/Tresjs/tres/commit/0185bfa6f04faff5eabbc526616713ef7747ebeb))
* 524 feat add directives to core ([#525](https://github.com/Tresjs/tres/issues/525)) ([5268e9f](https://github.com/Tresjs/tres/commit/5268e9f13bf65c61d5ddfe7153b71b335449b81d))

Expand Down
18 changes: 18 additions & 0 deletions docs/.vitepress/theme/components/BlenderCube.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { useTresContext } from '@tresjs/core'
import { useGLTF } from '@tresjs/cientos'

const { nodes } = await useGLTF('https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/blender-cube.glb',
{ draco: true })
const model = nodes.Cube

model.position.set(0, 1, 0)

const state = useTresContext()

state.invalidate()
</script>

<template>
<primitive :object="model" />
</template>
101 changes: 101 additions & 0 deletions docs/.vitepress/theme/components/GraphPane.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { useRafFn } from '@vueuse/core'
import { useState } from '../composables/state'

const width = 160
const height = 40
const strokeWidth = 2
const updateInterval = 100 // Update interval in milliseconds
const topOffset = 0 // Offset from the top

const points = ref('')
const frameTimes = ref([])
const maxFrames = ref(width / strokeWidth)

let lastUpdateTime = performance.now()

const { renderingTimes } = useState()

useRafFn(({ timestamp }) => {
if (timestamp - lastUpdateTime >= updateInterval) {
lastUpdateTime = timestamp

frameTimes.value.push(renderingTimes?.value)
renderingTimes.value = 0

if (frameTimes.value.length > maxFrames.value) {
frameTimes.value.shift()
}

points.value = frameTimes.value
.map(
(value, index) =>
`${index * strokeWidth},${
height + topOffset - strokeWidth / 2 - (value * (height + topOffset - strokeWidth)) / 2
}`,
)
.join(' ')
}
})
</script>

<template>
<div
class="absolute
right-2
top-2
flex
px-4
py-1
justify-between
gap-4
items-center
mb-2
z-10
bg-white
dark:bg-dark
shadow-xl
rounded
border-4
border-solid
bg-primary
border-primary
pointer-events-none
overflow-hidden"
>
<label class="text-secondary text-xs w-1/3">Rendering Activity</label>

<div
class="
bg-gray-100
dark:bg-gray-600
relative
w-2/3
p-1
rounded
text-right
text-xs
focus:border-gray-200
outline-none
border-none
font-sans
"
>
<svg
:width="width"
:height="height"
xmlns="http://www.w3.org/2000/svg"
fill="none"
>
<polyline
:points="points"
stroke="lightgray"
:stroke-width="strokeWidth"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</div>
</div>
</template>
40 changes: 40 additions & 0 deletions docs/.vitepress/theme/components/OnDemandRendering.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { BasicShadowMap, SRGBColorSpace, NoToneMapping } from 'three'
import { OrbitControls } from '@tresjs/cientos'
import { useState } from '../composables/state'
import BlenderCube from './BlenderCube.vue'
import GraphPane from './GraphPane.vue'
import RenderingLogger from './RenderingLogger.vue'

const { renderingTimes } = useState()

function onRender() {
renderingTimes.value = 1

}
</script>

<template>
<GraphPane />
<TresCanvas
render-mode="on-demand"
clear-color="#82DBC5"
@render="onRender"
>
<TresPerspectiveCamera
:position="[5, 5, 5]"
:look-at="[0, 0, 0]"
/>
<Suspense>
<BlenderCube />
</Suspense>
<TresGridHelper />
<RenderingLogger />
<TresAmbientLight :intensity="1" />
<TresDirectionalLight
:position="[0, 8, 4]"
:intensity="0.7"
/>
</TresCanvas>
</template>
24 changes: 24 additions & 0 deletions docs/.vitepress/theme/components/RenderingLogger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import { useRenderLoop, useTresContext } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
import { onMounted } from 'vue'
import { useState } from '../composables/state'

const { renderingTimes } = useState()

const state = useTresContext()

function manualInvalidate() {
state.invalidate()
}

onMounted(() => {
manualInvalidate()
})
</script>

<template>
<OrbitControls
@change="manualInvalidate"
/>
</template>
11 changes: 11 additions & 0 deletions docs/.vitepress/theme/composables/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { reactive, toRefs } from 'vue'

const state = reactive({
renderingTimes: 0,
})
export function useState() {
return {
...toRefs(state),

}
}
131 changes: 131 additions & 0 deletions docs/advanced/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Scaling performance 🚀

> Quick guide with tips to improve performance of your Tres.js application.

We are running WebGL on the browser, which can be quite expensive and it will depend on how powerful the user's device is. To make 3D accessible to everyone, we need to make sure our applications are optimized to run also on low-end devices. This guide will provide some tips to improve the performance of your Tres.js application.

## On-demand rendering <Badge type="tip" text="^4.0.0" />

By default, Tres.js will render your scene on every frame. This is great for most applications, but if you are building a game or a complex application, you might want to control when the scene is rendered.

Otherwise it might drain your device battery 🔋 🔜 🪫 and make your computer sound like an airplane 🛫.

Ideally, you only want to **render the scene when necessary**, for example when the user interacts with the scene and the camera moves, or when objects in the scene are animated.

You can do that by setting the `renderMode` prop to `on-demand` or `manual`:


### Mode `on-demand`

<ClientOnly>
<div style="position: relative; aspect-ratio: 16/9; height: auto; margin: 2rem 0; border-radius: 8px; overflow:hidden;">
<onDemandRendering />
</div>
</ClientOnly>


```vue
<TresCanvas render-mode="on-demand">
<!-- Your scene goes here -->
</TresCanvas>
```

#### Automatic Invalidation

When using `render-mode="on-demand"`, Tres.js will automatically invalidate the current frame by observing component props and lifecycle hooks like `onMounted` and `onUnmounted`. It will also invalidate the frame when resizing the window or changing any prop from the `<TresCanvas>` component like `clearColor` or `antialias`.

The code below updates TresMesh's position-x prop every second, triggering a new render.

```vue
<script setup>
import { ref } from 'vue'

const positionX = ref(0)

setTimeout(() => {
positionX.value = 1
}, 1000)
</script>

<template>
<TresCanvas render-mode="on-demand">
<TresMesh :position-x="positionX">
<TresBoxGeometry />
<TresMeshBasicMaterial color="teal" />
</TresMesh>
</TresCanvas>
</template>
```

#### Manual Invalidation

Since it is not really possible to observe all the possible changes in your application, you can also manually invalidate the frame by calling the `invalidate()` method from the [`useTresContext` composable](../api/composables.md#usetrescontext):


::: code-group

```vue [App.vue]
<script setup>
import { TresCanvas } from '@tresjs/core'
import Scene from './Scene.vue'
</script>

<template>
<TresCanvas
render-mode="manual"
>
<Scene />
</TresCanvas>
</template>
```

```vue [Scene.vue]
<script setup>
import { useTres } from '@tresjs/core'

const boxRef = ref()
const { invalidate } = useTres()

watch(boxRef.value, () => {
boxRef.value.position.x = 1
invalidate()
})
</script>

<template>
<TresMesh ref="boxRef">
<TresBoxGeometry />
<TresMeshBasicMaterial color="teal" />
</TresMesh>
</template>
```

:::

### Mode `always`

In this rendering mode, Tres will continously render the scene on every frame. This is the default mode and the easiest to use, but it's also the most resource expensive one.


### Mode `manual`

If you want to have full control of when the scene is rendered, you can set the `render-mode` prop to `manual`:

```vue
<TresCanvas render-mode="manual">
<!-- Your scene goes here -->
</TresCanvas>
```

In this mode, Tres will not render the scene automatically. You will need to call the `advance()` method from the [`useTresContext` composable](../api/composables.md#usetrescontext) to render the scene:

```vue
<script setup>
import { useTres } from '@tresjs/core'

const { advance } = useTres()

advance()
</script>
```

15 changes: 9 additions & 6 deletions docs/api/composables.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,13 @@ const context = useTresContext()
| **controls** | The controls of your scene |
| **deregisterCamera** | A method to deregister a camera. This is only required if you manually create a camera. Cameras in the template are deregistered automatically. |
| **extend** | Extends the component catalogue. See [extending](/advanced/extending) |
| **raycaster** | The global raycaster used for pointer events |
| **registerCamera** | A method to register a camera. This is only required if you manually create a camera. Cameras in the template are registered automatically. |
| **renderer** | The [WebGLRenderer](https://threejs.org/docs/#api/en/renderers/WebGLRenderer) of your scene |
| **scene** | The [scene](https://threejs.org/docs/?q=sce#api/en/scenes/Scene). |
| **setCameraActive** | A method to set a camera active |
| **sizes** | Contains width, height and aspect ratio of your canvas |
| **raycaster** | the global raycaster used for pointer events |
| **registerCamera** | a method to register a camera. This is only required if you manually create a camera. Cameras in the template are registered automatically. |
| **renderer** | the [WebGLRenderer](https://threejs.org/docs/#api/en/renderers/WebGLRenderer) of your scene |
| **scene** | the [scene](https://threejs.org/docs/?q=sce#api/en/scenes/Scene). |
| **setCameraActive** | a method to set a camera active |
| **sizes** | contains width, height and aspect ratio of your canvas |
| **invalidate** | a method to invalidate the render loop. This is only required if you set the `render-mode` prop to `on-demand`. |
| **advance** | a method to advance the render loop. This is only required if you set the `render-mode` prop to `manual`. |


Loading
Loading