Skip to content

Commit ab9c8a0

Browse files
feat: tilt shift effect (#160)
* final doc * lint * update code, doc * update doc and code * update doc and code * update code, props * fix review line-73-75 --------- Co-authored-by: Tino Koch <17991193+Tinoooo@users.noreply.github.com>
1 parent 84cc46a commit ab9c8a0

File tree

9 files changed

+344
-1
lines changed

9 files changed

+344
-1
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export default defineConfig({
6161
{ text: 'Vignette', link: '/guide/pmndrs/vignette' },
6262
{ text: 'Barrel blur', link: '/guide/pmndrs/barrel-blur' },
6363
{ text: 'Hue & Saturation', link: '/guide/pmndrs/hue-saturation' },
64+
{ text: 'Tilt Shift', link: '/guide/pmndrs/tilt-shift' },
6465
{ text: 'Dot Screen', link: '/guide/pmndrs/dot-screen' },
6566
],
6667
},
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<script setup lang="ts">
2+
import { Environment, OrbitControls } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { EffectComposerPmndrs, TiltShiftPmndrs } from '@tresjs/post-processing'
6+
import { BlendFunction } from 'postprocessing'
7+
import { NoToneMapping } from 'three'
8+
9+
import '@tresjs/leches/styles'
10+
11+
const gl = {
12+
toneMapping: NoToneMapping,
13+
multisampling: 8,
14+
}
15+
16+
const colors = [
17+
'#FF5733',
18+
'#33FF57',
19+
'#3357FF',
20+
'#FF33A1',
21+
'#33FFF5',
22+
'#FF5733',
23+
'#FF8D33',
24+
]
25+
26+
const { blendFunction, offset, rotation, focusArea, feather } = useControls({
27+
blendFunction: {
28+
options: Object.keys(BlendFunction).map(key => ({
29+
text: key,
30+
value: BlendFunction[key],
31+
})),
32+
value: BlendFunction.NORMAL,
33+
},
34+
offset: { value: 0.0, min: -0.5, max: 0.5, step: 0.01 },
35+
rotation: { value: 0.0, min: -Math.PI, max: Math.PI, step: 0.01 },
36+
focusArea: { value: 0.7, min: 0, max: 1, step: 0.01 },
37+
feather: { value: 0.1, min: 0, max: 1, step: 0.01 },
38+
})
39+
</script>
40+
41+
<template>
42+
<TresLeches style="left: initial;right:10px; top:10px;" />
43+
44+
<TresCanvas v-bind="gl">
45+
<TresPerspectiveCamera :position="[0, 4, 8]" />
46+
<OrbitControls auto-rotate />
47+
48+
<template v-for="index in 50" :key="index">
49+
<TresMesh :position="[(index % 10) * 3 - 13.5, 0, Math.floor(index / 10) * 3 - 7.5]" :scale="[2, Math.random() * 5 + 2, 2]">
50+
<TresBoxGeometry :args="[1, 1, 1]" />
51+
<TresMeshPhysicalMaterial
52+
:color="colors[index % colors.length]"
53+
:roughness="0.35"
54+
:metalness="0.5"
55+
:clearcoat="0.3"
56+
:clearcoatRoughness="0.25"
57+
/>
58+
</TresMesh>
59+
</template>
60+
61+
<Suspense>
62+
<Environment background :blur=".35" preset="snow" />
63+
</Suspense>
64+
65+
<Suspense>
66+
<EffectComposerPmndrs>
67+
<TiltShiftPmndrs
68+
:blendFunction="Number(blendFunction.value)"
69+
:offset="offset.value"
70+
:rotation="rotation.value"
71+
:focusArea="focusArea.value"
72+
:feather="feather.value"
73+
/>
74+
</EffectComposerPmndrs>
75+
</Suspense>
76+
77+
<TresGridHelper :position="[0, -3.5, 0]" :args="[30, 15]" />
78+
</TresCanvas>
79+
</template>

docs/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ declare module 'vue' {
2828
ScanlineDemo: typeof import('./.vitepress/theme/components/pmdrs/ScanlineDemo.vue')['default']
2929
SepiaDemo: typeof import('./.vitepress/theme/components/pmdrs/SepiaDemo.vue')['default']
3030
SMAAThreeDemo: typeof import('./.vitepress/theme/components/three/SMAAThreeDemo.vue')['default']
31+
TiltShiftDemo: typeof import('./.vitepress/theme/components/pmdrs/TiltShiftDemo.vue')['default']
3132
ToneMappingDemo: typeof import('./.vitepress/theme/components/pmdrs/ToneMappingDemo.vue')['default']
3233
UnrealBloomThreeDemo: typeof import('./.vitepress/theme/components/three/UnrealBloomThreeDemo.vue')['default']
3334
VignetteDemo: typeof import('./.vitepress/theme/components/pmdrs/VignetteDemo.vue')['default']

docs/guide/pmndrs/tilt-shift.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Tilt Shift
2+
3+
<DocsDemo>
4+
<TiltShiftDemo />
5+
</DocsDemo>
6+
7+
The `TiltShift` effect is part of the [`postprocessing`](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/TiltShiftEffect.js~TiltShiftEffect.html) package. It allows you to create a tilt-shift effect, simulating a shallow depth of field.
8+
9+
## Usage
10+
11+
The `<TiltShiftPmndrs>` component is straightforward to use and provides customizable options to fine-tune the tilt-shift effect.
12+
13+
```vue{3,21-24,49-53}
14+
<script setup lang="ts">
15+
import { Environment, OrbitControls } from '@tresjs/cientos'
16+
import { EffectComposerPmndrs, TiltShiftPmndrs } from '@tresjs/post-processing'
17+
import { NoToneMapping } from 'three'
18+
19+
const colors = [
20+
'#FF5733',
21+
'#33FF57',
22+
'#3357FF',
23+
'#FF33A1',
24+
'#33FFF5',
25+
'#FF5733',
26+
'#FF8D33',
27+
]
28+
29+
const gl = {
30+
toneMapping: NoToneMapping,
31+
multisampling: 8,
32+
}
33+
34+
const effectProps = {
35+
focusArea: 0.7,
36+
feather: 0.1,
37+
}
38+
</script>
39+
40+
<template>
41+
<TresCanvas v-bind="gl">
42+
<TresPerspectiveCamera :position="[0, 4, 8]" />
43+
<OrbitControls auto-rotate />
44+
45+
<template v-for="index in 50" :key="index">
46+
<TresMesh :position="[(index % 10) * 3 - 13.5, 0, Math.floor(index / 10) * 3 - 7.5]" :scale="[2, Math.random() * 5 + 2, 2]">
47+
<TresBoxGeometry :args="[1, 1, 1]" />
48+
<TresMeshPhysicalMaterial
49+
:color="colors[index % colors.length]"
50+
:roughness="0.35"
51+
:metalness="0.5"
52+
:clearcoat="0.3"
53+
:clearcoatRoughness="0.25"
54+
/>
55+
</TresMesh>
56+
</template>
57+
58+
<Suspense>
59+
<Environment background :blur=".35" preset="snow" />
60+
</Suspense>
61+
62+
<Suspense>
63+
<EffectComposerPmndrs>
64+
<TiltShiftPmndrs v-bind="effectProps" />
65+
</EffectComposerPmndrs>
66+
</Suspense>
67+
68+
<TresGridHelper :position="[0, -3.5, 0]" :args="[30, 15]" />
69+
</TresCanvas>
70+
</template>
71+
```
72+
73+
## Props
74+
75+
| Prop | Description | Default |
76+
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
77+
| **blendFunction** | Defines how the effect blends with the original scene. <br> See the [`BlendFunction`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-BlendFunction) options. | `BlendFunction.NORMAL` |
78+
| **offset** | The relative offset of the focus area. A positive value shifts the focus area upwards, while a negative value shifts it downwards. <br> Range: `[-0.5, 0.5]`. | `0.0` |
79+
| **rotation** | The rotation of the focus area in radians. A positive rotation turns the focus area clockwise, while a negative rotation turns it counterclockwise. <br> Range: `[-π, π]`. | `0.0` |
80+
| **focusArea** | The relative size of the focus area. A higher value increases the size of the focus area, while a lower value reduces it. <br> Range: `[0, 1]`. | `0.4` |
81+
| **feather** | The softness of the focus area edges. A higher value makes the edges softer, while a lower value makes them sharper. <br> Range: `[0, 1]`. | `0.3` |
82+
| **kernelSize** | The blur kernel size. A larger kernel size produces a more pronounced blur. <br> See the [`KernelSize`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-KernelSize) options. | `KernelSize.MEDIUM` |
83+
| **resolutionScale** | The resolution scale. A higher value increases the effect's resolution, while a lower value reduces it, affecting quality and performance. <br> Range: `[0.1, 1]`. | `0.5` |
84+
| **resolutionX** | The horizontal resolution. Use `Resolution.AUTO_SIZE` for automatic sizing based on the scene's resolution. | `Resolution.AUTO_SIZE` |
85+
| **resolutionY** | The vertical resolution. Use `Resolution.AUTO_SIZE` for automatic sizing based on the scene's resolution. | `Resolution.AUTO_SIZE` |
86+
87+
## Further Reading
88+
89+
For more details, see the [TiltShift documentation](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/TiltShiftEffect.js~TiltShiftEffect.html).
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<script setup lang="ts">
2+
import { Environment, OrbitControls } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { EffectComposerPmndrs, TiltShiftPmndrs } from '@tresjs/post-processing'
6+
import { BlendFunction, KernelSize, Resolution } from 'postprocessing'
7+
import { NoToneMapping } from 'three'
8+
9+
import '@tresjs/leches/styles'
10+
11+
const gl = {
12+
toneMapping: NoToneMapping,
13+
multisampling: 8,
14+
}
15+
16+
const { blendFunction, offset, rotation, focusArea, feather, kernelSize, resolutionScale, resolutionX, resolutionY } = useControls({
17+
blendFunction: {
18+
options: Object.keys(BlendFunction).map(key => ({
19+
text: key,
20+
value: BlendFunction[key],
21+
})),
22+
value: BlendFunction.NORMAL,
23+
},
24+
offset: { value: 0.0, min: -0.5, max: 0.5, step: 0.01 },
25+
rotation: { value: 0.0, min: -Math.PI, max: Math.PI, step: 0.01 },
26+
focusArea: { value: 0.4, min: 0, max: 1, step: 0.01 },
27+
feather: { value: 0.3, min: 0, max: 1, step: 0.01 },
28+
kernelSize: {
29+
options: Object.keys(KernelSize).map(key => ({
30+
text: key,
31+
value: KernelSize[key],
32+
})),
33+
value: KernelSize.MEDIUM,
34+
},
35+
resolutionScale: { value: 0.5, min: 0.1, max: 1, step: 0.1 },
36+
resolutionX: { value: Resolution.AUTO_SIZE, min: 0, max: 2048, step: 1 },
37+
resolutionY: { value: Resolution.AUTO_SIZE, min: 0, max: 2048, step: 1 },
38+
})
39+
</script>
40+
41+
<template>
42+
<TresLeches />
43+
44+
<TresCanvas
45+
v-bind="gl"
46+
>
47+
<TresPerspectiveCamera
48+
:position="[5, 5, 6]"
49+
:look-at="[0, 0, 0]"
50+
/>
51+
<OrbitControls auto-rotate />
52+
53+
<TresGridHelper :position="[0, -3, 0]" />
54+
55+
<TresMesh :position="[0, 2, 0]">
56+
<TresBoxGeometry :args="[2, 2, 2]" />
57+
<TresMeshPhysicalMaterial color="#FF5733" :roughness="1" :transmission="0" />
58+
</TresMesh>
59+
60+
<TresMesh :position="[0, 0, 0]">
61+
<TresBoxGeometry :args="[2, 2, 2]" />
62+
<TresMeshPhysicalMaterial color="#33FF57" :roughness="1" :transmission="0" />
63+
</TresMesh>
64+
65+
<TresMesh :position="[0, -2, 0]">
66+
<TresBoxGeometry :args="[2, 2, 2]" />
67+
<TresMeshPhysicalMaterial color="#3357FF" :roughness="1" :transmission="0" />
68+
</TresMesh>
69+
70+
<Suspense>
71+
<Environment background :blur=".25" preset="city" />
72+
</Suspense>
73+
74+
<Suspense>
75+
<EffectComposerPmndrs>
76+
<TiltShiftPmndrs
77+
:blendFunction="Number(blendFunction.value)"
78+
:offset="offset.value"
79+
:rotation="rotation.value"
80+
:focusArea="focusArea.value"
81+
:feather="feather.value"
82+
:kernelSize="Number(kernelSize.value)"
83+
:resolutionScale="resolutionScale.value"
84+
:resolutionX="resolutionX.value"
85+
:resolutionY="resolutionY.value"
86+
/>
87+
</EffectComposerPmndrs>
88+
</Suspense>
89+
</TresCanvas>
90+
</template>

playground/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const postProcessingRoutes = [
3737
makeRoute('Glitch', '📺', false),
3838
makeRoute('Depth of Field', '📷', false),
3939
makeRoute('Hue & Saturation', '📷', false),
40+
makeRoute('Tilt Shift', '🔍', false),
4041
makeRoute('Dot Screen', '🔘', false),
4142
makeRoute('Pixelation', '👾', false),
4243
makeRoute('Bloom', '🌼', false),

src/core/pmndrs/HueSaturationPmndrs.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export interface HueSaturationPmndrsProps {
2121
* The blend function. Defines how the effect blends with the original scene.
2222
*/
2323
blendFunction?: BlendFunction
24-
2524
}
2625
2726
const props = withDefaults(

src/core/pmndrs/TiltShiftPmndrs.vue

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<script lang="ts" setup>
2+
import type { BlendFunction, KernelSize } from 'postprocessing'
3+
import { TiltShiftEffect } from 'postprocessing'
4+
import { makePropWatchers } from '../../util/prop'
5+
import { useEffectPmndrs } from './composables/useEffectPmndrs'
6+
7+
export interface TiltShiftPmndrsProps {
8+
/**
9+
* The blend function. Defines how the effect blends with the original scene.
10+
*/
11+
blendFunction?: BlendFunction
12+
13+
/**
14+
* The relative offset of the focus area.
15+
* Range: [-0.5, 0.5]
16+
*/
17+
offset?: number
18+
19+
/**
20+
* The rotation of the focus area in radians.
21+
* Range: [-π, π]
22+
*/
23+
rotation?: number
24+
25+
/**
26+
* The relative size of the focus area.
27+
* Range: [0, 1]
28+
*/
29+
focusArea?: number
30+
31+
/**
32+
* The softness of the focus area edges.
33+
* Range: [0, 1]
34+
*/
35+
feather?: number
36+
37+
/**
38+
* The blur kernel size.
39+
*/
40+
kernelSize?: KernelSize
41+
42+
/**
43+
* The resolution scale.
44+
* Range: [0.1, 1]
45+
*/
46+
resolutionScale?: number
47+
48+
/**
49+
* The horizontal resolution.
50+
*/
51+
resolutionX?: number
52+
53+
/**
54+
* The vertical resolution.
55+
*/
56+
resolutionY?: number
57+
}
58+
59+
const props = defineProps<TiltShiftPmndrsProps>()
60+
61+
const { pass, effect } = useEffectPmndrs(() => new TiltShiftEffect(props), props)
62+
63+
defineExpose({ pass, effect })
64+
65+
makePropWatchers(
66+
[
67+
[() => props.blendFunction, 'blendMode.blendFunction'],
68+
[() => props.offset, 'offset'],
69+
[() => props.rotation, 'rotation'],
70+
[() => props.focusArea, 'focusArea'],
71+
[() => props.feather, 'feather'],
72+
[() => props.kernelSize, 'kernelSize'],
73+
[() => props.resolutionScale, 'resolution.scale'],
74+
[() => props.resolutionX, 'resolution.width'],
75+
[() => props.resolutionY, 'resolution.height'],
76+
],
77+
effect,
78+
() => new TiltShiftEffect(),
79+
)
80+
</script>

src/core/pmndrs/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ToneMappingPmndrs, { type ToneMappingPmndrsProps } from './ToneMappingPmn
1414
import ChromaticAberrationPmndrs, { type ChromaticAberrationPmndrsProps } from './ChromaticAberrationPmndrs.vue'
1515
import HueSaturationPmndrs, { type HueSaturationPmndrsProps } from './HueSaturationPmndrs.vue'
1616
import ScanlinePmndrs, { type ScanlinePmndrsProps } from './ScanlinePmndrs.vue'
17+
import TiltShiftPmndrs, { type TiltShiftPmndrsProps } from './TiltShiftPmndrs.vue'
1718
import DotScreenPmndrs, { type DotScreenPmndrsProps } from './DotScreenPmndrs.vue'
1819
import SepiaPmndrs, { type SepiaPmndrsProps } from './SepiaPmndrs.vue'
1920

@@ -34,6 +35,7 @@ export {
3435
ChromaticAberrationPmndrs,
3536
HueSaturationPmndrs,
3637
ScanlinePmndrs,
38+
TiltShiftPmndrs,
3739
DotScreenPmndrs,
3840
SepiaPmndrs,
3941

@@ -50,6 +52,7 @@ export {
5052
ChromaticAberrationPmndrsProps,
5153
HueSaturationPmndrsProps,
5254
ScanlinePmndrsProps,
55+
TiltShiftPmndrsProps,
5356
DotScreenPmndrsProps,
5457
SepiaPmndrsProps,
5558
}

0 commit comments

Comments
 (0)