Skip to content

Commit

Permalink
feat: 107 use video texture (#167)
Browse files Browse the repository at this point in the history
* feat: add use video texture, draft

* chore: update types

* chore: fix types, clean the code

* docs: add docs for useVideoTexture

* chore: add error handling

* chore: use complete words, less cognitive load
  • Loading branch information
JaimeTorrealba authored Aug 21, 2023
1 parent d71ab29 commit f0f1f9b
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default defineConfig({
{ text: 'GLTFModel', link: '/guide/loaders/gltf-model' },
{ text: 'useFBX', link: '/guide/loaders/use-fbx' },
{ text: 'FBXModel', link: '/guide/loaders/fbx-model' },
{ text: 'useVideoTexture', link: '/guide/loaders/use-video-texture' },
],
},
{
Expand Down
39 changes: 39 additions & 0 deletions docs/guide/loaders/use-video-texture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# useVideoProgress

A composable to easily use videos as textures in your meshes.

This composable is based on the Drei [useVideoTexture](https://github.com/pmndrs/drei/tree/master#usevideotexture)

## Usage

```ts
import { useVideoTexture } from '@tresjs/cientos'
import exampleVideo from '/myVideoPath'

const texture = ref()
texture.value = await useVideoTexture(exampleVideo, { loop: false })
```

Then you can use the texture in your material, for example:

```vue{3}
...
<Sphere :position="[0, 2, 0]">
<TresMeshBasicMaterial :map="texture" />
</Sphere>
...
```

## Props

| Prop | Description | Default |
| :------------ | :----------------------------------------------------------------------- | ---------------- |
| `src` | Path to the video. | `undefined` |
| `unsuspend` | Path to the model file. | `loadedmetadata` |
| `crossOrigin` | Whether to use CORS to fetch the related video. | `Anonymous` |
| `muted` | Whether to set the audio silenced. | true |
| `loop` | Automatically seek back to the start upon reaching the end of the video. | true |
| `start` | To play to the video once loaded or not. | true |
| `playsInline` | To be play the video inline or not. | true |

- Any other attribute for a `<video>` tag is accepted and will automatically set
33 changes: 33 additions & 0 deletions playground/src/components/useVideoTextureDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useVideoTexture, OrbitControls } from '@tresjs/cientos'
import { Sphere } from '../../../src/core'
import { TresCanvas } from '@tresjs/core'
import { SRGBColorSpace, NoToneMapping } from 'three'
const gl = {
clearColor: '#333',
alpha: true,
outputColorSpace: SRGBColorSpace,
toneMapping: NoToneMapping,
useLegacyLights: false,
}
const exampleVideo = 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/video-textures/useVideoTexture.mp4'
const texture = ref()
texture.value = await useVideoTexture(exampleVideo, { loop: false})
</script>
<template>
<TresCanvas v-bind="gl" ref="canvas">
<TresPerspectiveCamera :position="[0, 2, 5]" />
<OrbitControls />
<Sphere :position="[0, 2, 0]">
<TresMeshBasicMaterial :map="texture" />
</Sphere>
<TresGridHelper :size="10" :divisions="10" />
<TresAmbientLight :intensity="1" />
</TresCanvas>
</template>
6 changes: 3 additions & 3 deletions playground/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts"></script>
<template>
<Suspense>
<OrbitControlsDemo />
</Suspense>
<Suspense>
<UseVideoTextureDemo />
</Suspense>
</template>
3 changes: 2 additions & 1 deletion src/core/loaders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import FBXModel from './useFBX/component.vue'
export * from './useGLTF'
export * from './useFBX'
import { useProgress } from './useProgress'
import { useVideoTexture } from './useVideoTexture'

export { FBXModel, GLTFModel, useProgress }
export { FBXModel, GLTFModel, useProgress, useVideoTexture }
73 changes: 73 additions & 0 deletions src/core/loaders/useVideoTexture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { VideoTexture } from 'three'
import { useLogger } from '../../composables/useLogger'

interface VideoTextureProps extends HTMLVideoElement {
unsuspend?: 'canplay' | 'canplaythrough' | 'loadstart' | 'loadedmetadata'
start?: boolean
}

/**
* Composable for loading video textures.
*
* ```ts
* import { ref } from 'vue'
* import { useVideoTexture } from '@tresjs/cientos'
* import MyVideo from 'MyVideo.mp4'
*
* const texture = ref()
* texture.value = await useVideoTexture(MyVideo)
* ```
* Then you can use the texture in your material.
*
* ```vue
* <TresMeshBasicMaterial :map="texture" />
* ```
* @see https://threejs.org/docs/index.html?q=video#api/en/textures/VideoTexture
* @export
* @param {HTMLVideoElement} src
* @return {VideoTexture} {VideoTexture}
*/
export async function useVideoTexture(src: string | MediaStream, options?: Partial<VideoTextureProps>) {
/**
* Load a video as a texture.
*
* @param {src} string
* @return {VideoTexture} {VideoTexture}
*/
const { logError } = useLogger()
if (!src) return logError('Error no path provided')

const { unsuspend, start, crossOrigin, muted, loop, ...rest } = {
unsuspend: 'loadedmetadata',
crossOrigin: 'Anonymous',
muted: true,
loop: true,
start: true,
playsInline: true,
...options,
}

function loadTexture(): Promise<VideoTexture> {
return new Promise((resolve, reject) => {
const video = Object.assign(document.createElement('video'), {
src: (typeof src === 'string' && src) || undefined,
crossOrigin,
loop,
muted,
autoplay: true,
...rest,
})
const texture = new VideoTexture(video)
video.addEventListener(unsuspend, () => resolve(texture))
video.addEventListener('error', () => reject())
return texture
})
}
try {
const texture = await loadTexture()
if (start && texture.image) texture.image.play()
return texture
} catch {
logError('Error loading resource')
}
}

0 comments on commit f0f1f9b

Please sign in to comment.