feat(stage-ui): achieve Warudo (https://warudo.app) style rendering for VRM models
This commit is contained in:
+4
-1
@@ -1,4 +1,4 @@
|
||||
version: '0.2'
|
||||
version: "0.2"
|
||||
ignorePaths: []
|
||||
dictionaryDefinitions: []
|
||||
dictionaries: []
|
||||
@@ -82,6 +82,7 @@ words:
|
||||
- DuckDBWASMQuery
|
||||
- eastasia
|
||||
- elevenlabs
|
||||
- Equirectangular
|
||||
- esaxx
|
||||
- Factorio
|
||||
- feaxios
|
||||
@@ -95,6 +96,7 @@ words:
|
||||
- gugi
|
||||
- guii
|
||||
- guiiai
|
||||
- Hdri
|
||||
- hfspaceup
|
||||
- hfsup
|
||||
- hfup
|
||||
@@ -198,6 +200,7 @@ words:
|
||||
- reka
|
||||
- Replayable
|
||||
- resampler
|
||||
- RGBE
|
||||
- rlib
|
||||
- rmcp
|
||||
- rolldown
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
"@ricky0123/vad-web": "^0.0.24",
|
||||
"@tresjs/cientos": "^4.3.1",
|
||||
"@tresjs/core": "^4.3.6",
|
||||
"@tresjs/post-processing": "^2.4.0",
|
||||
"@vueuse/core": "^13.6.0",
|
||||
"@vueuse/motion": "^3.0.3",
|
||||
"@vueuse/shared": "^13.6.0",
|
||||
@@ -97,6 +98,7 @@
|
||||
"pinia": "^3.0.3",
|
||||
"pixi-filters": "4",
|
||||
"pixi-live2d-display": "^0.4.0",
|
||||
"postprocessing": "^6.37.7",
|
||||
"rehype-stringify": "^10.0.1",
|
||||
"reka-ui": "^2.4.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
|
||||
@@ -242,7 +242,7 @@ function handleUrlLoad() {
|
||||
|
||||
<Callout :label="t('settings.vrm.scale-and-position.model-info-title')">
|
||||
<div>
|
||||
<div class="text-sm text-neutral-600 space-y-1">
|
||||
<div class="text-sm text-neutral-600 space-y-1 dark:text-neutral-400">
|
||||
<div class="flex justify-between">
|
||||
<span>{{ t('settings.vrm.scale-and-position.model-info-x') }}</span>
|
||||
<span>{{ modelSize.x.toFixed(4) }}</span>
|
||||
@@ -262,7 +262,7 @@ function handleUrlLoad() {
|
||||
theme="lime"
|
||||
label="Tips!"
|
||||
>
|
||||
<div class="text-sm text-neutral-600 space-y-1">
|
||||
<div class="text-sm text-neutral-600 space-y-1 dark:text-neutral-400">
|
||||
{{ t('settings.vrm.scale-and-position.tips') }}
|
||||
</div>
|
||||
</Callout>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useTresContext } from '@tresjs/core'
|
||||
import { until } from '@vueuse/core'
|
||||
import { onMounted, toRef } from 'vue'
|
||||
import { onMounted, shallowRef, toRef } from 'vue'
|
||||
|
||||
import * as THREE from 'three'
|
||||
|
||||
@@ -11,11 +11,29 @@ const props = defineProps<{
|
||||
|
||||
const { scene } = useTresContext()
|
||||
const directionalLightRef = toRef(() => props.directionalLight)
|
||||
const lightHelper = shallowRef<THREE.DirectionalLightHelper>()
|
||||
|
||||
onMounted(async () => {
|
||||
await until(directionalLightRef).toBeTruthy()
|
||||
scene.value.add(new THREE.DirectionalLightHelper(props.directionalLight!, 1))
|
||||
lightHelper.value = new THREE.DirectionalLightHelper(directionalLightRef.value!, 1)
|
||||
scene.value.add(lightHelper.value)
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
// Ensure cleanup on HMR
|
||||
import.meta.hot.dispose(() => {
|
||||
try {
|
||||
if (lightHelper.value) {
|
||||
lightHelper.value.dispose()
|
||||
scene.value.remove(lightHelper.value)
|
||||
lightHelper.value = undefined
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error during DirectionalLightHelper cleanup:', error)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { useTresContext } from '@tresjs/core'
|
||||
import { until } from '@vueuse/core'
|
||||
import { onMounted, shallowRef, toRef } from 'vue'
|
||||
|
||||
import * as THREE from 'three'
|
||||
|
||||
const props = defineProps<{
|
||||
hemisphereLight?: THREE.HemisphereLight | null
|
||||
}>()
|
||||
|
||||
const { scene } = useTresContext()
|
||||
const hemisphereLightRef = toRef(() => props.hemisphereLight)
|
||||
const lightHelper = shallowRef<THREE.HemisphereLightHelper>()
|
||||
|
||||
onMounted(async () => {
|
||||
await until(hemisphereLightRef).toBeTruthy()
|
||||
lightHelper.value = new THREE.HemisphereLightHelper(hemisphereLightRef.value!, 1)
|
||||
scene.value.add(lightHelper.value)
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
// Ensure cleanup on HMR
|
||||
import.meta.hot.dispose(() => {
|
||||
try {
|
||||
if (lightHelper.value) {
|
||||
lightHelper.value.dispose()
|
||||
scene.value.remove(lightHelper.value)
|
||||
lightHelper.value = undefined
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error during HemisphereLightHelper cleanup:', error)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
</template>
|
||||
+2495
File diff suppressed because one or more lines are too long
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { TresCanvas } from '@tresjs/core'
|
||||
import { EffectComposerPmndrs, HueSaturationPmndrs } from '@tresjs/post-processing'
|
||||
import { useElementBounding, useMouse } from '@vueuse/core'
|
||||
import { formatHex } from 'culori'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { BlendFunction } from 'postprocessing'
|
||||
import { ACESFilmicToneMapping, PerspectiveCamera, Plane, Raycaster, Vector2, Vector3 } from 'three'
|
||||
import { onUnmounted, ref, shallowRef, watch } from 'vue'
|
||||
|
||||
import * as THREE from 'three'
|
||||
|
||||
import DirectionalLightHelper from './Tres/DirectionalLightHelper.vue'
|
||||
|
||||
import { useVRM } from '../../stores'
|
||||
import { OrbitControls, VRMModel } from '../Scenes'
|
||||
|
||||
@@ -37,26 +37,35 @@ const {
|
||||
directionalLightPosition,
|
||||
directionalLightRotation,
|
||||
directionalLightIntensity,
|
||||
directionalLightColor,
|
||||
|
||||
ambientLightIntensity,
|
||||
ambientLightColor,
|
||||
|
||||
hemisphereLightPosition,
|
||||
hemisphereLightIntensity,
|
||||
hemisphereSkyColor,
|
||||
hemisphereGroundColor,
|
||||
} = storeToRefs(useVRM())
|
||||
|
||||
const modelRef = ref<InstanceType<typeof VRMModel>>()
|
||||
|
||||
const camera = shallowRef(new THREE.PerspectiveCamera())
|
||||
const camera = shallowRef(new PerspectiveCamera())
|
||||
const controlsRef = shallowRef<InstanceType<typeof OrbitControls>>()
|
||||
const directionalLightRef = shallowRef<InstanceType<typeof THREE.DirectionalLight>>()
|
||||
|
||||
const effectProps = {
|
||||
saturation: 0.3,
|
||||
hue: 0,
|
||||
blendFunction: BlendFunction.SRC,
|
||||
}
|
||||
|
||||
let isUpdatingCamera = true
|
||||
// manage the sequence of the camera and controls initialization
|
||||
const controlsReady = ref(false)
|
||||
const modelReady = ref(false)
|
||||
const sceneReady = ref(false)
|
||||
const raycaster = new THREE.Raycaster()
|
||||
const mouse = new THREE.Vector2()
|
||||
const raycaster = new Raycaster()
|
||||
const mouse = new Vector2()
|
||||
|
||||
watch(cameraFOV, (newFov) => {
|
||||
if (camera.value) {
|
||||
@@ -113,7 +122,7 @@ function handleLoadModelProgress() {
|
||||
modelReady.value = true
|
||||
}
|
||||
|
||||
// Then start to set the camera postion and target
|
||||
// Then start to set the camera position and target
|
||||
watch(
|
||||
[controlsReady, modelReady],
|
||||
([ctrlOk, modelOk]) => {
|
||||
@@ -146,9 +155,9 @@ watch(
|
||||
watch(cameraDistance, (newDistance) => {
|
||||
if (!isUpdatingCamera && camera.value && controlsRef.value && controlsRef.value.controls) {
|
||||
isUpdatingCamera = true
|
||||
const newPosition = new THREE.Vector3()
|
||||
const newPosition = new Vector3()
|
||||
const target = controlsRef.value.controls.target
|
||||
const direction = new THREE.Vector3().subVectors(camera.value.position, target).normalize()
|
||||
const direction = new Vector3().subVectors(camera.value.position, target).normalize()
|
||||
newPosition.copy(target).addScaledVector(direction, newDistance)
|
||||
camera.value.position.set(
|
||||
newPosition.x,
|
||||
@@ -179,16 +188,16 @@ function lookAtMouse(mouseX: number, mouseY: number) {
|
||||
raycaster.setFromCamera(mouse, camera.value)
|
||||
|
||||
// Create a plane in front of the camera
|
||||
const cameraDirection = new THREE.Vector3()
|
||||
const cameraDirection = new Vector3()
|
||||
camera.value.getWorldDirection(cameraDirection) // Get camera's forward direction
|
||||
|
||||
const plane = new THREE.Plane()
|
||||
const plane = new Plane()
|
||||
plane.setFromNormalAndCoplanarPoint(
|
||||
cameraDirection,
|
||||
camera.value.position.clone().add(cameraDirection.multiplyScalar(1)), // 1 unit in front of the camera
|
||||
)
|
||||
|
||||
const intersection = new THREE.Vector3()
|
||||
const intersection = new Vector3()
|
||||
raycaster.ray.intersectPlane(plane, intersection)
|
||||
lookAtTarget.value = { x: intersection.x, y: intersection.y, z: intersection.z }
|
||||
|
||||
@@ -239,28 +248,40 @@ defineExpose({
|
||||
|
||||
<template>
|
||||
<div ref="vrmContainerRef" w="100%" h="100%">
|
||||
<TresCanvas v-if="camera" v-show="sceneReady" :camera="camera" :antialias="true" :width="width" :height="height">
|
||||
<TresCanvas
|
||||
v-if="camera" v-show="sceneReady"
|
||||
:camera="camera"
|
||||
:antialias="true"
|
||||
:width="width"
|
||||
:height="height"
|
||||
:tone-mapping="ACESFilmicToneMapping"
|
||||
:tone-mapping-exposure="1"
|
||||
>
|
||||
<OrbitControls ref="controlsRef" />
|
||||
<TresAmbientLight
|
||||
:color="formatHex(ambientLightColor)"
|
||||
:intensity="ambientLightIntensity"
|
||||
cast-shadow
|
||||
/>
|
||||
<TresHemisphereLight
|
||||
:color="0xFFFFFF"
|
||||
:color="formatHex(hemisphereSkyColor)"
|
||||
:ground-color="formatHex(hemisphereGroundColor)"
|
||||
:position="[hemisphereLightPosition.x, hemisphereLightPosition.y, hemisphereLightPosition.z]"
|
||||
:intensity="hemisphereLightIntensity"
|
||||
cast-shadow
|
||||
/>
|
||||
<TresDirectionalLight
|
||||
ref="directionalLightRef"
|
||||
:color="0xFFFFFF"
|
||||
:color="formatHex(directionalLightColor)"
|
||||
:position="[directionalLightPosition.x, directionalLightPosition.y, directionalLightPosition.z]"
|
||||
:rotation="[directionalLightRotation.x, directionalLightRotation.y, directionalLightRotation.z]"
|
||||
:intensity="directionalLightIntensity"
|
||||
cast-shadow
|
||||
/>
|
||||
<DirectionalLightHelper :directional-light="directionalLightRef" />
|
||||
<TresAmbientLight
|
||||
:color="0xFFFFFF"
|
||||
:intensity="ambientLightIntensity"
|
||||
cast-shadow
|
||||
/>
|
||||
<Suspense>
|
||||
<EffectComposerPmndrs>
|
||||
<HueSaturationPmndrs v-bind="effectProps" />
|
||||
</EffectComposerPmndrs>
|
||||
</Suspense>
|
||||
<VRMModel
|
||||
ref="modelRef"
|
||||
:model-src="props.modelSrc"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
import type { CanvasTexture, DataTexture } from 'three'
|
||||
|
||||
import { useTresContext } from '@tresjs/core'
|
||||
import { EquirectangularReflectionMapping } from 'three'
|
||||
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
import defaultSkyBoxHdri from '../Tres/assets/sky_linekotsi_23_HDRI.hdr?url'
|
||||
|
||||
// Add these reactive variables to your setup
|
||||
const environment = ref<DataTexture | CanvasTexture>()
|
||||
const backgroundBlur = ref(0) // Controls background blur
|
||||
const backgroundIntensity = ref(1) // Controls background visibility
|
||||
|
||||
const { scene } = useTresContext()
|
||||
|
||||
// Add this function to load HDRI environment
|
||||
async function loadEnvironment() {
|
||||
try {
|
||||
const loader = new RGBELoader()
|
||||
// Resources
|
||||
// - polyhaven.com
|
||||
// - hdrihaven.com
|
||||
const texture = await loader.loadAsync(defaultSkyBoxHdri)
|
||||
texture.mapping = EquirectangularReflectionMapping
|
||||
|
||||
environment.value = texture
|
||||
|
||||
// Apply to scene if renderer is available
|
||||
if (scene.value) {
|
||||
scene.value.environment = texture
|
||||
scene.value.background = texture
|
||||
scene.value.backgroundBlurriness = backgroundBlur.value
|
||||
scene.value.backgroundIntensity = backgroundIntensity.value
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.warn('Failed to load HDRI environment:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Usage in your component
|
||||
onMounted(async () => {
|
||||
await loadEnvironment()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
</template>
|
||||
@@ -6,7 +6,7 @@ import { VRMUtils } from '@pixiv/three-vrm'
|
||||
import { useLoop, useTresContext } from '@tresjs/core'
|
||||
import { until, useObjectUrl } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { AnimationMixer, MathUtils, Quaternion, Vector3, VectorKeyframeTrack } from 'three'
|
||||
import { AnimationMixer, MathUtils, Mesh, MeshPhysicalMaterial, MeshStandardMaterial, Quaternion, Vector3, VectorKeyframeTrack } from 'three'
|
||||
import { computed, onMounted, onUnmounted, ref, toRef, watch } from 'vue'
|
||||
|
||||
import { clipFromVRMAnimation, loadVRMAnimation, useBlink, useIdleEyeSaccades } from '../../../composables/vrm/animation'
|
||||
@@ -32,6 +32,7 @@ const emit = defineEmits<{
|
||||
let disposeBeforeRenderLoop: (() => void | undefined)
|
||||
|
||||
const modelCreating = ref(false)
|
||||
const modelLoaded = ref(false)
|
||||
const modelSrcRef = toRef(() => props.modelSrc)
|
||||
const modelFileRef = toRef(() => props.modelFile)
|
||||
const modelFileSrc = useObjectUrl(modelFileRef)
|
||||
@@ -69,6 +70,7 @@ const idleEyeSaccades = useIdleEyeSaccades()
|
||||
async function loadModel() {
|
||||
await until(modelCreating).not.toBeTruthy()
|
||||
modelCreating.value = true
|
||||
modelLoaded.value = false
|
||||
|
||||
try {
|
||||
if (!scene.value) {
|
||||
@@ -83,7 +85,6 @@ async function loadModel() {
|
||||
const _vrmInfo = await loadVrm(modelSrcNormalized.value, {
|
||||
scene: scene.value,
|
||||
lookAt: true,
|
||||
positionOffset: [modelOffset.value.x, modelOffset.value.y, modelOffset.value.z],
|
||||
onProgress: progress => emit('loadModelProgress', Number((100 * progress.loaded / progress.total).toFixed(2))),
|
||||
})
|
||||
if (!_vrmInfo || !_vrmInfo._vrm) {
|
||||
@@ -99,6 +100,7 @@ async function loadModel() {
|
||||
} = _vrmInfo
|
||||
|
||||
vrmGroup.value = _vrmGroup
|
||||
|
||||
// Set initial camera position
|
||||
cameraPosition.value = {
|
||||
x: vrmModelCenter.x + vrmInitialCameraOffset.x,
|
||||
@@ -119,6 +121,12 @@ async function loadModel() {
|
||||
z: vrmModelSize.z,
|
||||
}
|
||||
|
||||
vrmGroup.value.position.set(
|
||||
modelOffset.value.x,
|
||||
modelOffset.value.y,
|
||||
modelOffset.value.z,
|
||||
)
|
||||
|
||||
// Set model facing direction
|
||||
const targetDirection = new Vector3(0, 0, -1) // Default facing direction
|
||||
const lookAt = _vrm.lookAt
|
||||
@@ -189,9 +197,28 @@ async function loadModel() {
|
||||
|
||||
vrmEmote.value = useVRMEmote(_vrm)
|
||||
|
||||
// TODO: perhaps we should allow user to choose whether to enable
|
||||
// this kind of behavior or not?
|
||||
// WORKAROUND: set to use envMapIntensity for all matched materials
|
||||
// REVIEW: MeshToonMaterial, and MeshBasicMaterial will not be affected
|
||||
// since they do not have envMapIntensity property
|
||||
_vrm.scene.traverse((child) => {
|
||||
if (child instanceof Mesh && child.material) {
|
||||
const material = Array.isArray(child.material) ? child.material : [child.material]
|
||||
material.forEach((mat) => {
|
||||
if (mat instanceof MeshStandardMaterial || mat instanceof MeshPhysicalMaterial) {
|
||||
// Should read envMap intensity from outside props
|
||||
mat.envMapIntensity = 1.0
|
||||
mat.needsUpdate = true
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
vrm.value = _vrm
|
||||
|
||||
emit('modelReady')
|
||||
modelLoaded.value = true
|
||||
|
||||
function getEyePosition(): number | null {
|
||||
const eye = vrm.value?.humanoid?.getNormalizedBoneNode('head')
|
||||
@@ -286,5 +313,5 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
<slot v-if="modelLoaded" />
|
||||
</template>
|
||||
|
||||
@@ -12,7 +12,6 @@ interface GLTFUserdata extends Record<string, any> {
|
||||
}
|
||||
|
||||
export async function loadVrm(model: string, options?: {
|
||||
positionOffset?: [number, number, number]
|
||||
scene?: Scene
|
||||
lookAt?: boolean
|
||||
onProgress?: (progress: ProgressEvent<EventTarget>) => void | Promise<void>
|
||||
@@ -57,8 +56,6 @@ export async function loadVrm(model: string, options?: {
|
||||
box.getCenter(modelCenter)
|
||||
modelCenter.y += modelSize.y / 5 // Adjust pivot to align chest with the origin
|
||||
|
||||
// Set position
|
||||
|
||||
// Compute the initial camera position (once per loaded model)
|
||||
// In order to see the up-2/3 part fo the model, z = (y/3) / tan(fov/2)
|
||||
const fov = 40 // default fov = 40 degrees
|
||||
|
||||
@@ -43,19 +43,39 @@ export const useVRM = defineStore('vrm', () => {
|
||||
const cameraPosition = useLocalStorage('settings/vrm/camera-position', { x: 0, y: 0, z: -1 })
|
||||
const cameraDistance = useLocalStorage('settings/vrm/cameraDistance', 0)
|
||||
|
||||
const directionalLightPosition = useLocalStorage('settings/vrm/scenes/scene/directional-light/position', { x: 1, y: 1, z: -10 })
|
||||
const directionalLightPosition = useLocalStorage('settings/vrm/scenes/scene/directional-light/position', { x: 0, y: 0, z: -10 })
|
||||
const directionalLightTarget = useLocalStorage('settings/vrm/scenes/scene/directional-light/target', { x: 0, y: 0, z: 0 })
|
||||
const directionalLightRotation = useLocalStorage('settings/vrm/scenes/scene/directional-light/rotation', { x: 0, y: 0, z: 0 })
|
||||
const directionalLightIntensity = useLocalStorage('settings/vrm/scenes/scene/directional-light/intensity', 0.6)
|
||||
const directionalLightColor = useLocalStorage('settings/vrm/scenes/scene/directional-light/color', '#FFFFFF')
|
||||
// TODO: Manual directional light intensity will not work for other
|
||||
// scenes with different lighting setups. But since the model
|
||||
// is possible to have MeshToonMaterial, and MeshBasicMaterial
|
||||
// without envMap to be able to inherit lighting from HDRI map,
|
||||
// we will have to figure out a way to make this work to apply
|
||||
// different directional light and other lighting setups
|
||||
// for different environments.
|
||||
// WORKAROUND: To achieve the rendering style of Warudo for anime style
|
||||
// Genshin Impact, or so called Cartoon style rendering with
|
||||
// harsh shadows and bright highlights.
|
||||
// REVIEW: This is a temporary solution, and will be replaced with
|
||||
// a more flexible lighting system in the future.
|
||||
const directionalLightIntensity = useLocalStorage('settings/vrm/scenes/scene/directional-light/intensity', 2.02)
|
||||
// TODO: color are the same
|
||||
const directionalLightColor = useLocalStorage('settings/vrm/scenes/scene/directional-light/color', '#fffbf5')
|
||||
|
||||
const hemisphereLightPosition = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/position', { x: 0, y: 1, z: 0 })
|
||||
const hemisphereLightPosition = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/position', { x: 0, y: 0, z: 0 })
|
||||
// TODO: color are the same
|
||||
const hemisphereSkyColor = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/sky-color', '#FFFFFF')
|
||||
// TODO: color are the same
|
||||
const hemisphereGroundColor = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/ground-color', '#000000')
|
||||
const hemisphereLightIntensity = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/intensity', 2.0)
|
||||
// TODO: The same as directional light, this is a temporary solution
|
||||
// and will be replaced with a more flexible lighting system in the future.
|
||||
const hemisphereLightIntensity = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/intensity', 0.4)
|
||||
|
||||
const ambientLightIntensity = useLocalStorage('settings/vrm/scenes/scene/ambient-light/intensity', 0.0)
|
||||
// TODO: color are the same
|
||||
const ambientLightColor = useLocalStorage('settings/vrm/scenes/scene/ambient-light/color', '#FFFFFF')
|
||||
// TODO: The same as directional light, this is a temporary solution
|
||||
// and will be replaced with a more flexible lighting system in the future.
|
||||
const ambientLightIntensity = useLocalStorage('settings/vrm/scenes/scene/ambient-light/intensity', 0.6)
|
||||
|
||||
const lookAtTarget = useLocalStorage('settings/vrm/lookAtTarget', { x: 0, y: 0, z: 0 })
|
||||
const isTracking = useLocalStorage('settings/vrm/isTracking', false)
|
||||
|
||||
Generated
+39
-108
@@ -1122,7 +1122,7 @@ importers:
|
||||
version: 0.1.3
|
||||
unplugin-yaml:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
vitepress:
|
||||
specifier: ^2.0.0-alpha.9
|
||||
version: 2.0.0-alpha.9(@types/node@24.1.0)(change-case@5.4.4)(fuse.js@7.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(nprogress@0.2.0)(postcss@8.5.6)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
|
||||
@@ -1165,7 +1165,7 @@ importers:
|
||||
devDependencies:
|
||||
unplugin-yaml:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
|
||||
packages/memory-pgvector:
|
||||
dependencies:
|
||||
@@ -1320,6 +1320,9 @@ importers:
|
||||
'@tresjs/core':
|
||||
specifier: ^4.3.6
|
||||
version: 4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
|
||||
'@tresjs/post-processing':
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0(@tresjs/core@4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
|
||||
'@vueuse/core':
|
||||
specifier: ^13.6.0
|
||||
version: 13.6.0(vue@3.5.18(typescript@5.9.2))
|
||||
@@ -1398,6 +1401,9 @@ importers:
|
||||
pixi-live2d-display:
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0(0736f5bd67d2e4de7e9fff36ad63fa2e)
|
||||
postprocessing:
|
||||
specifier: ^6.37.7
|
||||
version: 6.37.7(three@0.179.0)
|
||||
rehype-stringify:
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1
|
||||
@@ -1542,7 +1548,7 @@ importers:
|
||||
version: 1.2.4(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(esbuild@0.25.8)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
unplugin-yaml:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
vite:
|
||||
specifier: ^6.3.5
|
||||
version: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
@@ -5282,6 +5288,13 @@ packages:
|
||||
three: '>=0.133'
|
||||
vue: '>=3.4'
|
||||
|
||||
'@tresjs/post-processing@2.4.0':
|
||||
resolution: {integrity: sha512-4l18DTLkn0Y/abyn+FD/gSJ6/SC01oXn+/qPgUxMgxZ8zGaw4PZbOi4yorhbSbOTp0gO4D1X7lNOvNUokqJwFw==}
|
||||
peerDependencies:
|
||||
'@tresjs/core': '>=4.0'
|
||||
three: '>=0.169'
|
||||
vue: '>=3.4'
|
||||
|
||||
'@tweenjs/tween.js@23.1.3':
|
||||
resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
|
||||
|
||||
@@ -10423,6 +10436,11 @@ packages:
|
||||
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postprocessing@6.37.7:
|
||||
resolution: {integrity: sha512-3mXzCyhHQvw6cMQKzvHUzQVsy21yC3PZMIeH7KUjx+EVqLWRFPnARh4DEnnFJ+tE08mmIHrrN7UtxVR1Gxbokw==}
|
||||
peerDependencies:
|
||||
three: '>= 0.157.0 < 0.180.0'
|
||||
|
||||
potpack@1.0.2:
|
||||
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
|
||||
|
||||
@@ -16391,6 +16409,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@tresjs/post-processing@2.4.0(@tresjs/core@4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))':
|
||||
dependencies:
|
||||
'@tresjs/core': 4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
|
||||
'@vueuse/core': 12.8.2(typescript@5.9.2)
|
||||
postprocessing: 6.37.7(three@0.179.0)
|
||||
three: 0.179.0
|
||||
vue: 3.5.18(typescript@5.9.2)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@tweenjs/tween.js@23.1.3': {}
|
||||
|
||||
'@tybys/wasm-util@0.10.0':
|
||||
@@ -18335,107 +18363,6 @@ snapshots:
|
||||
- yaml
|
||||
optional: true
|
||||
|
||||
astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0):
|
||||
dependencies:
|
||||
'@astrojs/compiler': 2.12.2
|
||||
'@astrojs/internal-helpers': 0.6.1
|
||||
'@astrojs/markdown-remark': 6.3.2
|
||||
'@astrojs/telemetry': 3.3.0
|
||||
'@capsizecss/unpack': 2.4.0(encoding@0.1.13)
|
||||
'@oslojs/encoding': 1.1.0
|
||||
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
|
||||
acorn: 8.15.0
|
||||
aria-query: 5.3.2
|
||||
axobject-query: 4.1.0
|
||||
boxen: 8.0.1
|
||||
ci-info: 4.3.0
|
||||
clsx: 2.1.1
|
||||
common-ancestor-path: 1.0.1
|
||||
cookie: 1.0.2
|
||||
cssesc: 3.0.0
|
||||
debug: 4.4.1
|
||||
deterministic-object-hash: 2.0.2
|
||||
devalue: 5.1.1
|
||||
diff: 5.2.0
|
||||
dlv: 1.1.3
|
||||
dset: 3.1.4
|
||||
es-module-lexer: 1.7.0
|
||||
esbuild: 0.25.8
|
||||
estree-walker: 3.0.3
|
||||
flattie: 1.1.1
|
||||
fontace: 0.3.0
|
||||
github-slugger: 2.0.0
|
||||
html-escaper: 3.0.3
|
||||
http-cache-semantics: 4.2.0
|
||||
import-meta-resolve: 4.1.0
|
||||
js-yaml: 4.1.0
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.17
|
||||
magicast: 0.3.5
|
||||
mrmime: 2.0.1
|
||||
neotraverse: 0.6.18
|
||||
p-limit: 6.2.0
|
||||
p-queue: 8.1.0
|
||||
package-manager-detector: 1.3.0
|
||||
picomatch: 4.0.3
|
||||
prompts: 2.4.2
|
||||
rehype: 13.0.2
|
||||
semver: 7.7.2
|
||||
shiki: 3.9.1
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.14
|
||||
tsconfck: 3.1.6(typescript@5.9.2)
|
||||
ultrahtml: 1.6.0
|
||||
unifont: 0.5.2
|
||||
unist-util-visit: 5.0.0
|
||||
unstorage: 1.16.0
|
||||
vfile: 6.0.3
|
||||
vite: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
vitefu: 1.0.7(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
|
||||
xxhash-wasm: 1.1.0
|
||||
yargs-parser: 21.1.1
|
||||
yocto-spinner: 0.2.3
|
||||
zod: 3.25.76
|
||||
zod-to-json-schema: 3.24.6(zod@3.25.76)
|
||||
zod-to-ts: 1.2.0(typescript@5.9.2)(zod@3.25.76)
|
||||
optionalDependencies:
|
||||
sharp: 0.33.5
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
- '@azure/data-tables'
|
||||
- '@azure/identity'
|
||||
- '@azure/keyvault-secrets'
|
||||
- '@azure/storage-blob'
|
||||
- '@capacitor/preferences'
|
||||
- '@deno/kv'
|
||||
- '@netlify/blobs'
|
||||
- '@planetscale/database'
|
||||
- '@types/node'
|
||||
- '@upstash/redis'
|
||||
- '@vercel/blob'
|
||||
- '@vercel/kv'
|
||||
- aws4fetch
|
||||
- db0
|
||||
- encoding
|
||||
- idb-keyval
|
||||
- ioredis
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- rollup
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- typescript
|
||||
- uploadthing
|
||||
- yaml
|
||||
optional: true
|
||||
|
||||
async-mutex@0.3.2:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
@@ -23105,6 +23032,10 @@ snapshots:
|
||||
|
||||
postgres@3.4.7: {}
|
||||
|
||||
postprocessing@6.37.7(three@0.179.0):
|
||||
dependencies:
|
||||
three: 0.179.0
|
||||
|
||||
potpack@1.0.2: {}
|
||||
|
||||
prelude-ls@1.2.1: {}
|
||||
@@ -25280,7 +25211,7 @@ snapshots:
|
||||
rollup: 4.46.2
|
||||
vite: rolldown-vite@7.0.12(@types/node@24.1.0)(esbuild@0.25.8)(jiti@2.5.1)(less@4.4.0)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
|
||||
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
|
||||
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
|
||||
unplugin: 2.3.5
|
||||
@@ -25288,13 +25219,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
|
||||
astro: 5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
|
||||
astro: 5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
|
||||
esbuild: 0.25.8
|
||||
rolldown: 1.0.0-beta.30
|
||||
rollup: 4.46.2
|
||||
vite: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
|
||||
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
|
||||
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
|
||||
unplugin: 2.3.5
|
||||
@@ -25302,7 +25233,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
|
||||
astro: 5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
|
||||
astro: 5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
|
||||
esbuild: 0.25.8
|
||||
rolldown: 1.0.0-beta.30
|
||||
rollup: 4.46.2
|
||||
|
||||
Reference in New Issue
Block a user