Skip to content

Commit

Permalink
Merge pull request #363 from Tresjs/feature/252-water-component
Browse files Browse the repository at this point in the history
feat: 252 ocean component
  • Loading branch information
JaimeTorrealba authored Mar 13, 2024
2 parents 49444d0 + 94a927f commit 55ca2bf
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 3 deletions.
4 changes: 3 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ export default defineConfig({
{ text: 'Smoke', link: '/guide/staging/smoke' },
{ text: 'Contact Shadows', link: '/guide/staging/contact-shadows' },
{ text: 'Precipitation', link: '/guide/staging/precipitation' },
{ text: 'Sparkles', link: '/guide/staging/sparkles' }],
{ text: 'Sparkles', link: '/guide/staging/sparkles' },
{ text: 'Ocean', link: '/guide/staging/ocean' },
],
},
{
text: 'Misc',
Expand Down
24 changes: 24 additions & 0 deletions docs/.vitepress/theme/components/OceanDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { Sky, OrbitControls, Ocean } from '@tresjs/cientos'
</script>

<template>
<TresCanvas>
<TresPerspectiveCamera :position="[0, 1, 1]" />
<Sky :azimuth="0" />
<Suspense>
<Ocean />
</Suspense>
<TresMesh :position-y="1">
<TresBoxGeometry :args="[1, 1, 1]" />
</TresMesh>
<OrbitControls
:enable-pan="false"
:enable-zoom="false"
:max-polar-angle="Math.PI * 0.495"
:min-distance="40.0"
:max-distance="200.0"
/>
</TresCanvas>
</template>
56 changes: 56 additions & 0 deletions docs/guide/staging/ocean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Ocean

<DocsDemo>
<OceanDemo />
</DocsDemo>

`<Ocean />` is a wrapper for the [Three.js `Water` add-on](https://threejs.org/examples/?q=ocean#webgl_shaders_ocean).

::: warning
<Ocean /> comes with a default texture, so it needs to be wrapped in a Suspense component.
:::

## Usage

<<< @/.vitepress/theme/components/OceanDemo.vue{3,11}

### SKY

<Ocean /> works hand in hand with the Sky component, detecting the position of the sun and reflecting on the water.
(<Sky /> is not required for making this component work.)

### Fog

The `<Ocean />` component also reacts when there's [Fog](https://threejs.org/docs/index.html?q=fog#api/en/scenes/Fog) or [FogExp2](https://threejs.org/docs/index.html?q=fog#api/en/scenes/FogExp2) in your scene.

## Custom Geometry

You can use custom geometry by adding it as a child.

```
<Suspense>
<Ocean>
<TresCircleGeometry :args="[50, 16]" />
</Ocean>
</Suspense>
```

## Props

::: warning
All of the props of this component are not reactive.
:::

| Prop | Description | Default |
| :------------------ | :------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| **textureWidth** | Width of the mirror texture | 512 |
| **textureHeight** | Height of the mirror texture | 512 |
| **waterNormals** | Normals of the water | https://raw.githubusercontent.com/Tresjs/assets/main/textures/water-normals/Water_1_M_Normal.jpg |
| **sunDirection** | Sun direction to be reflected on the water | Vector3(0,0,0) |
| **sunColor** | Sun color to be reflected on the water | 0xffffff |
| **waterColor** | Water Color | 0x001e0f |
| **distortionScale** | Distortion scale on reflected objects | 3.7 |
| **size** | Size of the water normals | 1 |
| **clipBias** | To use the clipBias property | 0.0 |
| **alpha** | To use the clipBias Alpha | 1.0 |
| **side** | Which size of the mesh will render the water | FrontSide |
37 changes: 37 additions & 0 deletions playground/src/pages/staging/OceanDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls, Ocean, Sky } from '@tresjs/cientos'
import { SRGBColorSpace, ACESFilmicToneMapping, Vector3 } from 'three'
const gl = {
clearColor: '#333',
outputColorSpace: SRGBColorSpace,
toneMapping: ACESFilmicToneMapping,
toneMappingExposure: 1,
}
</script>

<template>
<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera :position="[0, 0, 15]" />
<TresDirectionalLight :position="[0, 0, 1]" />
<Sky :azimuth="0" />
<Suspense>
<Ocean>
<TresCircleGeometry :args="[50, 16]" />
</Ocean>
</Suspense>
<TresMesh :position-y="1">
<TresBoxGeometry :args="[1, 1, 1]" />
</TresMesh>
<OrbitControls
:enable-pan="false"
:enable-zoom="false"
:max-polar-angle="Math.PI * 0.495"
:min-distance="40.0"
:max-distance="200.0"
/>
</TresCanvas>
</template>
6 changes: 5 additions & 1 deletion playground/src/router/routes/staging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const stagingRoutes = [
name: 'Stars',
component: () => import('../../pages/staging/StarsDemo.vue'),
},

{
path: '/staging/environment',
name: 'Environment',
Expand All @@ -40,4 +39,9 @@ export const stagingRoutes = [
name: 'Sparkles',
component: () => import('../../pages/staging/SparklesDemo.vue'),
},
{
path: '/staging/ocean',
name: 'Ocean',
component: () => import('../../pages/staging/OceanDemo.vue'),
},
]
195 changes: 195 additions & 0 deletions src/core/staging/Ocean.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<script lang="ts" setup>
import { shallowRef, toRefs, onMounted, nextTick } from 'vue'
import { useTresContext, useRenderLoop, useTexture } from '@tresjs/core'
import type { TresColor, TresVector3 } from '@tresjs/core'
import { Water } from 'three/addons/objects/Water.js'
import { Vector3, RepeatWrapping, FrontSide } from 'three'
import type { Texture } from 'three'
import type { Sky } from 'three/addons/objects/Sky.js'
export interface OceanProps {
/**
* The textureWidth of the internal WebGLRenderTarget.
*
* @default 512
* @type {number}
* @memberof OceanProps
*
*/
textureWidth?: number
/**
* The textureHeight of the internal WebGLRenderTarget.
*
* @default 512
* @type {number}
* @memberof OceanProps
*
*/
textureHeight?: number
/**
* The normal texture of the ocean.
* @default 'https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/water/Water_1_M_Normal.jpg'
* @type {string}
* @memberof OceanProps
* @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial
*/
waterNormals?: string
/**
* The sun direction
* @default '[0,0,0]'
* @type {TresVector3}
* @memberof OceanProps
*/
sunDirection?: TresVector3
/**
* The sun color.
*
* @default '#fff'
* @type {TresColor}
* @memberof OceanProps
*
*/
sunColor?: TresColor
/**
* The water color.
*
* @default '#001e0f'
* @type {TresColor}
* @memberof OceanProps
*
*/
waterColor?: TresColor
/**
* The distortion scale of the reflections.
* @default 3.7
* @type {number}
* @memberof OceanProps
*
*/
distortionScale?: number
/**
* The size of the normal texture.
*
* @default 1
* @type {number}
* @memberof OceanProps
*
*/
size?: number
/**
* The ClipBias.
*
* @default 0.0
* @type {number}
* @memberof OceanProps
*
*/
clipBias?: number
/**
* The alpha factor.
*
* @default 1.0
* @type {number}
* @memberof OceanProps
*
*/
alpha?: number
/**
* ThreeJs side material property.
*
* @default FrontSide
* @type {TresVector3}
* @memberof OceanProps
*
*/
side?: TresVector3
}
const props = withDefaults(defineProps<OceanProps>(), {
textureWidth: 512,
textureHeight: 512,
waterNormals: 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/water-normals/Water_1_M_Normal.jpg',
sunDirection: () => new Vector3(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 3.7,
size: 1,
clipBias: 0.0,
alpha: 1.0,
side: FrontSide,
})
const { textureWidth,
textureHeight,
waterNormals,
sunDirection,
sunColor,
waterColor,
distortionScale,
size,
clipBias,
alpha,
side,
} = toRefs(props)
const { extend, scene } = useTresContext()
extend({ Water })
const waterRef = shallowRef()
const sunRef = shallowRef()
const _fog = scene.value.fog !== undefined
defineExpose({
root: waterRef,
})
scene.value.traverse((child) => {
if (child.hasOwnProperty('isSky')) {
sunRef.value = child as Sky
}
})
onMounted(async () => {
await nextTick()
if (sunRef.value) {
const sunPosition = sunRef.value.material.uniforms.sunPosition.value
waterRef.value.material.uniforms.sunDirection.value.copy(sunPosition)
}
})
const { normalMap } = (await useTexture({ normalMap: waterNormals.value })) as { normalMap: Texture }
normalMap.wrapS = normalMap.wrapT = RepeatWrapping
const { onLoop } = useRenderLoop()
onLoop(({ delta }) => {
waterRef.value.material.uniforms.time.value += delta
})
</script>

<template>
<TresWater
ref="waterRef"
:rotation-x="-Math.PI / 2"
:args="[undefined, {
textureWidth,
textureHeight,
waterNormals: normalMap,
sunDirection,
sunColor,
waterColor,
distortionScale,
fog: _fog,
size,
clipBias,
alpha,
side,
}]"
>
<slot>
<TresPlaneGeometry :args="[10000, 10000]" />
</slot>
</TresWater>
</template>
9 changes: 8 additions & 1 deletion src/core/staging/Sky.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// eslint-disable-file vue/attribute-hyphenation
import { MathUtils, Vector3 } from 'three'
import { Sky as SkyImpl } from 'three/examples/jsm/objects/Sky'
import { computed } from 'vue'
import { computed, shallowRef } from 'vue'
export interface SkyProps {
/**
Expand Down Expand Up @@ -46,6 +46,7 @@ const props = withDefaults(defineProps<SkyProps>(), {
distance: 450000,
})
const skyRef = shallowRef<SkyImpl>()
const skyImpl = new SkyImpl()
const sunPosition = computed(() =>
getSunPosition(props.azimuth, props.elevation),
Expand All @@ -56,10 +57,16 @@ function getSunPosition(azimuth: number, elevation: number) {
const theta = MathUtils.degToRad(azimuth)
return new Vector3().setFromSphericalCoords(1, phi, theta)
}
defineExpose({
root: skyRef,
sunPosition: sunPosition.value,
})
</script>

<template>
<primitive
ref="skyRef"
:object="skyImpl"
:material-uniforms-turbidity-value="props.turbidity"
:material-uniforms-rayleigh-value="props.rayleigh"
Expand Down
2 changes: 2 additions & 0 deletions src/core/staging/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Sky from './Sky.vue'
import Smoke from './Smoke.vue'
import Sparkles from './Sparkles/component.vue'
import Stars from './Stars.vue'
import Ocean from './Ocean.vue'

export {
Backdrop,
Expand All @@ -16,4 +17,5 @@ export {
Smoke,
Sparkles,
Stars,
Ocean,
}

0 comments on commit 55ca2bf

Please sign in to comment.