1
0
Эх сурвалжийг харах

Merge pull request #112 from Tresjs/feature/110-environment-component-cientos

feat(cientos): environment component cientos
Alvaro Saburido 2 жил өмнө
parent
commit
d6a422ebbc

+ 2 - 0
docs/.vitepress/config.ts

@@ -70,6 +70,8 @@ export default defineConfig({
             items: [
               { text: 'Text3D', link: '/cientos/abstractions/text-3d' },
               { text: 'useAnimations', link: '/cientos/abstractions/use-animations' },
+              { text: 'Environment', link: '/cientos/abstractions/environment' },
+              { text: 'useEnvironment', link: '/cientos/abstractions/use-environment' },
             ],
           },
           {

+ 67 - 0
docs/cientos/abstractions/environment.md

@@ -0,0 +1,67 @@
+# Environment <Badge type="warning" text="^1.7.0" />
+
+![Environment](/cientos/environment.png)
+
+Is a component abstraction that automatically sets up a global cubemap, which affects the default `scene.environment`, and optionally `scene.background`,
+
+It uses the composable [useEnvironment](/cientos/abstractions/use-environment) under the hood to load the cubemap.
+
+## Usage
+
+```html
+<Environment
+  :files="[
+    '/px.jpg',
+    '/nx.jpg',
+    '/py.jpg',
+    '/ny.jpg',
+    '/pz.jpg',
+    '/nz.jpg'
+]"
+/>
+```
+
+You can also pass the `.hdr` file directly:
+
+```html
+<Environment files="/sunset.hdr" />
+```
+
+![Environment](/cientos/envmaps.png)
+
+## Texture reference
+
+You can access the model reference by pasing a `ref` to the `<Environment />` prop and then using the method `getTexture()` to get the object.
+
+```vue{4,6,9,14,17}
+<script setup lang="ts">
+import { Environment } from '@tresjs/cientos'
+
+let envMap = null
+
+const environmentTexture = shallowRef()
+
+watch(environmentTexture, ({ getTexture }) => {
+  envMap = getTexture()
+})
+</script>
+
+<template>
+  <Environment ref="environmentTexture" />
+  <TresMesh>
+    <TresSphereGeometry />
+    <TresMeshStandardMaterial :env-map="envMap" />
+  </TresMesh>
+</template>
+```
+
+## Props
+
+| Prop         | Description                                                          | Default                                                                        |
+| :----------- | :------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
+| `files`      | Array of 6 urls to images, one for each side of the CubeTexture.     | `undefined`                                                                    |
+| `path`       | Path to the environment map files.                                   | `undefined`                                                                    |
+| `encoding`   | Encoding of the environment map.                                     | `sRGBEncoding` for an array of files and `LinearEncoding` for a single texture |
+| `background` | If `true`, the environment map will be used as the scene background. | `false`                                                                        |
+| `blur`       | Blur factor between 0 and 1. (only works with three 0.146 and up)    | 0                                                                              |
+| `preset`     | Preset environment map.                                              | `undefined`                                                                    |

+ 44 - 0
docs/cientos/abstractions/use-environment.md

@@ -0,0 +1,44 @@
+# UseEnvironment <Badge type="warning" text="^1.7.0" />
+
+`useEnvironment` composable that automatically sets up a global cubemap, which affects the default `scene.environment`, and optionally `scene.background`.
+
+It uses the [CubeTextureLoader](https://threejs.org/docs/#api/en/loaders/CubeTextureLoader) to load the cubemap
+
+## Usage
+
+```ts
+import { useEnvironment } from '@tresjs/cientos'
+
+const texture = await useEnvironment({
+  files: [
+    '/textures/environmentMaps/0/px.jpg',
+    '/textures/environmentMaps/0/nx.jpg',
+    '/textures/environmentMaps/0/py.jpg',
+    '/textures/environmentMaps/0/ny.jpg',
+    '/textures/environmentMaps/0/pz.jpg',
+    '/textures/environmentMaps/0/nz.jpg',
+  ],
+  path: '',
+  encoding: sRGBEncoding,
+})
+```
+
+Then you can use the `texture` in your scene:
+
+```html{3}
+<TresMesh>
+    <TresSphereGeometry />
+    <TresMeshStandardMaterial :map="texture" />
+</TresMesh>
+```
+
+## Options
+
+| Name           | Type       | Default                                                                        | Description                                                       |
+| :------------- | ---------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------- |
+| **files**      | `Array`    | `undefined`                                                                    | Array of 6 urls to images, one for each side of the CubeTexture.  |
+| **path**       | `boolean`  | `false`                                                                        | Path to the environment map files.                                |
+| **encoding**   | `Encoding` | `sRGBEncoding` for an array of files and `LinearEncoding` for a single texture | Encoding of the environment map.                                  |
+| **background** | `boolean`  | `false`                                                                        | If `true` the texture will be used as the scene background.       |
+| **blur**       | `number`   | `0`                                                                            | Blur factor between 0 and 1. (only works with three 0.146 and up) |
+| **preset**     | `string`   | `undefined`                                                                    | Preset environment map.                                           |

BIN
docs/public/cientos/environment.png


BIN
docs/public/cientos/envmaps.png


+ 36 - 0
packages/cientos/src/core/useEnvironment/component.ts

@@ -0,0 +1,36 @@
+import { EnvironmentOptions, EnvironmentPresetsType } from './const'
+import { CubeTexture, Texture, TextureEncoding } from 'three'
+import { defineComponent, PropType } from 'vue'
+
+import { useEnvironment } from '.'
+
+export const Environment = defineComponent({
+  name: 'Environment',
+  props: {
+    background: {
+      type: Boolean,
+      default: false,
+    },
+    blur: {
+      type: Number,
+      default: 0,
+    },
+    files: {
+      type: [String, Array],
+    },
+    encoding: Object as PropType<TextureEncoding>,
+    path: String,
+    preset: Object as PropType<EnvironmentPresetsType>,
+  },
+  async setup(props, { expose }) {
+    let texture: Texture | CubeTexture | null = null
+
+    expose({ getTexture: () => texture })
+
+    texture = await useEnvironment(props as EnvironmentOptions)
+
+    return () => {
+      texture
+    }
+  },
+})

+ 16 - 0
packages/cientos/src/core/useEnvironment/const.ts

@@ -0,0 +1,16 @@
+import { TextureEncoding } from 'three'
+
+export type EnvironmentOptions = {
+  background?: boolean
+  blur?: number
+  files?: string | string[]
+  path?: string
+  preset?: EnvironmentPresetsType
+  encoding?: TextureEncoding
+}
+
+export const environmentPresets = {
+  sunset: 'venice/venice_sunset_4k.hdr',
+}
+
+export type EnvironmentPresetsType = keyof typeof environmentPresets

+ 58 - 0
packages/cientos/src/core/useEnvironment/index.ts

@@ -0,0 +1,58 @@
+import { useLoader } from '@tresjs/core'
+import {
+  CubeReflectionMapping,
+  CubeTexture,
+  CubeTextureLoader,
+  EquirectangularReflectionMapping,
+  LinearEncoding,
+  sRGBEncoding,
+  Texture,
+} from 'three'
+import { RGBELoader } from 'three-stdlib'
+import { useCientos } from '../useCientos'
+import { EnvironmentOptions, environmentPresets } from './const'
+
+export async function useEnvironment({
+  files = ['/px.png', '/nx.png', '/py.png', '/ny.png', '/pz.png', '/nz.png'],
+  blur = 0,
+  background = false,
+  path = undefined,
+  preset = undefined,
+  encoding = undefined,
+}: Partial<EnvironmentOptions>): Promise<Texture | CubeTexture> {
+  const { state } = useCientos()
+
+  if (preset) {
+    if (!(preset in environmentPresets))
+      throw new Error('Preset must be one of: ' + Object.keys(environmentPresets).join(', '))
+    files = environmentPresets[preset]
+    path = 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/hdr/'
+  }
+
+  const isCubeMap = Array.isArray(files)
+
+  const loader = isCubeMap ? CubeTextureLoader : RGBELoader
+
+  const result = await useLoader(loader, isCubeMap ? [files] : files, (loader: any) => {
+    if (path) loader.setPath(path)
+    if (encoding) loader.encoding = encoding
+  })
+
+  const texture: Texture | CubeTexture = isCubeMap ? result[0] : result
+
+  if (texture) {
+    texture.mapping = isCubeMap ? CubeReflectionMapping : EquirectangularReflectionMapping
+    texture.encoding = encoding ?? isCubeMap ? sRGBEncoding : LinearEncoding
+  }
+
+  if (background && state.scene) {
+    state.scene.environment = texture
+    state.scene.background = texture
+
+    if (blur) {
+      state.scene.backgroundBlurriness = blur | 0
+    }
+  }
+
+  return texture
+}

+ 3 - 0
packages/cientos/src/index.ts

@@ -18,9 +18,11 @@ import Tetrahedron from './core/Tetrahedron.vue'
 import Icosahedron from './core/Icosahedron.vue'
 import Octahedron from './core/Octahedron.vue'
 import Dodecahedron from './core/Dodecahedron.vue'
+import { Environment } from './core/useEnvironment/component'
 
 export * from './core/useGLTF'
 export * from './core/useFBX'
+export * from './core/useEnvironment'
 export * from './types'
 export {
   OrbitControls,
@@ -43,4 +45,5 @@ export {
   Octahedron,
   Dodecahedron,
   useAnimations,
+  Environment,
 }

+ 2 - 2
packages/tres/src/App.vue

@@ -1,12 +1,12 @@
 <script setup lang="ts">
 import { useTweakPane } from '@tresjs/cientos'
-import TheEvents from '/@/components/TheEvents.vue'
+import TheEnvironment from '/@/components/TheEnvironment.vue'
 
 useTweakPane()
 </script>
 
 <template>
   <Suspense>
-    <TheEvents />
+    <TheEnvironment />
   </Suspense>
 </template>

+ 135 - 0
packages/tres/src/components/TheEnvironment.vue

@@ -0,0 +1,135 @@
+<script setup lang="ts">
+import {
+  sRGBEncoding,
+  LinearEncoding,
+  BasicShadowMap,
+  PCFShadowMap,
+  PCFSoftShadowMap,
+  VSMShadowMap,
+  NoToneMapping,
+  LinearToneMapping,
+  ReinhardToneMapping,
+  CineonToneMapping,
+  ACESFilmicToneMapping,
+  CustomToneMapping,
+} from 'three'
+import { reactive, ref, shallowRef, watch } from 'vue'
+import { OrbitControls, useTweakPane, Environment } from '../../../cientos/src'
+import { TresCanvas } from '../core/useRenderer/component'
+/* import { OrbitControls, GLTFModel } from '@tresjs/cientos' */
+
+const state = reactive({
+  shadows: true,
+  alpha: true,
+  physicallyCorrectLights: true,
+  shadowMapType: BasicShadowMap,
+  outputEncoding: sRGBEncoding,
+  toneMapping: NoToneMapping,
+})
+
+const sphereRef = ref()
+
+const { pane } = useTweakPane()
+
+/* const environmentFiles = [
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/px.jpg',
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/nx.jpg',
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/py.jpg',
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/ny.jpg',
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/pz.jpg',
+  'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap/nz.jpg',
+] */
+
+const environmentFiles = ['/px.jpg', '/nx.jpg', '/py.jpg', '/ny.jpg', '/pz.jpg', '/nz.jpg']
+
+let envMap = null
+
+const environmentTexture = shallowRef()
+
+watch(environmentTexture, ({ getTexture }) => {
+  envMap = getTexture()
+})
+
+pane.addInput(state, 'shadows', {
+  label: 'Shadows',
+})
+pane.addInput(state, 'physicallyCorrectLights', {
+  label: 'physicallyCorrectLights',
+})
+
+pane
+  .addBlade({
+    view: 'list',
+    label: 'outputEncoding',
+    options: [
+      { text: 'sRGBEncoding', value: sRGBEncoding },
+      { text: 'LinearEncoding', value: LinearEncoding },
+    ],
+    value: sRGBEncoding,
+  })
+  .on('change', ev => {
+    state.outputEncoding = ev.value
+  })
+
+pane
+  .addBlade({
+    view: 'list',
+    label: 'ShadowMap Type',
+    options: [
+      { text: 'BasicShadowMap', value: BasicShadowMap },
+      { text: 'PCFShadowMap', value: PCFShadowMap },
+      { text: 'PCFSoftShadowMap', value: PCFSoftShadowMap },
+      { text: 'VSMShadowMap', value: VSMShadowMap },
+    ],
+    value: BasicShadowMap,
+  })
+  .on('change', ev => {
+    state.shadowMapType = ev.value
+  })
+
+pane
+  .addBlade({
+    view: 'list',
+    label: 'toneMapping',
+    options: [
+      { text: 'NoToneMapping', value: NoToneMapping },
+      { text: 'LinearToneMapping', value: LinearToneMapping },
+      { text: 'ReinhardToneMapping', value: ReinhardToneMapping },
+      { text: 'CineonToneMapping', value: CineonToneMapping },
+      { text: 'ACESFilmicToneMapping', value: ACESFilmicToneMapping },
+      { text: 'CustomToneMapping', value: CustomToneMapping },
+    ],
+    value: NoToneMapping,
+  })
+  .on('change', ev => {
+    console.log(ev.value)
+    state.toneMapping = ev.value
+  })
+</script>
+<template>
+  <TresCanvas v-bind="state">
+    <TresPerspectiveCamera :position="[8, 8, 8]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
+    <OrbitControls make-default />
+    <TresScene>
+      <Environment
+        ref="environmentTexture"
+        background
+        :files="environmentFiles"
+        :path="'https://raw.githubusercontent.com/Tresjs/assets/main/textures/environmentMap'"
+      />
+      <!--  <Environment ref="environmentTexture" background preset="sunset" /> -->
+      <TresAmbientLight :intensity="0.5" />
+
+      <TresMesh ref="sphereRef" :position="[0, 4, 0]" cast-shadow>
+        <TresSphereGeometry />
+        <TresMeshStandardMaterial color="#FBB03B" :map="envMap" :metalness="1" :roughness="0" />
+      </TresMesh>
+      <TresDirectionalLight :position="[0, 8, 4]" :intensity="0.7" cast-shadow />
+      <TresMesh :rotation="[-Math.PI / 2, 0, 0]" receive-shadow>
+        <TresPlaneGeometry :args="[10, 10, 10, 10]" />
+        <TresMeshToonMaterial />
+      </TresMesh>
+      <TresDirectionalLight :position="[0, 2, 4]" :intensity="1" cast-shadow />
+    </TresScene>
+  </TresCanvas>
+</template>