Skip to content

Commit 0a89733

Browse files
feat: SMAA (#199)
* init smaa effect source * ad doc and modify source effect * dix: add commentary for props * added workaround for type issue * updated debug mode handling and improve type safety --------- Co-authored-by: Tino Koch <>
1 parent fba8b58 commit 0a89733

File tree

8 files changed

+605
-0
lines changed

8 files changed

+605
-0
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export default defineConfig({
6262
{ text: 'Lens Distortion', link: '/guide/pmndrs/lens-distortion' },
6363
{ text: 'Grid', link: '/guide/pmndrs/grid' },
6464
{ text: 'FXAA', link: '/guide/pmndrs/fxaa' },
65+
{ text: 'SMAA', link: '/guide/pmndrs/smaa' },
6566
{ text: 'Kuwahara', link: '/guide/pmndrs/kuwahara' },
6667
{ text: 'Color Average', link: '/guide/pmndrs/color-average' },
6768
{ text: 'Depth of Field', link: '/guide/pmndrs/depth-of-field' },
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<script setup lang="ts">
2+
import { OrbitControls } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { NoToneMapping } from 'three'
6+
import { BlendFunction, EdgeDetectionMode, PredicationMode, SMAAPreset } from 'postprocessing'
7+
import { EffectComposerPmndrs, SMAAPmndrs } from '@tresjs/post-processing'
8+
import type { PerspectiveCamera } from 'three'
9+
import { ref } from 'vue'
10+
11+
import '@tresjs/leches/styles'
12+
13+
const gl = {
14+
antialias: false,
15+
clearColor: '#FC7BAC',
16+
toneMapping: NoToneMapping,
17+
}
18+
19+
const { blendFunction, debug, autoRotateSpeed, opacity, preset, wireframe, boxColor, predicationMode, edgeDetectionMode } = useControls({
20+
blendFunction: {
21+
options: Object.keys(BlendFunction).map(key => ({
22+
text: key,
23+
value: BlendFunction[key as keyof typeof BlendFunction],
24+
})),
25+
value: BlendFunction.NORMAL,
26+
},
27+
debug: {
28+
options: [
29+
{ text: 'OFF', value: 0 },
30+
{ text: 'EDGES', value: 1 },
31+
{ text: 'WEIGHTS', value: 2 },
32+
],
33+
value: 0,
34+
},
35+
preset: {
36+
options: Object.keys(SMAAPreset).map(key => ({
37+
text: key,
38+
value: SMAAPreset[key as keyof typeof SMAAPreset],
39+
})),
40+
value: SMAAPreset.HIGH,
41+
},
42+
predicationMode: {
43+
options: Object.keys(PredicationMode).map(key => ({
44+
text: key,
45+
value: PredicationMode[key as keyof typeof PredicationMode],
46+
})),
47+
value: PredicationMode.DISABLED,
48+
},
49+
edgeDetectionMode: {
50+
options: Object.keys(EdgeDetectionMode).map(key => ({
51+
text: key,
52+
value: EdgeDetectionMode[key as keyof typeof EdgeDetectionMode],
53+
})),
54+
value: EdgeDetectionMode.COLOR,
55+
},
56+
boxColor: '#ffffff',
57+
wireframe: false,
58+
opacity: {
59+
value: 1,
60+
min: 0,
61+
max: 1,
62+
step: 0.01,
63+
},
64+
autoRotateSpeed: {
65+
value: 0.5,
66+
min: 0,
67+
max: 10,
68+
step: 0.1,
69+
},
70+
})
71+
72+
const wrapperRef = ref<HTMLElement | undefined>(undefined)
73+
const cameraRef = ref<PerspectiveCamera | null>(null)
74+
75+
const onChange = (e: { object: PerspectiveCamera }) => {
76+
if (!cameraRef.value) { return }
77+
78+
cameraRef.value.position.copy(e.object.position)
79+
cameraRef.value.rotation.copy(e.object.rotation)
80+
cameraRef.value.zoom = e.object.zoom
81+
cameraRef.value.quaternion.copy(e.object.quaternion)
82+
}
83+
</script>
84+
85+
<template>
86+
<div ref="wrapperRef" class="aspect-16/9 relative h-full">
87+
<TresCanvas
88+
v-bind="gl"
89+
class="doc-smaa-canvas-left"
90+
>
91+
<TresPerspectiveCamera :position="[0, 2, 3.5]" />
92+
<OrbitControls :domElement="wrapperRef" auto-rotate :auto-rotate-speed="autoRotateSpeed" :target="[0, 0.25, 0]" @change="onChange" />
93+
94+
<TresMesh :position="[0, .5, 0]">
95+
<TresBoxGeometry :args="[2, 2, 2]" />
96+
<TresMeshBasicMaterial :color="boxColor" :wireframe="wireframe" />
97+
</TresMesh>
98+
</TresCanvas>
99+
100+
<div class="doc-smaa-divider"></div>
101+
102+
<TresCanvas
103+
v-bind="gl"
104+
class="doc-smaa-canvas-right"
105+
>
106+
<TresPerspectiveCamera ref="cameraRef" :position="[0, 2, 3.5]" />
107+
108+
<TresMesh :position="[0, .5, 0]">
109+
<TresBoxGeometry :args="[2, 2, 2]" />
110+
<TresMeshBasicMaterial :color="boxColor" :wireframe="wireframe" />
111+
</TresMesh>
112+
113+
<Suspense>
114+
<EffectComposerPmndrs>
115+
<SMAAPmndrs
116+
:debug="Number(debug)"
117+
:blendFunction="blendFunction"
118+
:opacity="opacity"
119+
:preset="preset"
120+
:predicationMode="predicationMode"
121+
:edgeDetectionMode="edgeDetectionMode"
122+
/>
123+
</EffectComposerPmndrs>
124+
</Suspense>
125+
</TresCanvas>
126+
127+
<p class="doc-smaa-info doc-smaa-info-left text-xs font-semibold">⬅️ No SMAA</p>
128+
<p class="doc-smaa-info doc-smaa-info-right text-xs font-semibold">With SMAA ➡️</p>
129+
</div>
130+
131+
<TresLeches :float="false" />
132+
</template>
133+
134+
<style scoped>
135+
.doc-smaa-canvas-left {
136+
position: absolute !important;
137+
inset: 0;
138+
z-index: 1;
139+
clip-path: inset(0 50% 0 0);
140+
-webkit-clip-path: inset(0 50% 0 0);
141+
}
142+
143+
.doc-smaa-canvas-right {
144+
position: absolute !important;
145+
inset: 0;
146+
z-index: 2;
147+
pointer-events: none;
148+
clip-path: inset(0 0 0 50%);
149+
-webkit-clip-path: inset(0 0 0 50%);
150+
}
151+
152+
.doc-smaa-divider {
153+
position: absolute;
154+
top: 0;
155+
bottom: 0;
156+
left: 50%;
157+
width: 2px;
158+
background: red;
159+
z-index: 3;
160+
pointer-events: none;
161+
}
162+
163+
.doc-smaa-info {
164+
position: absolute;
165+
bottom: 0;
166+
padding: 0.45rem 0.75rem;
167+
margin: 0;
168+
text-align: center;
169+
color: #fff;
170+
z-index: 2;
171+
background: linear-gradient(90deg, #ff2277 0%, #fdb1c8 100%);
172+
}
173+
174+
.doc-smaa-info-left {
175+
left: 0;
176+
border-radius: 0px 10px 0px 0px;
177+
}
178+
179+
.doc-smaa-info-right {
180+
right: 0;
181+
border-radius: 10px 0px 0px 0px;
182+
}
183+
</style>

docs/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ declare module 'vue' {
4040
ScanlineDemo: typeof import('./.vitepress/theme/components/pmdrs/ScanlineDemo.vue')['default']
4141
SepiaDemo: typeof import('./.vitepress/theme/components/pmdrs/SepiaDemo.vue')['default']
4242
ShockWaveDemo: typeof import('./.vitepress/theme/components/pmdrs/ShockWaveDemo.vue')['default']
43+
SMAADemo: typeof import('./.vitepress/theme/components/pmdrs/SMAADemo.vue')['default']
4344
SMAAThreeDemo: typeof import('./.vitepress/theme/components/three/SMAAThreeDemo.vue')['default']
4445
TiltShiftDemo: typeof import('./.vitepress/theme/components/pmdrs/TiltShiftDemo.vue')['default']
4546
ToneMappingDemo: typeof import('./.vitepress/theme/components/pmdrs/ToneMappingDemo.vue')['default']

docs/guide/pmndrs/smaa.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# SMAA
2+
3+
<DocsDemoGUI>
4+
<SMAADemo />
5+
</DocsDemoGUI>
6+
7+
<details>
8+
<summary>Demo code</summary>
9+
10+
<<< @/.vitepress/theme/components/pmdrs/SMAADemo.vue{0}
11+
</details>
12+
13+
The `SMAAEffect` effect is part of the [`postprocessing`](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/SMAAEffect.js~SMAAEffect.html) package. **SMAA** (Subpixel Morphological Antialiasing) is a post-processing antialiasing technique that uses look-up tables to detect edges accurately, preserving texture details while minimizing false positives.
14+
15+
:::info
16+
**SMAA** generally provides superior visual quality compared to [FXAA](/guide/pmndrs/fxaa), though it is slightly less performant. Note that **SMAA** is distinct from **MSAA**.
17+
:::
18+
19+
## Usage
20+
21+
The `<SMAAPmndrs>` component is easy to use and provides customizable options to suit different visual styles.
22+
23+
:::info
24+
When using the `<EffectComposerPmndrs>` pipeline, enabling native antialiasing with the [`antialias`](https://docs.tresjs.org/api/tres-canvas.html#props) props on `<TresCanvas>` is unnecessary.
25+
:::
26+
27+
```vue{2-3,13-15,24-28}
28+
<script setup lang="ts">
29+
import { EffectComposerPmndrs, SMAAPmndrs } from '@tresjs/post-processing/pmndrs'
30+
import type { SMAAPreset } from 'postprocessing'
31+
32+
const gl = {
33+
toneMapping: NoToneMapping,
34+
antialias: false,
35+
}
36+
// It is not required to add `antialias: false` for
37+
// the <TresCanvas> context, as it is automatically
38+
// disabled when using `<EffectComposerPmndrs>`.
39+
40+
const effectProps = {
41+
preset: SMAAPreset.HIGH
42+
}
43+
</script>
44+
45+
<template>
46+
<TresCanvas v-bind="gl">
47+
<TresPerspectiveCamera />
48+
49+
<!-- Your scene -->
50+
51+
<Suspense>
52+
<EffectComposerPmndrs>
53+
<SMAAPmndrs v-bind="effectProps" />
54+
</EffectComposerPmndrs>
55+
</Suspense>
56+
</TresCanvas>
57+
</template>
58+
```
59+
60+
## Props
61+
62+
| Prop | Description | Default |
63+
| ------------- | ------------------------------------------------------------------- | --------------------------- |
64+
| blendFunction | Defines how the effect blends with the original scene. See the [`BlendFunction`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-BlendFunction) options. | `BlendFunction.SRC` |
65+
| opacity | The opacity of the effect. | `1` |
66+
| preset | Define the quality and performance trade-offs. See the [`SMAAPreset`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-SMAAPreset) options. | `SMAAPreset.MEDIUM` |
67+
| edgeDetectionMode | Define the edge detection modes. See the [`EdgeDetectionMode`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-EdgeDetectionMode) options. | `EdgeDetectionMode.COLOR` |
68+
| predicationMode | Define the edge detection modes. See the [`PredicationMode`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-PredicationMode) options. | `PredicationMode.DISABLED` |
69+
| debug | Define the debug mode. <br> Options: <br> - `0` : OFF <br> - `1` : EDGES <br> - `2` : WEIGHTS | `0` (OFF) |
70+
71+
## Further Reading
72+
For more details, see the [SMAAEffect documentation](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/SMAAEffect.js~SMAAEffect.html)

0 commit comments

Comments
 (0)