Skip to content

Commit

Permalink
feat: use tres provider and context
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosabu committed Apr 3, 2023
1 parent 6819e24 commit 46cdd00
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 141 deletions.
63 changes: 58 additions & 5 deletions playground/src/components/MultipleCanvas.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,66 @@
<script setup lang="ts">
import { TresCanvas } from '/@/'
import { BasicShadowMap, NoToneMapping, sRGBEncoding } from 'three'
import { TresCanvas } from '/@/components/TresCanvas'
import { GLTFModel, OrbitControls } from '@tresjs/cientos'
const state = reactive({
clearColor: '#201919',
shadows: true,
alpha: false,
shadowMapType: BasicShadowMap,
outputEncoding: sRGBEncoding,
toneMapping: NoToneMapping,
})
const state2 = reactive({
clearColor: '#4f4f4f',
shadows: true,
alpha: false,
/* shadowMapType: BasicShadowMap,
outputEncoding: sRGBEncoding,
toneMapping: NoToneMapping, */
})
</script>
<template>
<div class="flex">
<div class="w-1/2 aspect-video">
<TresCanvas />
<TresCanvas v-bind="state">
<TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[0, 4, 0]" />
<OrbitControls />

<TresAmbientLight :intensity="0.5" />
<TresMesh :position="[0, 4, 0]">
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshToonMaterial color="cyan" />
</TresMesh>

<Suspense>
<TestSphere />
</Suspense>
<TresDirectionalLight :position="[0, 2, 4]" :intensity="1" />
</TresCanvas>
</div>
<div class="w-1/2 aspect-video">
<TresCanvas v-bind="state2">
<TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[0, 4, 0]" />
<TresAmbientLight :intensity="0.5" />

<TresMesh :position="[0, 4, 0]" cast-shadow>
<TresSphereGeometry :args="[2, 32, 32]" />
<TresMeshToonMaterial color="yellow" />
</TresMesh>
<OrbitControls />

<Suspense>
<GLTFModel
path="https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/aku-aku/AkuAku.gltf"
draco
/>
</Suspense>

<TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
</TresCanvas>
</div>
<!-- <div class="w-1/2 aspect-video">
<TresCanvas />
</div> -->
</div>
</template>
2 changes: 1 addition & 1 deletion playground/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup lang="ts"></script>
<template>
<MultipleCanvas></MultipleCanvas>
<MultipleCanvas />
</template>
116 changes: 6 additions & 110 deletions src/components/TresCanvas.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { App, defineComponent, h, onUnmounted, ref, watch, watchEffect } from 'vue'
import * as THREE from 'three'
import { TresScene } from './TresScene'
import { defineComponent, h } from 'vue'
import { ShadowMapType, TextureEncoding, ToneMapping } from 'three'
import { createTres } from '/@/core/renderer'
import { useLogger } from '/@/composables'
import { useCamera, useRenderer, useRenderLoop, useRaycaster, useTres } from '/@/composables'
import { extend } from '/@/core/catalogue'
import { useTresProvider } from '/@/composables'
import { RendererPresetsType } from '/@/composables/useRenderer/const'
import { TresObject } from '../types'

