diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a40c8fda..d8757b66 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,9 +16,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup Pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 + uses: pnpm/action-setup@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: diff --git a/playground/components.d.ts b/playground/components.d.ts index 09766ef1..f707e945 100644 --- a/playground/components.d.ts +++ b/playground/components.d.ts @@ -10,6 +10,7 @@ declare module 'vue' { AkuAku: typeof import('./src/components/AkuAku.vue')['default'] FboCube: typeof import('./src/components/FboCube.vue')['default'] Gltf: typeof import('./src/components/gltf/index.vue')['default'] + GraphPane: typeof import('./src/components/GraphPane.vue')['default'] ModelsDemo: typeof import('./src/components/ModelsDemo.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] diff --git a/playground/src/components/GraphPane.vue b/playground/src/components/GraphPane.vue new file mode 100644 index 00000000..e952173e --- /dev/null +++ b/playground/src/components/GraphPane.vue @@ -0,0 +1,101 @@ + + + + + Rendering Activity + + + + + + + + diff --git a/playground/src/composables/state.ts b/playground/src/composables/state.ts new file mode 100644 index 00000000..227164b7 --- /dev/null +++ b/playground/src/composables/state.ts @@ -0,0 +1,11 @@ +import { reactive, toRefs } from 'vue' + +const state = reactive({ + renderingTimes: 0, +}) +export function useState() { + return { + ...toRefs(state), + + } +} diff --git a/playground/src/pages/abstractions/AnimatedSprite.vue b/playground/src/pages/abstractions/AnimatedSpriteDemo.vue similarity index 97% rename from playground/src/pages/abstractions/AnimatedSprite.vue rename to playground/src/pages/abstractions/AnimatedSpriteDemo.vue index 5b92a500..1fe23c4a 100644 --- a/playground/src/pages/abstractions/AnimatedSprite.vue +++ b/playground/src/pages/abstractions/AnimatedSpriteDemo.vue @@ -7,6 +7,7 @@ import { TresLeches, useControls } from '@tresjs/leches' import '@tresjs/leches/styles' import { degToRad } from 'three/src/math/MathUtils.js' import type { Atlasish } from '../../../../src/core/abstractions/AnimatedSprite/Atlas' +import { useState } from '../../composables/state' const ASSETS_URL = 'https://raw.githubusercontent.com/andretchen0/tresjs_assets/' + '462ad0f669f78d2c5ed7007b5134b419f646efad/textures/animated-sprite/' @@ -119,16 +120,23 @@ const centerDemoImgData = (() => { canvas.parentElement?.removeChild(canvas) return imgData })() + +const { renderingTimes } = useState() + +function onRender() { + renderingTimes.value = 1 +} + @frame: {{ lastFrame }} @end: {{ lastEnd }} @loop: {{ lastLoop }} - + diff --git a/playground/src/pages/abstractions/FBODemo.vue b/playground/src/pages/abstractions/FBODemo.vue deleted file mode 100644 index f631b3fe..00000000 --- a/playground/src/pages/abstractions/FBODemo.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/playground/src/pages/abstractions/PositionalAudio.vue b/playground/src/pages/abstractions/PositionalAudioDemo.vue similarity index 92% rename from playground/src/pages/abstractions/PositionalAudio.vue rename to playground/src/pages/abstractions/PositionalAudioDemo.vue index bb4cab7b..1423acbd 100644 --- a/playground/src/pages/abstractions/PositionalAudio.vue +++ b/playground/src/pages/abstractions/PositionalAudioDemo.vue @@ -1,6 +1,7 @@ @@ -65,8 +72,8 @@ const onContinue = () => { - - + + diff --git a/playground/src/pages/abstractions/Sampler.vue b/playground/src/pages/abstractions/Sampler.vue index 907bd53b..c0412f09 100644 --- a/playground/src/pages/abstractions/Sampler.vue +++ b/playground/src/pages/abstractions/Sampler.vue @@ -30,7 +30,7 @@ const { samples } = useControls({ - + diff --git a/playground/src/pages/abstractions/fbo/FBODemo.vue b/playground/src/pages/abstractions/fbo/FBODemo.vue new file mode 100644 index 00000000..a4537c2a --- /dev/null +++ b/playground/src/pages/abstractions/fbo/FBODemo.vue @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/playground/src/pages/abstractions/fbo/index.vue b/playground/src/pages/abstractions/fbo/index.vue new file mode 100644 index 00000000..39df979a --- /dev/null +++ b/playground/src/pages/abstractions/fbo/index.vue @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/playground/src/pages/abstractions/useFBODemo.vue b/playground/src/pages/abstractions/fbo/useFBODemo.vue similarity index 100% rename from playground/src/pages/abstractions/useFBODemo.vue rename to playground/src/pages/abstractions/fbo/useFBODemo.vue diff --git a/playground/src/pages/abstractions/lensflare/LensflareDemo.vue b/playground/src/pages/abstractions/lensflare/LensflareDemo.vue new file mode 100644 index 00000000..b19fffde --- /dev/null +++ b/playground/src/pages/abstractions/lensflare/LensflareDemo.vue @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/playground/src/pages/abstractions/lensflare/index.vue b/playground/src/pages/abstractions/lensflare/index.vue new file mode 100644 index 00000000..3dfba338 --- /dev/null +++ b/playground/src/pages/abstractions/lensflare/index.vue @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/playground/src/pages/controls/KeyboardControls.vue b/playground/src/pages/controls/KeyboardControlsDemo.vue similarity index 95% rename from playground/src/pages/controls/KeyboardControls.vue rename to playground/src/pages/controls/KeyboardControlsDemo.vue index 5d4fbfa1..3928fbdb 100644 --- a/playground/src/pages/controls/KeyboardControls.vue +++ b/playground/src/pages/controls/KeyboardControlsDemo.vue @@ -22,7 +22,7 @@ const hasChange = (state: any) => { - + diff --git a/playground/src/pages/controls/OrbitControlsDemo.vue b/playground/src/pages/controls/OrbitControlsDemo.vue index 3e3d4216..2011a811 100644 --- a/playground/src/pages/controls/OrbitControlsDemo.vue +++ b/playground/src/pages/controls/OrbitControlsDemo.vue @@ -6,6 +6,7 @@ import { OrbitControls } from '@tresjs/cientos' import { reactive } from 'vue' import { TresLeches, useControls } from '@tresjs/leches' import '@tresjs/leches/styles' +import { useState } from '../../composables/state' const gl = { clearColor: '#82DBC5', @@ -174,11 +175,18 @@ function onStart() { function onEnd() { /* console.log('end') */ } + +const { renderingTimes } = useState() + +function onRender() { + renderingTimes.value = 1 +} - + + diff --git a/playground/src/pages/misc/BakeShadows.vue b/playground/src/pages/misc/BakeShadowsDemo.vue similarity index 100% rename from playground/src/pages/misc/BakeShadows.vue rename to playground/src/pages/misc/BakeShadowsDemo.vue diff --git a/playground/src/pages/staging/FitDemo.vue b/playground/src/pages/staging/FitDemo.vue deleted file mode 100644 index b63d6752..00000000 --- a/playground/src/pages/staging/FitDemo.vue +++ /dev/null @@ -1,217 +0,0 @@ - - - - - :into value - - - - { choice = c; }" - /> - {{ `${c.label} - ${JSON.stringify(c.value)?.substring(0, 25)}` }} - - - {{ c.label }} - - - - N.B.: fit.update() is called continuously in the update loop. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/playground/src/pages/staging/fit/FitDemo.vue b/playground/src/pages/staging/fit/FitDemo.vue new file mode 100644 index 00000000..2b5d92be --- /dev/null +++ b/playground/src/pages/staging/fit/FitDemo.vue @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/playground/src/pages/staging/fit/index.vue b/playground/src/pages/staging/fit/index.vue new file mode 100644 index 00000000..2114a513 --- /dev/null +++ b/playground/src/pages/staging/fit/index.vue @@ -0,0 +1,87 @@ + + + + + :into value + + + + { choice = c; }" + /> + {{ `${c.label} - ${JSON.stringify(c.value)?.substring(0, 25)}` }} + + + {{ c.label }} + + + + N.B.: fit.update() is called continuously in the update loop. + + + + + + + + diff --git a/playground/src/router/routes/abstractions.ts b/playground/src/router/routes/abstractions.ts index 1dc766c1..1c10a6f8 100644 --- a/playground/src/router/routes/abstractions.ts +++ b/playground/src/router/routes/abstractions.ts @@ -17,7 +17,7 @@ export const abstractionsRoutes = [ { path: '/abstractions/lensflare', name: 'Lensflare', - component: () => import('../../pages/abstractions/LensflareDemo.vue'), + component: () => import('../../pages/abstractions/lensflare/index.vue'), }, { path: '/abstractions/reflector-mesh', @@ -32,12 +32,12 @@ export const abstractionsRoutes = [ { path: '/abstractions/fbo', name: 'Fbo', - component: () => import('../../pages/abstractions/FBODemo.vue'), + component: () => import('../../pages/abstractions/fbo/index.vue'), }, { path: '/abstractions/use-fbo', name: 'useFbo', - component: () => import('../../pages/abstractions/useFBODemo.vue'), + component: () => import('../../pages/abstractions/fbo/useFBODemo.vue'), }, { path: '/abstractions/use-surface-sampler', @@ -52,11 +52,11 @@ export const abstractionsRoutes = [ { path: '/abstractions/positional-audio', name: 'PositionalAudio', - component: () => import('../../pages/abstractions/PositionalAudio.vue'), + component: () => import('../../pages/abstractions/PositionalAudioDemo.vue'), }, { path: '/abstractions/animated-sprite', name: 'AnimatedSprite', - component: () => import('../../pages/abstractions/AnimatedSprite.vue'), + component: () => import('../../pages/abstractions/AnimatedSpriteDemo.vue'), }, ] diff --git a/playground/src/router/routes/controls.ts b/playground/src/router/routes/controls.ts index 3d8eea05..931aa55f 100644 --- a/playground/src/router/routes/controls.ts +++ b/playground/src/router/routes/controls.ts @@ -22,12 +22,12 @@ export const controlsRoutes = [ { path: '/controls/keyboard-controls', name: 'KeyboardControls', - component: () => import('../../pages/controls/KeyboardControls.vue'), + component: () => import('../../pages/controls/KeyboardControlsDemo.vue'), }, { path: '/controls/pointerlock-controls', name: 'PointerLockControls', - component: () => import('../../pages/controls/PointerLockControls.vue'), + component: () => import('../../pages/controls/PointerLockControlsDemo.vue'), }, { path: '/controls/scroll-controls', diff --git a/playground/src/router/routes/materials.ts b/playground/src/router/routes/materials.ts index 8daf59e3..976a558a 100644 --- a/playground/src/router/routes/materials.ts +++ b/playground/src/router/routes/materials.ts @@ -2,7 +2,7 @@ export const materialsRoutes = [ { path: '/materials/wobble-material', name: 'WobbleMaterial', - component: () => import('../../pages/materials/WobbleMaterial.vue'), + component: () => import('../../pages/materials/WobbleMaterialDemo.vue'), }, { path: '/materials/glass-material', diff --git a/playground/src/router/routes/misc.ts b/playground/src/router/routes/misc.ts index d2f98785..ee134671 100644 --- a/playground/src/router/routes/misc.ts +++ b/playground/src/router/routes/misc.ts @@ -22,7 +22,7 @@ export const miscRoutes = [ { path: '/misc/bake-shadows', name: 'BakeShadows', - component: () => import('../../pages/misc/BakeShadows.vue'), + component: () => import('../../pages/misc/BakeShadowsDemo.vue'), }, { path: '/misc/gltfExporter', diff --git a/playground/src/router/routes/staging.ts b/playground/src/router/routes/staging.ts index 895e678c..e6141523 100644 --- a/playground/src/router/routes/staging.ts +++ b/playground/src/router/routes/staging.ts @@ -47,6 +47,6 @@ export const stagingRoutes = [ { path: '/staging/fit', name: 'Fit', - component: () => import('../../pages/staging/FitDemo.vue'), + component: () => import('../../pages/staging/fit/index.vue'), }, ] diff --git a/src/composables/useOnDemandInvalidation.ts b/src/composables/useOnDemandInvalidation.ts new file mode 100644 index 00000000..9b0b0d04 --- /dev/null +++ b/src/composables/useOnDemandInvalidation.ts @@ -0,0 +1,20 @@ +import { watch } from 'vue' +import { useTresContext } from '@tresjs/core' // Replace with the actual import path + +export function useOnDemandInvalidation(props: Record) { + const { render, invalidate } = useTresContext() + + function invalidateOnDemand() { + if (render.mode.value === 'on-demand') { + invalidate() + } + } + + watch(props, () => { + invalidateOnDemand() + }) + + return { + invalidateOnDemand, + } +} diff --git a/src/core/abstractions/AnimatedSprite/component.vue b/src/core/abstractions/AnimatedSprite/component.vue index 3e045ded..a25ebaf3 100644 --- a/src/core/abstractions/AnimatedSprite/component.vue +++ b/src/core/abstractions/AnimatedSprite/component.vue @@ -4,6 +4,7 @@ import type { TresVector2 } from '@tresjs/core' import { normalizeVectorFlexibleParam, useLoop } from '@tresjs/core' import type { Intersection } from 'three' import { DoubleSide } from 'three' +import { useOnDemandInvalidation } from '../../../composables/useOnDemandInvalidation' import type { Atlasish } from './Atlas' import { getAtlasFrames, getNullAtlasFrame, getTextureAndAtlasAsync, setAtlasDefinitions } from './Atlas' @@ -77,6 +78,8 @@ const emit = defineEmits<{ (e: 'click', event: Intersection): void }>() +useOnDemandInvalidation(props) + const positionX = ref(0) const positionY = ref(0) const scaleX = ref(0) diff --git a/src/core/abstractions/Levioso.vue b/src/core/abstractions/Levioso.vue index a1d3f9e1..a3ef5944 100644 --- a/src/core/abstractions/Levioso.vue +++ b/src/core/abstractions/Levioso.vue @@ -2,6 +2,7 @@ import { useLoop } from '@tresjs/core' import { MathUtils } from 'three' import { shallowRef } from 'vue' +import { useOnDemandInvalidation } from '../../composables/useOnDemandInvalidation' const props = withDefaults( defineProps<{ @@ -18,6 +19,8 @@ const props = withDefaults( }, ) +const { invalidateOnDemand } = useOnDemandInvalidation(props) + const groupRef = shallowRef() defineExpose({ @@ -45,6 +48,8 @@ defineExpose({ group.rotation.y = Math.sin(theta) * AMPLITUDE_ROTATION_Y * props.rotationFactor group.rotation.z = Math.sin(theta) * AMPLITUDE_ROTATION_Z * props.rotationFactor group.position.y = MathUtils.mapLinear(Math.sin(theta), -1, 1, props.range[0], props.range[1]) * props.floatFactor + + invalidateOnDemand() }) } diff --git a/src/core/abstractions/MouseParallax.vue b/src/core/abstractions/MouseParallax.vue index 953b0e1c..3bb4dbb4 100644 --- a/src/core/abstractions/MouseParallax.vue +++ b/src/core/abstractions/MouseParallax.vue @@ -4,6 +4,7 @@ import type { Group } from 'three' import { useLoop, useTresContext } from '@tresjs/core' import { useElementSize, useMouse, useWindowSize } from '@vueuse/core' import type { UseMouseOptions } from '@vueuse/core' +import { useOnDemandInvalidation } from '../../composables/useOnDemandInvalidation' export interface MouseParallaxProps { /** @@ -47,6 +48,8 @@ const props = withDefaults(defineProps(), { local: false, }) +const { invalidateOnDemand } = useOnDemandInvalidation(props) + const { camera, renderer } = useTresContext() const { disabled, factor, ease, local } = toRefs(props) @@ -83,6 +86,8 @@ onBeforeRender(({ delta }) => { += (cursorX.value - cameraGroupRef.value.position.x) * ease.value * delta cameraGroupRef.value.position.y += (cursorY.value - cameraGroupRef.value.position.y) * ease.value * delta + + invalidateOnDemand() }) watch( diff --git a/src/core/abstractions/Reflector.vue b/src/core/abstractions/Reflector.vue index f8ec8408..71a29012 100644 --- a/src/core/abstractions/Reflector.vue +++ b/src/core/abstractions/Reflector.vue @@ -2,7 +2,8 @@ import { shallowRef, toRefs } from 'vue' import { useTresContext } from '@tresjs/core' import type { TresColor } from '@tresjs/core' -import { Reflector } from 'three/examples/jsm/objects/Reflector.js' +import { Reflector } from 'three-stdlib' +import { useOnDemandInvalidation } from '../../composables/useOnDemandInvalidation' export interface ReflectorProps { /** @@ -79,6 +80,8 @@ extend({ Reflector }) const { color, textureWidth, textureHeight, clipBias, multisample, shader } = toRefs(props) +useOnDemandInvalidation(props) + defineExpose({ instance: reflectorRef, }) diff --git a/src/core/abstractions/Text3D.vue b/src/core/abstractions/Text3D.vue index b77fc4dd..71a1ff97 100644 --- a/src/core/abstractions/Text3D.vue +++ b/src/core/abstractions/Text3D.vue @@ -3,6 +3,7 @@ import { computed, shallowRef, toRefs, toValue, useSlots, watchEffect } from 'vu import type { TextGeometryParameters } from 'three-stdlib' import { FontLoader, TextGeometry } from 'three-stdlib' import { useTresContext } from '@tresjs/core' +import { useOnDemandInvalidation } from '../../composables/useOnDemandInvalidation' export interface Glyph { _cachedOutline: string[] @@ -151,6 +152,8 @@ const { bevelSegments, } = toRefs(props) +useOnDemandInvalidation(props) + const { extend } = useTresContext() extend({ TextGeometry }) diff --git a/src/core/abstractions/useFBO/index.ts b/src/core/abstractions/useFBO/index.ts index 06f11fd7..484b463f 100644 --- a/src/core/abstractions/useFBO/index.ts +++ b/src/core/abstractions/useFBO/index.ts @@ -1,8 +1,9 @@ import { useLoop, useTresContext } from '@tresjs/core' -import type { Camera, WebGLRenderTargetOptions } from 'three' +import type { Camera, RenderTargetOptions } from 'three' import { DepthTexture, FloatType, HalfFloatType, LinearFilter, WebGLRenderTarget } from 'three' import type { Ref } from 'vue' -import { isReactive, onBeforeUnmount, reactive, ref, toRefs, watchEffect } from 'vue' +import { isReactive, onBeforeUnmount, reactive, ref, toRefs, watch } from 'vue' +import { useOnDemandInvalidation } from '../../../composables/useOnDemandInvalidation' export interface FboOptions { /* @@ -35,21 +36,22 @@ export interface FboOptions { * See https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget for more information. * * @default {} - * @type {WebGLRenderTargetOptions} + * @type {RenderTargetOptions} * @memberof FboProps */ - settings?: WebGLRenderTargetOptions + settings?: RenderTargetOptions } export function useFBO(options: FboOptions) { const target: Ref = ref(null) const { height, width, settings, depth } = isReactive(options) ? toRefs(options) : toRefs(reactive(options)) + const { invalidateOnDemand } = useOnDemandInvalidation(options) const { onBeforeRender } = useLoop() const { camera, renderer, scene, sizes } = useTresContext() - watchEffect(() => { + watch(() => [width?.value, sizes.width.value, height?.value, sizes.height.value], () => { target.value?.dispose() target.value = new WebGLRenderTarget(width?.value || sizes.width.value, height?.value || sizes.height.value, { @@ -66,7 +68,9 @@ export function useFBO(options: FboOptions) { FloatType, ) } - }) + + invalidateOnDemand() + }, { immediate: true }) onBeforeRender(() => { renderer.value.setRenderTarget(target.value) diff --git a/src/core/abstractions/useSurfaceSampler/component.vue b/src/core/abstractions/useSurfaceSampler/component.vue index 8c3dca7f..1338527c 100644 --- a/src/core/abstractions/useSurfaceSampler/component.vue +++ b/src/core/abstractions/useSurfaceSampler/component.vue @@ -1,6 +1,7 @@ diff --git a/src/core/controls/MapControls.vue b/src/core/controls/MapControls.vue index 96ff16c0..01bd6cde 100644 --- a/src/core/controls/MapControls.vue +++ b/src/core/controls/MapControls.vue @@ -1,8 +1,11 @@ diff --git a/src/core/materials/meshReflectionMaterial/index.vue b/src/core/materials/meshReflectionMaterial/index.vue index 904e6f0b..3228c774 100644 --- a/src/core/materials/meshReflectionMaterial/index.vue +++ b/src/core/materials/meshReflectionMaterial/index.vue @@ -30,6 +30,7 @@ import { WebGLRenderTarget, } from 'three' import type { TresColor } from '@tresjs/core' +import { useOnDemandInvalidation } from '../../../composables/useOnDemandInvalidation' import { BlurPass } from './BlurPass' import { MeshReflectionMaterial } from './material' @@ -156,6 +157,8 @@ const props = withDefaults( }, ) +const { invalidateOnDemand } = useOnDemandInvalidation(props) + const blurWidth = computed(() => 500 - (Array.isArray(props.blurSize) ? props.blurSize[0] : props.blurSize)) const blurHeight = computed(() => 500 - (Array.isArray(props.blurSize) ? props.blurSize[1] : props.blurSize)) const hasBlur = computed(() => blurWidth.value > 0 || blurHeight.value > 0) @@ -285,6 +288,8 @@ function onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, _ renderer.shadowMap.autoUpdate = currentShadowAutoUpdate object.visible = true renderer.setRenderTarget(null) + + invalidateOnDemand() } watch( diff --git a/src/core/materials/meshWobbleMaterial/index.vue b/src/core/materials/meshWobbleMaterial/index.vue index cb4c6cb9..b1b425a3 100644 --- a/src/core/materials/meshWobbleMaterial/index.vue +++ b/src/core/materials/meshWobbleMaterial/index.vue @@ -1,6 +1,7 @@ diff --git a/src/core/staging/Precipitation.vue b/src/core/staging/Precipitation.vue index 69fcadee..1357e0d4 100644 --- a/src/core/staging/Precipitation.vue +++ b/src/core/staging/Precipitation.vue @@ -2,6 +2,7 @@ import { shallowRef, toRefs, watchEffect } from 'vue' import type { TresColor } from '@tresjs/core' import { useLoop } from '@tresjs/core' +import { useOnDemandInvalidation } from '../../composables/useOnDemandInvalidation' export interface PrecipitationProps { /** @@ -143,6 +144,8 @@ const { randomness, } = toRefs(props) +const { invalidateOnDemand } = useOnDemandInvalidation(props) + const geometryRef = shallowRef() let positionArray: [] | Float32Array = [] let velocityArray: [] | Float32Array = [] @@ -187,6 +190,8 @@ onBeforeRender(() => { if (positionArray[i * 3 + 1] <= -area.value[1] / 2 || positionArray[i * 3 + 1] >= area.value[1] / 2) { positionArray[i * 3 + 1] = positionArray[i * 3 + 1] * -1 } } geometryRef.value.attributes.position.needsUpdate = true + + invalidateOnDemand() } }) diff --git a/src/core/staging/Sky.vue b/src/core/staging/Sky.vue index 6e94a810..187b7b65 100644 --- a/src/core/staging/Sky.vue +++ b/src/core/staging/Sky.vue @@ -1,8 +1,9 @@ diff --git a/src/core/staging/Stars.vue b/src/core/staging/Stars.vue index 35e93c65..be7006e0 100644 --- a/src/core/staging/Stars.vue +++ b/src/core/staging/Stars.vue @@ -1,6 +1,7 @@ diff --git a/src/core/staging/useEnvironment/index.ts b/src/core/staging/useEnvironment/index.ts index ee249837..a2e4157a 100644 --- a/src/core/staging/useEnvironment/index.ts +++ b/src/core/staging/useEnvironment/index.ts @@ -12,6 +12,7 @@ import { import { RGBELoader } from 'three-stdlib' import type { Ref } from 'vue' import { computed, ref, toRefs, unref, watch } from 'vue' +import { useOnDemandInvalidation } from '../../../composables/useOnDemandInvalidation' import type { EnvironmentOptions } from './const' import { environmentPresets } from './const' @@ -45,6 +46,8 @@ export async function useEnvironment( background, } = toRefs(options) + const { invalidateOnDemand } = useOnDemandInvalidation(options) + const texture: Ref = ref() const isCubeMap = computed(() => Array.isArray((files as Ref).value)) const loader = computed(() => isCubeMap.value ? CubeTextureLoader : RGBELoader) @@ -122,6 +125,7 @@ export async function useEnvironment( texture.value = result.value texture.value.mapping = EquirectangularReflectionMapping } + invalidateOnDemand() } else if (value && !(value in environmentPresets)) { throw new Error(`Preset must be one of: ${Object.keys(environmentPresets).join(', ')}`)
@frame: {{ lastFrame }}
@end: {{ lastEnd }}
@loop: {{ lastLoop }}
:into
N.B.: fit.update() is called continuously in the update loop.
fit.update()