Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add reflector #136

Merged
merged 20 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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