Skip to content

Commit

Permalink
feat: add reflector (#136)
Browse files Browse the repository at this point in the history
* feat: add reflector

* docs: add docs for Reflector

* chore: details on component

* chore: update reflector position, no reactive props yet

* chore: broke component

* chore: fix routes

* chore: internal refactor

* docs: update docs, props no reactive

* chore: remove unnecessary undefined

* chore: componets.d.ts?

* docs: update docs

* chore: change import from addons to examples

* chore: remove comments in demo

* docs: add demo to docs
  • Loading branch information
JaimeTorrealba authored Nov 14, 2023
1 parent c7d8fa0 commit bd4d710
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default defineConfig({
{ text: 'useAnimations', link: '/guide/abstractions/use-animations' },
{ text: 'MouseParallax', link: '/guide/abstractions/mouse-parallax' },
{ text: 'Lensflare', link: '/guide/abstractions/lensflare' },
{ text: 'Reflector', link: '/guide/abstractions/reflector' },
{ text: 'GlobalAudio', link: '/guide/abstractions/global-audio' },
{ text: 'Fbo', link: '/guide/abstractions/fbo' },
{ text: 'useFBO', link: '/guide/abstractions/use-fbo' },
Expand Down
36 changes: 36 additions & 0 deletions docs/.vitepress/theme/components/ReflectorDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import {
OrbitControls,
MeshWobbleMaterial,
Reflector,
Stars,
} from '@tresjs/cientos'
</script>

<template>
<TresCanvas clear-color="#111">
<TresPerspectiveCamera
:position="[3, 2, 6]"
:look-at="[0, 0, 0]"
/>
<Stars />
<TresMesh>
<TresTorusGeometry />
<MeshWobbleMaterial
color="orange"
:speed="1"
:factor="2"
/>
</TresMesh>
<Reflector
:rotation="[-Math.PI * 0.5, 0, 0]"
:position="[0, -2, 0]"
color="#f7f7f7"
>
<TresCircleGeometry :args="[10, 32]" />
</Reflector>
<TresAmbientLight :intensity="1" />
<OrbitControls />
</TresCanvas>
</template>
123 changes: 123 additions & 0 deletions docs/guide/abstractions/reflector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Reflector

<DocsDemo>
<ReflectorDemo />
</DocsDemo>

The `cientos` package provides an abstraction of the [Reflector class](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/objects/Reflector.js), which creates a Mesh showing a real-time reflection of your scene. This Mesh extends from `Mesh` so all the default props can be passed as well:

## Usage

<<< @/.vitepress/theme/components/ReflectorDemo.vue{6,26-32}

## Props

| Prop | Description | Default |
| :---------------- | :--------------------------------------------------- | ------------------------- |
| **color** | The base color that's combine with the mirror effect | '#333' |
| **textureWidth** | the width of the texture to render on the mirror | 512 |
| **textureHeight** | the height of the texture to render on the mirror | 512 |
| **clipBias** | to use the clipBias property | 0 |
| **multisample** | how many samplers will be render | 4 |
| **shader** | The texture of the smoke. | Reflector.ReflectorShader |

::: warning
All the props except the `color`, are not reactive
:::

## Custom mirror effect

For more complex effect you can provide your own shaders, you could do this creating an object and pass the uniforms, vertexShaders or fragmentShaders:

```vue{2,4-6,15}
<script setup lang="ts" >
import vertexShader from "MyCustomVertexShader.glsl"
const customShader = {
vertexShader
}
<script>
<template>
<TresCanvas shadows alpha>
<TresPerspectiveCamera :position="[0, 0, 3]" />
...
<Reflector :rotation="[-Math.PI * 0.5, 0, 0]"
:position-y="-2"
color="#fff"
:shader="customShader"
>
<TresCircleGeometry :args="[10, 10]" />
</Reflector>
...
</TresCanvas>
</template>
```
The Reflector shader use the following configuration by default:

You can extend, modify or just play with them

### Default shader

```js
{
name:'ReflectorShader',
uniforms: {
color: {
value: null
},
tDiffuse: {
value: null
},
textureMatrix: {
value: null
}
},
vertexShader: /* glsl */`
uniform mat4 textureMatrix;
varying vec4 vUv;
#include <common>
#include <logdepthbuf_pars_vertex>
void main() {
vUv = textureMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
#include <logdepthbuf_vertex>
}`,
fragmentShader: /* glsl */`
uniform vec3 color;
uniform sampler2D tDiffuse;
varying vec4 vUv;
#include <logdepthbuf_pars_fragment>
float blendOverlay( float base, float blend ) {
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
}
vec3 blendOverlay( vec3 base, vec3 blend ) {
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
}
void main() {
#include <logdepthbuf_fragment>
vec4 base = texture2DProj( tDiffuse, vUv );
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`

}
```
64 changes: 64 additions & 0 deletions playground/src/pages/abstractions/ReflectorMeshDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<script setup lang="ts">
import { shallowRef, watch } from 'vue'
import { TresCanvas } from '@tresjs/core'
import {
OrbitControls,
MeshWobbleMaterial,
Reflector,
Stars,
} from '@tresjs/cientos'
import { BasicShadowMap, SRGBColorSpace, NoToneMapping, PlaneGeometry } from 'three'
const gl = {
clearColor: '#111',
shadows: false,
alpha: false,
shadowMapType: BasicShadowMap,
outputColorSpace: SRGBColorSpace,
toneMapping: NoToneMapping,
}
const reflectorRef = shallowRef()
watch(reflectorRef, (value) => {
console.log(value)
})
const options = {
color: '#f7f7f7',
clipBias: 0,
textureWidth: 1024,
textureHeight: 1024,
}
</script>

<template>
<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera
:position="[3, 3, 6]"
:look-at="[0, 0, 0]"
/>
<Stars />
<TresMesh>
<TresTorusGeometry />
<MeshWobbleMaterial
color="orange"
:speed="1"
:factor="2"
/>
</TresMesh>
<Reflector
ref="reflectorRef"
:rotation="[-Math.PI * 0.5, 0, 0]"
:position="[0, -2, 0]"
:color="options.color"
:clip-bias="options.clipBias"
:texture-width="options.textureWidth"
:texture-height="options.textureHeight"
/>
<TresAmbientLight :intensity="1" />
<OrbitControls />
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/src/router/routes/abstractions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const abstractionsRoutes = [
name: 'Lensflare',
component: () => import('../../pages/abstractions/LensflareDemo.vue'),
},
{
path: '/abstractions/reflector-mesh',
name: 'ReflectorMeshDemo',
component: () => import('../../pages/abstractions/ReflectorMeshDemo.vue'),
},
{
path: '/abstractions/global-audio',
name: 'GlobalAudio',
Expand Down
97 changes: 97 additions & 0 deletions src/core/abstractions/Reflector.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script lang="ts" setup>
import { shallowRef, toRefs } from 'vue'
import { useTresContext } from '@tresjs/core'
import type { TresColor } from '@tresjs/core'
import { Reflector } from 'three/examples/jsm/objects/Reflector.js'
export interface ReflectorProps {
/**
* The color of the reflector.
*
* @default '#333'
* @type {TresColor}
* @memberof ReflectorProps
*
*/
color?: TresColor
/**
* The textureWidth of the internal WebGLRenderTarget.
*
* @default window.innerWidth
* @type {number}
* @memberof ReflectorProps
*
*/
textureWidth?: number
/**
* The textureHeight of the internal WebGLRenderTarget.
*
* @default window.innerHeight
* @type {number}
* @memberof ReflectorProps
*
*/
textureHeight?: number
/**
* The clipBias.
*
* @default 0
* @type {number}
* @memberof ReflectorProps
*
*/
clipBias?: number
/**
* The multisample.
*
* @default 4
* @type {number}
* @memberof ReflectorProps
*
*/
multisample?: number
/**
* Custom shader.
*
* @default Reflector.ReflectorShader
* @type {object}
* @memberof ReflectorProps
*
*/
shader?: object
}
const props = withDefaults(defineProps<ReflectorProps>(), {
color: '#333',
textureWidth: 512,
textureHeight: 512,
clipBias: 0,
multisample: 4,
shader: Reflector.ReflectorShader,
})
const { extend } = useTresContext()
const reflectorRef = shallowRef<Reflector>()
extend({ Reflector })
const { color, textureWidth, textureHeight, clipBias, multisample, shader }
= toRefs(props)
defineExpose({
reflectorRef,
})
</script>

<template>
<TresReflector
ref="reflectorRef"
:args="[undefined, { textureWidth, textureHeight, clipBias, multisample, shader }]"
:material-uniforms-color-value="color"
>
<slot>
<TresPlaneGeometry :args="[5, 5]" />
</slot>
</TresReflector>
</template>
2 changes: 2 additions & 0 deletions src/core/abstractions/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Text3D from './Text3D.vue'
import { useAnimations } from './useAnimations'
import Levioso from './Levioso.vue'
import Reflector from './Reflector.vue'
import MouseParallax from './MouseParallax.vue'
import { GlobalAudio } from './GlobalAudio'
import Lensflare from './Lensflare/component.vue'
Expand All @@ -13,6 +14,7 @@ export {
useAnimations,
MouseParallax,
Levioso,
Reflector,
Lensflare,
GlobalAudio,
Fbo,
Expand Down

0 comments on commit bd4d710

Please sign in to comment.