Skip to content

Commit a0e957c

Browse files
feat: dot screen effect (#167)
* init dot screen * wip demo src * wip demo doc * done doc, code --------- Co-authored-by: Tino Koch <17991193+Tinoooo@users.noreply.github.com>
1 parent 5df6957 commit a0e957c

File tree

8 files changed

+239
-0
lines changed

8 files changed

+239
-0
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export default defineConfig({
5959
{ text: 'Pixelation', link: '/guide/pmndrs/pixelation' },
6060
{ text: 'Vignette', link: '/guide/pmndrs/vignette' },
6161
{ text: 'Hue & Saturation', link: '/guide/pmndrs/hue-saturation' },
62+
{ text: 'Dot Screen', link: '/guide/pmndrs/dot-screen' },
6263
],
6364
},
6465
{
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<script setup lang="ts">
2+
import { ContactShadows, Environment, OrbitControls, useGLTF } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { DotScreenPmndrs, EffectComposerPmndrs } from '@tresjs/post-processing'
6+
7+
import { BlendFunction } from 'postprocessing'
8+
import { NoToneMapping } from 'three'
9+
10+
import '@tresjs/leches/styles'
11+
12+
const gl = {
13+
clearColor: '#ffffff',
14+
toneMapping: NoToneMapping,
15+
multisampling: 8,
16+
}
17+
18+
const { angle, scale, blendFunction } = useControls({
19+
angle: { value: 1.57, min: -Math.PI, max: Math.PI, step: 0.001 },
20+
scale: { value: 1.25, min: 0.1, max: 2.5, step: 0.01 },
21+
blendFunction: {
22+
options: Object.keys(BlendFunction).map(key => ({
23+
text: key,
24+
value: BlendFunction[key],
25+
})),
26+
value: BlendFunction.NORMAL,
27+
},
28+
})
29+
30+
const { scene } = await useGLTF('https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/suzanne/suzanne.glb', { draco: true })
31+
</script>
32+
33+
<template>
34+
<TresLeches style="left: initial;right:10px; top:10px;" />
35+
36+
<TresCanvas
37+
v-bind="gl"
38+
>
39+
<TresPerspectiveCamera
40+
:position="[0, 1, 7.5]"
41+
:look-at="[0, 0, 0]"
42+
/>
43+
<OrbitControls />
44+
45+
<primitive :scale="2" :rotation-x="Math.PI / -5" :rotation-y="Math.PI" :position-y=".25" :position-z="0.5" :object="scene" />
46+
47+
<ContactShadows
48+
:opacity="1"
49+
:position-y="-1.5"
50+
/>
51+
52+
<Suspense>
53+
<Environment preset="modern" />
54+
</Suspense>
55+
56+
<Suspense>
57+
<EffectComposerPmndrs>
58+
<DotScreenPmndrs :blendFunction="Number(blendFunction.value)" :angle="angle.value" :scale="scale.value" />
59+
</EffectComposerPmndrs>
60+
</Suspense>
61+
</TresCanvas>
62+
</template>

docs/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ declare module 'vue' {
1212
ChromaticAberrationDemo: typeof import('./.vitepress/theme/components/pmdrs/ChromaticAberrationDemo.vue')['default']
1313
DepthOfFieldDemo: typeof import('./.vitepress/theme/components/pmdrs/DepthOfFieldDemo.vue')['default']
1414
DocsDemo: typeof import('./.vitepress/theme/components/DocsDemo.vue')['default']
15+
DotScreenDemo: typeof import('./.vitepress/theme/components/pmdrs/DotScreenDemo.vue')['default']
1516
Ducky: typeof import('./.vitepress/theme/components/Ducky.vue')['default']
1617
GlitchDemo: typeof import('./.vitepress/theme/components/pmdrs/GlitchDemo.vue')['default']
1718
GlitchThreeDemo: typeof import('./.vitepress/theme/components/three/GlitchThreeDemo.vue')['default']

docs/guide/pmndrs/dot-screen.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Dot Screen
2+
3+
<DocsDemo>
4+
<DotScreenDemo />
5+
</DocsDemo>
6+
7+
The `DotScreen` effect is part of the [`postprocessing`](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/DotScreenEffect.js~DotScreenEffect.html) package. It allows you to create a dot screen effect, providing flexibility for artistic effects.
8+
9+
## Usage
10+
11+
The `<DotScreenPmndrs>` component is straightforward to use and provides customizable options to fine-tune the dot screen effect.
12+
13+
```vue{4,13-16,42-46}
14+
<script setup lang="ts">
15+
import { ContactShadows, Environment, OrbitControls, useGLTF } from '@tresjs/cientos'
16+
import { TresCanvas } from '@tresjs/core'
17+
import { DotScreenPmndrs, EffectComposerPmndrs } from '@tresjs/post-processing'
18+
import { NoToneMapping } from 'three'
19+
20+
const gl = {
21+
clearColor: '#ffffff',
22+
toneMapping: NoToneMapping,
23+
multisampling: 8,
24+
}
25+
26+
const effectProps = reactive({
27+
angle: 1.57,
28+
scale: 1.25
29+
})
30+
31+
const { scene } = await useGLTF('https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/suzanne/suzanne.glb', { draco: true })
32+
</script>
33+
34+
<template>
35+
<TresCanvas
36+
v-bind="gl"
37+
>
38+
<TresPerspectiveCamera
39+
:position="[0, 1, 7.5]"
40+
:look-at="[0, 0, 0]"
41+
/>
42+
<OrbitControls />
43+
44+
<primitive :scale="2" :rotation-x="Math.PI / -5" :rotation-y="Math.PI" :position-y=".25" :position-z="0.5" :object="scene" />
45+
46+
<ContactShadows
47+
:opacity="1"
48+
:position-y="-1.5"
49+
/>
50+
51+
<Suspense>
52+
<Environment preset="modern" />
53+
</Suspense>
54+
55+
<Suspense>
56+
<EffectComposerPmndrs>
57+
<DotScreenPmndrs v-bind="effectProps" />
58+
</EffectComposerPmndrs>
59+
</Suspense>
60+
</TresCanvas>
61+
</template>
62+
```
63+
64+
## Props
65+
66+
| Prop | Description | Default |
67+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
68+
| **angle** | The angle of the dot pattern *(in radians)*. | `1.57` |
69+
| **scale** | The scale of the dot pattern. | `1.0` |
70+
| **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.NORMAL` |
71+
72+
## Further Reading
73+
74+
For more details, see the [DotScreen documentation](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/DotScreenEffect.js~DotScreenEffect.html).
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 { DotScreenPmndrs, EffectComposerPmndrs } 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 { angle, scale, blendFunction } = useControls({
17+
angle: { value: 1.57, min: -Math.PI, max: Math.PI, step: 0.001 },
18+
scale: { value: 0.5, min: 0.1, max: 2.5, step: 0.01 },
19+
blendFunction: {
20+
options: Object.keys(BlendFunction).map(key => ({
21+
text: key,
22+
value: BlendFunction[key],
23+
})),
24+
value: BlendFunction.NORMAL,
25+
},
26+
})
27+
</script>
28+
29+
<template>
30+
<TresLeches />
31+
32+
<TresCanvas
33+
v-bind="gl"
34+
>
35+
<TresPerspectiveCamera
36+
:position="[5, 5, 5]"
37+
:look-at="[0, 0, 0]"
38+
/>
39+
<OrbitControls auto-rotate />
40+
41+
<TresMesh :position="[0, 1, 0]">
42+
<TresBoxGeometry :args="[2, 2, 2]" />
43+
<TresMeshPhysicalMaterial color="white" :roughness="1" :transmission="0" />
44+
</TresMesh>
45+
46+
<Suspense>
47+
<Environment background :blur=".1" preset="dawn" />
48+
</Suspense>
49+
50+
<Suspense>
51+
<EffectComposerPmndrs>
52+
<DotScreenPmndrs :blendFunction="Number(blendFunction.value)" :angle="angle.value" :scale="scale.value" />
53+
</EffectComposerPmndrs>
54+
</Suspense>
55+
</TresCanvas>
56+
</template>

playground/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const postProcessingRoutes = [
3636
makeRoute('Glitch', '📺', false),
3737
makeRoute('Depth of Field', '📷', false),
3838
makeRoute('Hue & Saturation', '📷', false),
39+
makeRoute('Dot Screen', '🔘', false),
3940
makeRoute('Pixelation', '👾', false),
4041
makeRoute('Bloom', '🌼', false),
4142
makeRoute('Noise', '📟', false),

src/core/pmndrs/DotScreenPmndrs.vue

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<script lang="ts" setup>
2+
import type { BlendFunction } from 'postprocessing'
3+
import { DotScreenEffect } from 'postprocessing'
4+
import { makePropWatchers } from '../../util/prop'
5+
import { useEffectPmndrs } from './composables/useEffectPmndrs'
6+
7+
export interface DotScreenPmndrsProps {
8+
/**
9+
* The angle of the dot pattern.
10+
* Default: 1.57
11+
*/
12+
angle?: number
13+
14+
/**
15+
* The scale of the dot pattern.
16+
* Default: 1.0
17+
*/
18+
scale?: number
19+
20+
/**
21+
* The blend function. Defines how the effect blends with the original scene.
22+
*/
23+
blendFunction?: BlendFunction
24+
}
25+
26+
const props = defineProps<DotScreenPmndrsProps>()
27+
28+
const { pass, effect } = useEffectPmndrs(() => new DotScreenEffect(props), props)
29+
30+
defineExpose({ pass, effect })
31+
32+
makePropWatchers(
33+
[
34+
[() => props.blendFunction, 'blendMode.blendFunction'],
35+
[() => props.angle, 'angle'],
36+
[() => props.scale, 'scale'],
37+
],
38+
effect,
39+
() => new DotScreenEffect(),
40+
)
41+
</script>

src/core/pmndrs/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import VignettePmndrs, { type VignettePmndrsProps } from './VignettePmndrs.vue'
1212
import ChromaticAberrationPmndrs, { type ChromaticAberrationPmndrsProps } from './ChromaticAberrationPmndrs.vue'
1313
import HueSaturationPmndrs, { type HueSaturationPmndrsProps } from './HueSaturationPmndrs.vue'
1414
import ScanlinePmndrs, { type ScanlinePmndrsProps } from './ScanlinePmndrs.vue'
15+
import DotScreenPmndrs, { type DotScreenPmndrsProps } from './DotScreenPmndrs.vue'
1516
import SepiaPmndrs, { type SepiaPmndrsProps } from './SepiaPmndrs.vue'
1617

1718
export {
@@ -27,6 +28,7 @@ export {
2728
ChromaticAberrationPmndrs,
2829
HueSaturationPmndrs,
2930
ScanlinePmndrs,
31+
DotScreenPmndrs,
3032
SepiaPmndrs,
3133

3234
BloomPmndrsProps,
@@ -40,5 +42,6 @@ export {
4042
ChromaticAberrationPmndrsProps,
4143
HueSaturationPmndrsProps,
4244
ScanlinePmndrsProps,
45+
DotScreenPmndrsProps,
4346
SepiaPmndrsProps,
4447
}

0 commit comments

Comments
 (0)