Skip to content

Commit f3da309

Browse files
feat: add scanline (#150)
* add chromatic aberration * add chromatic aberration * add scanline effect * add scanline effect * revert outlineDemo deleted by mistake * Update playground/src/pages/postprocessing/scanline.vue --------- Co-authored-by: Alvaro Saburido <[email protected]>
1 parent 08b97bb commit f3da309

File tree

8 files changed

+252
-4
lines changed

8 files changed

+252
-4
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export default defineConfig({
5353
{ text: 'Glitch', link: '/guide/pmndrs/glitch' },
5454
{ text: 'Noise', link: '/guide/pmndrs/noise' },
5555
{ text: 'Outline', link: '/guide/pmndrs/outline' },
56+
{ text: 'Scanline', link: '/guide/pmndrs/scanline' },
5657
{ text: 'Pixelation', link: '/guide/pmndrs/pixelation' },
5758
{ text: 'Vignette', link: '/guide/pmndrs/vignette' },
5859
],
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<script setup lang="ts">
2+
import { Environment, Levioso, OrbitControls, Ring, Sphere, Stars } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { DoubleSide, MathUtils, NoToneMapping } from 'three'
6+
import { BlendFunction } from 'postprocessing'
7+
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing'
8+
9+
import '@tresjs/leches/styles'
10+
11+
const gl = {
12+
clearColor: '#000000',
13+
toneMapping: NoToneMapping,
14+
multisampling: 8,
15+
}
16+
17+
const { blendFunction, opacity, density, scrollSpeed } = useControls({
18+
density: { value: 1.15, step: 0.001, max: 2 },
19+
opacity: { value: 0.65, step: 0.1, min: 0, max: 1 },
20+
scrollSpeed: { value: 0.05, step: 0.01, min: 0, max: 2 },
21+
blendFunction: {
22+
options: Object.keys(BlendFunction).map(key => ({
23+
text: key,
24+
value: BlendFunction[key],
25+
})),
26+
value: BlendFunction.HARD_MIX,
27+
},
28+
})
29+
</script>
30+
31+
<template>
32+
<TresLeches style="left: initial;right:10px; top:10px;" />
33+
34+
<TresCanvas
35+
v-bind="gl"
36+
>
37+
<TresPerspectiveCamera
38+
:position="[6.5, 3, 6.5]"
39+
:look-at="[0, 0, 0]"
40+
/>
41+
<OrbitControls auto-rotate :auto-rotate-speed=".5" />
42+
43+
<Suspense>
44+
<Environment :blur="1" preset="snow" />
45+
</Suspense>
46+
47+
<TresAmbientLight />
48+
49+
<TresGroup :rotation-y="MathUtils.degToRad(5)" :rotation-x="MathUtils.degToRad(100)">
50+
<Sphere :args="[2, 32, 16]">
51+
<TresMeshPhysicalMaterial color="#FC7BAC" :side="DoubleSide" :transmission=".5" />
52+
</Sphere>
53+
54+
<Levioso :speed="2.5" :rotationFactor="1" :floatFactor=".5">
55+
<Ring :args="[4.25, 2.5, 32]" :scale-y="-1" :position-z="-.25">
56+
<TresMeshPhysicalMaterial color="#ffffff" :side="DoubleSide" :transmission=".25" />
57+
</Ring>
58+
</Levioso>
59+
</TresGroup>
60+
61+
<Stars />
62+
63+
<Suspense>
64+
<EffectComposerPmndrs>
65+
<ScanlinePmndrs :density="density.value" :opacity="opacity.value" :scrollSpeed="scrollSpeed.value" :blendFunction="Number(blendFunction.value)" />
66+
</EffectComposerPmndrs>
67+
</Suspense>
68+
</TresCanvas>
69+
</template>

docs/components.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,18 @@ declare module 'vue' {
99
export interface GlobalComponents {
1010
BlenderCube: typeof import('./.vitepress/theme/components/BlenderCube.vue')['default']
1111
BloomDemo: typeof import('./.vitepress/theme/components/pmdrs/BloomDemo.vue')['default']
12-
copy: typeof import('./.vitepress/theme/components/three/HalftoneThreeDemo copy.vue')['default']
1312
DepthOfFieldDemo: typeof import('./.vitepress/theme/components/pmdrs/DepthOfFieldDemo.vue')['default']
1413
DocsDemo: typeof import('./.vitepress/theme/components/DocsDemo.vue')['default']
1514
Ducky: typeof import('./.vitepress/theme/components/Ducky.vue')['default']
1615
GlitchDemo: typeof import('./.vitepress/theme/components/pmdrs/GlitchDemo.vue')['default']
1716
GlitchThreeDemo: typeof import('./.vitepress/theme/components/three/GlitchThreeDemo.vue')['default']
18-
GlitchTreeDemo: typeof import('./.vitepress/theme/components/three/GlitchTreeDemo.vue')['default']
1917
HalftoneThreeDemo: typeof import('./.vitepress/theme/components/three/HalftoneThreeDemo.vue')['default']
2018
LoveVueThreeJS: typeof import('./.vitepress/theme/components/LoveVueThreeJS.vue')['default']
2119
NoiseDemo: typeof import('./.vitepress/theme/components/pmdrs/NoiseDemo.vue')['default']
2220
OutlineDemo: typeof import('./.vitepress/theme/components/pmdrs/OutlineDemo.vue')['default']
2321
PixelationDemo: typeof import('./.vitepress/theme/components/pmdrs/PixelationDemo.vue')['default']
2422
PixelationThreeDemo: typeof import('./.vitepress/theme/components/three/PixelationThreeDemo.vue')['default']
25-
RouterLink: typeof import('vue-router')['RouterLink']
26-
RouterView: typeof import('vue-router')['RouterView']
23+
ScanlineDemo: typeof import('./.vitepress/theme/components/pmdrs/ScanlineDemo.vue')['default']
2724
SMAAThreeDemo: typeof import('./.vitepress/theme/components/three/SMAAThreeDemo.vue')['default']
2825
UnrealBloomThreeDemo: typeof import('./.vitepress/theme/components/three/UnrealBloomThreeDemo.vue')['default']
2926
VignetteDemo: typeof import('./.vitepress/theme/components/pmdrs/VignetteDemo.vue')['default']

docs/guide/pmndrs/scanline.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Scanline
2+
3+
<DocsDemo>
4+
<ScanlineDemo />
5+
</DocsDemo>
6+
7+
The `Scanline` effect is part of the [`postprocessing`](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/ScanlineEffect.js~ScanlineEffect.html) package. It simulates scanlines reminiscent of old CRT displays, creating a nostalgic or stylized visual effect for your scene. This effect can enhance the retro aesthetic of your project or add a unique visual touch.
8+
9+
## Usage
10+
11+
The `<ScanlinePmndrs>` component is easy to use and provides customizable options to achieve the desired visual appearance.
12+
13+
```vue{2,10-15,27-33}
14+
<script setup lang="ts">
15+
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing/pmndrs'
16+
import { BlendFunction } from 'postprocessing'
17+
18+
const gl = {
19+
toneMapping: NoToneMapping,
20+
multisampling: 8,
21+
}
22+
23+
const effectProps = {
24+
blendFunction: BlendFunction.HARD_MIX,
25+
density: 1.25,
26+
opacity: 0.65,
27+
scrollSpeed: 0.05,
28+
}
29+
</script>
30+
31+
<template>
32+
<TresCanvas
33+
v-bind="gl"
34+
>
35+
<TresPerspectiveCamera
36+
:position="[5, 5, 5]"
37+
:look-at="[0, 0, 0]"
38+
/>
39+
40+
<Suspense>
41+
<EffectComposerPmndrs>
42+
<ScanlinePmndrs
43+
v-bind="effectProps"
44+
/>
45+
</EffectComposerPmndrs>
46+
</Suspense>
47+
</TresCanvas>
48+
</template>
49+
```
50+
51+
## Props
52+
53+
| Prop | Description | Default |
54+
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------- |
55+
| blendFunction | Defines the [`BlendFunction`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-BlendFunction) used for the effect. | `BlendFunction.OVERLAY` |
56+
| density | The density of the scanlines. Higher values increase the frequency of lines. | `1.25` |
57+
| opacity | The opacity of the scanlines. Controls the transparency of the effect. | `1.0` |
58+
| scrollSpeed | The speed at which the scanlines scroll vertically. When set to `0`, the scanlines remain static. Any non-zero value animates the scanlines vertically. | `0.0` |
59+
60+
## Further Reading
61+
62+
See [postprocessing docs](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/ScanlineEffect.js~ScanlineEffect.html)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script setup lang="ts">
2+
import { ContactShadows, Environment, OrbitControls } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { TresLeches, useControls } from '@tresjs/leches'
5+
import { NoToneMapping, Vector2 } from 'three'
6+
import { watchEffect } from 'vue'
7+
import { BlendFunction } from 'postprocessing'
8+
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing'
9+
10+
import '@tresjs/leches/styles'
11+
12+
const gl = {
13+
clearColor: '#4f4f4f',
14+
toneMapping: NoToneMapping,
15+
multisampling: 8,
16+
envMapIntensity: 10,
17+
}
18+
19+
const { blendFunction, opacity, density, scrollSpeed } = useControls({
20+
density: { value: 1.15, step: 0.001, max: 2 },
21+
opacity: { value: 1, step: 0.1, min: 0, max: 1 },
22+
scrollSpeed: { value: 0.05, step: 0.01, min: 0, max: 2 },
23+
blendFunction: {
24+
options: Object.keys(BlendFunction).map(key => ({
25+
text: key,
26+
value: BlendFunction[key],
27+
})),
28+
value: BlendFunction.OVERLAY,
29+
},
30+
})
31+
</script>
32+
33+
<template>
34+
<TresLeches />
35+
36+
<TresCanvas
37+
v-bind="gl"
38+
>
39+
<TresPerspectiveCamera
40+
:position="[5, 5, 5]"
41+
:look-at="[0, 0, 0]"
42+
/>
43+
<OrbitControls auto-rotate />
44+
45+
<TresMesh :position="[0, .5, 0]">
46+
<TresBoxGeometry :args="[2, 2, 2]" />
47+
<TresMeshStandardMaterial color="white" :roughness="1" :metalness="1" />
48+
</TresMesh>
49+
50+
<TresDirectionalLight color="white" />
51+
52+
<ContactShadows
53+
:opacity="1"
54+
:position-y="-.5"
55+
/>
56+
57+
<Suspense>
58+
<EffectComposerPmndrs>
59+
<ScanlinePmndrs :density="density.value" :opacity="opacity.value" :scrollSpeed="scrollSpeed.value" :blendFunction="Number(blendFunction.value)" />
60+
</EffectComposerPmndrs>
61+
</Suspense>
62+
</TresCanvas>
63+
</template>

playground/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const postProcessingRoutes = [
3838
makeRoute('Pixelation', '👾', false),
3939
makeRoute('Bloom', '🌼', false),
4040
makeRoute('Noise', '📟', false),
41+
makeRoute('Scanline', '📺', false),
4142
makeRoute('Vignette', '🕶️', false),
4243
makeRoute('On-demand', '🔄', false),
4344
]

src/core/pmndrs/ScanlinePmndrs.vue

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<script lang="ts" setup>
2+
import type { BlendFunction } from 'postprocessing'
3+
import { ScanlineEffect } from 'postprocessing'
4+
import { makePropWatchers } from '../../util/prop'
5+
import { useEffectPmndrs } from './composables/useEffectPmndrs'
6+
7+
export interface ScanlinePmndrsProps {
8+
/**
9+
* The blend function.
10+
*/
11+
blendFunction?: BlendFunction
12+
13+
/**
14+
* The density of the scanlines.
15+
*/
16+
density?: number
17+
18+
/**
19+
* The density of the scanlines.
20+
*/
21+
scrollSpeed?: number
22+
23+
/**
24+
* The opacity of the scanlines.
25+
*/
26+
opacity?: number
27+
}
28+
29+
const props = withDefaults(
30+
defineProps<ScanlinePmndrsProps>(),
31+
{
32+
density: 1.25,
33+
opacity: 1.0,
34+
scrollSpeed: 0.0,
35+
},
36+
)
37+
38+
const { pass, effect } = useEffectPmndrs(() => new ScanlineEffect(props), props)
39+
40+
defineExpose({ pass, effect })
41+
42+
makePropWatchers(
43+
[
44+
[() => props.blendFunction, 'blendMode.blendFunction'],
45+
[() => props.opacity, 'blendMode.opacity.value'],
46+
[() => props.density, 'density'],
47+
[() => props.scrollSpeed, 'scrollSpeed'],
48+
],
49+
effect,
50+
() => new ScanlineEffect(),
51+
)
52+
</script>

src/core/pmndrs/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import NoisePmndrs, { type NoisePmndrsProps } from './NoisePmndrs.vue'
99
import OutlinePmndrs, { type OutlinePmndrsProps } from './OutlinePmndrs.vue'
1010
import PixelationPmndrs, { type PixelationPmndrsProps } from './PixelationPmndrs.vue'
1111
import VignettePmndrs, { type VignettePmndrsProps } from './VignettePmndrs.vue'
12+
import ScanlinePmndrs, { type ScanlinePmndrsProps } from './ScanlinePmndrs.vue'
1213

1314
export {
1415
BloomPmndrs,
@@ -20,6 +21,7 @@ export {
2021
PixelationPmndrs,
2122
useEffectPmndrs,
2223
VignettePmndrs,
24+
ScanlinePmndrs,
2325

2426
BloomPmndrsProps,
2527
DepthOfFieldPmndrsProps,
@@ -29,4 +31,5 @@ export {
2931
OutlinePmndrsProps,
3032
PixelationPmndrsProps,
3133
VignettePmndrsProps,
34+
ScanlinePmndrsProps,
3235
}

0 commit comments

Comments
 (0)