export interface TresCanvasProps {
shadows?: boolean
Expand All @@ -27,8 +23,6 @@ export interface TresCanvasProps {
* Vue component for rendering a Tres component.
*/

const { logWarning } = useLogger()

export const TresCanvas = defineComponent<TresCanvasProps>({
name: 'TresCanvas',
props: [
Expand All @@ -46,109 +40,11 @@ export const TresCanvas = defineComponent<TresCanvasProps>({
'windowSize',
'preset',
] as unknown as undefined,
setup(props, { slots, expose }) {
if (props.physicallyCorrectLights === true) {
logWarning('physicallyCorrectLights is deprecated, useLegacyLights is now false by default')
}

const container = ref<HTMLElement>()
const canvas = ref<HTMLCanvasElement>()
const scene = new THREE.Scene()
const { setState } = useTres()

setState('scene', scene)

onUnmounted(() => {
setState('renderer', null)
})

function initRenderer() {
const { renderer } = useRenderer(canvas, container, props)

const { activeCamera } = useCamera()

const { onLoop } = useRenderLoop()

const { raycaster, pointer } = useRaycaster()

watchEffect(() => {
if (activeCamera.value) raycaster.value.setFromCamera(pointer.value, activeCamera.value)
})

onLoop(() => {
if (activeCamera.value) renderer.value?.render(scene, activeCamera.value)
})
}

watch(canvas, initRenderer)

let app: App

function mountApp() {
app = createTres(slots)
app.provide('useTres', useTres())
app.provide('extend', extend)
app.mount(scene as unknown as TresObject)
}

mountApp()
expose({
scene,
})

function dispose() {
scene.children = []
app.unmount()
mountApp()
}

if (import.meta.hot) {
import.meta.hot.on('vite:afterUpdate', dispose)
}
setup(props, { slots }) {
useTresProvider()

return () => {
return h(
h(
'div',
{
ref: container,
'data-scene': scene.uuid,
key: scene.uuid,
style: {
position: 'relative',
width: '100%',
height: '100%',
pointerEvents: 'auto',
touchAction: 'none',
},
},
[
h(
'div',
{
style: {
width: '100%',
height: '100%',
},
},
[
h('canvas', {
ref: canvas,
'data-scene': scene.uuid,
style: {
display: 'block',
width: '100%',
height: '100%',
position: props.windowSize ? 'fixed' : 'absolute',
top: 0,
left: 0,
},
}),
],
),
],
),
)
return h(TresScene, props, slots)
}
},
})
Expand Down
164 changes: 164 additions & 0 deletions src/components/TresScene.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { App, defineComponent, h, onMounted, onUnmounted, onUpdated, provide, ref, watch, watchEffect } from 'vue'
import * as THREE from 'three'
import { PerspectiveCamera, ShadowMapType, TextureEncoding, ToneMapping } from 'three'
import { createTres } from '/@/core/renderer'
import { useLogger } from '/@/composables'
import { useCamera, useRenderer, useRenderLoop, useRaycaster, useTres } from '/@/composables'
import { extend } from '/@/core/catalogue'
import { RendererPresetsType } from '/@/composables/useRenderer/const'
import { TresObject } from '../types'

export interface TresSceneProps {
shadows?: boolean
shadowMapType?: ShadowMapType
physicallyCorrectLights?: boolean
useLegacyLights?: boolean
outputEncoding?: TextureEncoding
toneMapping?: ToneMapping
toneMappingExposure?: number
context?: WebGLRenderingContext
powerPreference?: 'high-performance' | 'low-power' | 'default'
preserveDrawingBuffer?: boolean
clearColor?: string
windowSize?: boolean
preset?: RendererPresetsType
}
/**
* Vue component for rendering a Tres component.
*/

const { logWarning } = useLogger()

export const TresScene = defineComponent<TresSceneProps>({
name: 'TresScene',
props: [
'shadows',
'shadowMapType',
'physicallyCorrectLights',
'useLegacyLights',
'outputEncoding',
'toneMapping',
'toneMappingExposure',
'context',
'powerPreference',
'preserveDrawingBuffer',
'clearColor',
'windowSize',
'preset',
] as unknown as undefined,
setup(props, { slots, expose }) {
if (props.physicallyCorrectLights === true) {
logWarning('physicallyCorrectLights is deprecated, useLegacyLights is now false by default')
}

const container = ref<HTMLElement>()
const canvas = ref<HTMLElement>()
const scene = new THREE.Scene()
const { state, setState } = useTres()

setState('scene', scene)
setState('canvas', canvas)
setState('container', container)

const { pushCamera } = useCamera()
pushCamera(new PerspectiveCamera())

onMounted(() => {
initRenderer()
})

onUnmounted(() => {
setState('renderer', null)
})

function initRenderer() {
const { renderer } = useRenderer(props)

const { activeCamera } = useCamera()

const { onLoop } = useRenderLoop()

const { raycaster, pointer } = useRaycaster()

watchEffect(() => {
if (activeCamera.value) raycaster.value.setFromCamera(pointer.value, activeCamera.value)
})

onLoop(() => {
if (activeCamera.value) renderer.value?.render(scene, activeCamera.value)
})
}

let app: App

function mountApp() {
app = createTres(slots)
app.provide('useTres', useTres())
app.provide('extend', extend)
app.mount(scene as unknown as TresObject)
}

mountApp()

expose({
scene,
})

function dispose() {
scene.children = []
app.unmount()
mountApp()
}

if (import.meta.hot) {
import.meta.hot.on('vite:afterUpdate', dispose)
}

return () => {
return h(
h(
'div',
{
ref: container,
'data-scene': scene.uuid,
key: scene.uuid,
style: {
position: 'relative',
width: '100%',
height: '100%',
pointerEvents: 'auto',
touchAction: 'none',
},
},
[
h(
'div',
{
style: {
width: '100%',
height: '100%',
},
},
[
h('canvas', {
ref: canvas,
'data-scene': scene.uuid,
style: {
display: 'block',
width: '100%',
height: '100%',
position: props.windowSize ? 'fixed' : 'absolute',
top: 0,
left: 0,
},
}),
],
),
],
),
)
}
},
})

export default TresScene
Loading

0 comments on commit 46cdd00

Please sign in to comment.