Skip to content

Commit

Permalink
feat: add scanline (#150)
Browse files Browse the repository at this point in the history
* 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 <alvaro.saburido@gmail.com>
  • Loading branch information
damienmontastier and alvarosabu authored Jan 4, 2025
1 parent 08b97bb commit f3da309
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export default defineConfig({
{ text: 'Glitch', link: '/guide/pmndrs/glitch' },
{ text: 'Noise', link: '/guide/pmndrs/noise' },
{ text: 'Outline', link: '/guide/pmndrs/outline' },
{ text: 'Scanline', link: '/guide/pmndrs/scanline' },
{ text: 'Pixelation', link: '/guide/pmndrs/pixelation' },
{ text: 'Vignette', link: '/guide/pmndrs/vignette' },
],
Expand Down
69 changes: 69 additions & 0 deletions docs/.vitepress/theme/components/pmdrs/ScanlineDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<script setup lang="ts">
import { Environment, Levioso, OrbitControls, Ring, Sphere, Stars } from '@tresjs/cientos'
import { TresCanvas } from '@tresjs/core'
import { TresLeches, useControls } from '@tresjs/leches'
import { DoubleSide, MathUtils, NoToneMapping } from 'three'
import { BlendFunction } from 'postprocessing'
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing'
import '@tresjs/leches/styles'
const gl = {
clearColor: '#000000',
toneMapping: NoToneMapping,
multisampling: 8,
}
const { blendFunction, opacity, density, scrollSpeed } = useControls({
density: { value: 1.15, step: 0.001, max: 2 },
opacity: { value: 0.65, step: 0.1, min: 0, max: 1 },
scrollSpeed: { value: 0.05, step: 0.01, min: 0, max: 2 },
blendFunction: {
options: Object.keys(BlendFunction).map(key => ({
text: key,
value: BlendFunction[key],
})),
value: BlendFunction.HARD_MIX,
},
})
</script>

<template>
<TresLeches style="left: initial;right:10px; top:10px;" />

<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera
:position="[6.5, 3, 6.5]"
:look-at="[0, 0, 0]"
/>
<OrbitControls auto-rotate :auto-rotate-speed=".5" />

<Suspense>
<Environment :blur="1" preset="snow" />
</Suspense>

<TresAmbientLight />

<TresGroup :rotation-y="MathUtils.degToRad(5)" :rotation-x="MathUtils.degToRad(100)">
<Sphere :args="[2, 32, 16]">
<TresMeshPhysicalMaterial color="#FC7BAC" :side="DoubleSide" :transmission=".5" />
</Sphere>

<Levioso :speed="2.5" :rotationFactor="1" :floatFactor=".5">
<Ring :args="[4.25, 2.5, 32]" :scale-y="-1" :position-z="-.25">
<TresMeshPhysicalMaterial color="#ffffff" :side="DoubleSide" :transmission=".25" />
</Ring>
</Levioso>
</TresGroup>

<Stars />

<Suspense>
<EffectComposerPmndrs>
<ScanlinePmndrs :density="density.value" :opacity="opacity.value" :scrollSpeed="scrollSpeed.value" :blendFunction="Number(blendFunction.value)" />
</EffectComposerPmndrs>
</Suspense>
</TresCanvas>
</template>
5 changes: 1 addition & 4 deletions docs/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@ declare module 'vue' {
export interface GlobalComponents {
BlenderCube: typeof import('./.vitepress/theme/components/BlenderCube.vue')['default']
BloomDemo: typeof import('./.vitepress/theme/components/pmdrs/BloomDemo.vue')['default']
copy: typeof import('./.vitepress/theme/components/three/HalftoneThreeDemo copy.vue')['default']
DepthOfFieldDemo: typeof import('./.vitepress/theme/components/pmdrs/DepthOfFieldDemo.vue')['default']
DocsDemo: typeof import('./.vitepress/theme/components/DocsDemo.vue')['default']
Ducky: typeof import('./.vitepress/theme/components/Ducky.vue')['default']
GlitchDemo: typeof import('./.vitepress/theme/components/pmdrs/GlitchDemo.vue')['default']
GlitchThreeDemo: typeof import('./.vitepress/theme/components/three/GlitchThreeDemo.vue')['default']
GlitchTreeDemo: typeof import('./.vitepress/theme/components/three/GlitchTreeDemo.vue')['default']
HalftoneThreeDemo: typeof import('./.vitepress/theme/components/three/HalftoneThreeDemo.vue')['default']
LoveVueThreeJS: typeof import('./.vitepress/theme/components/LoveVueThreeJS.vue')['default']
NoiseDemo: typeof import('./.vitepress/theme/components/pmdrs/NoiseDemo.vue')['default']
OutlineDemo: typeof import('./.vitepress/theme/components/pmdrs/OutlineDemo.vue')['default']
PixelationDemo: typeof import('./.vitepress/theme/components/pmdrs/PixelationDemo.vue')['default']
PixelationThreeDemo: typeof import('./.vitepress/theme/components/three/PixelationThreeDemo.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ScanlineDemo: typeof import('./.vitepress/theme/components/pmdrs/ScanlineDemo.vue')['default']
SMAAThreeDemo: typeof import('./.vitepress/theme/components/three/SMAAThreeDemo.vue')['default']
UnrealBloomThreeDemo: typeof import('./.vitepress/theme/components/three/UnrealBloomThreeDemo.vue')['default']
VignetteDemo: typeof import('./.vitepress/theme/components/pmdrs/VignetteDemo.vue')['default']
Expand Down
62 changes: 62 additions & 0 deletions docs/guide/pmndrs/scanline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Scanline

<DocsDemo>
<ScanlineDemo />
</DocsDemo>

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.

## Usage

The `<ScanlinePmndrs>` component is easy to use and provides customizable options to achieve the desired visual appearance.

```vue{2,10-15,27-33}
<script setup lang="ts">
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing/pmndrs'
import { BlendFunction } from 'postprocessing'
const gl = {
toneMapping: NoToneMapping,
multisampling: 8,
}
const effectProps = {
blendFunction: BlendFunction.HARD_MIX,
density: 1.25,
opacity: 0.65,
scrollSpeed: 0.05,
}
</script>
<template>
<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera
:position="[5, 5, 5]"
:look-at="[0, 0, 0]"
/>
<Suspense>
<EffectComposerPmndrs>
<ScanlinePmndrs
v-bind="effectProps"
/>
</EffectComposerPmndrs>
</Suspense>
</TresCanvas>
</template>
```

## Props

| Prop | Description | Default |
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------- |
| blendFunction | Defines the [`BlendFunction`](https://pmndrs.github.io/postprocessing/public/docs/variable/index.html#static-variable-BlendFunction) used for the effect. | `BlendFunction.OVERLAY` |
| density | The density of the scanlines. Higher values increase the frequency of lines. | `1.25` |
| opacity | The opacity of the scanlines. Controls the transparency of the effect. | `1.0` |
| 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` |

## Further Reading

See [postprocessing docs](https://pmndrs.github.io/postprocessing/public/docs/class/src/effects/ScanlineEffect.js~ScanlineEffect.html)
63 changes: 63 additions & 0 deletions playground/src/pages/postprocessing/scanline.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script setup lang="ts">
import { ContactShadows, Environment, OrbitControls } from '@tresjs/cientos'

Check failure on line 2 in playground/src/pages/postprocessing/scanline.vue

View workflow job for this annotation

GitHub Actions / Lint (20)

'Environment' is defined but never used
import { TresCanvas } from '@tresjs/core'
import { TresLeches, useControls } from '@tresjs/leches'
import { NoToneMapping, Vector2 } from 'three'

Check failure on line 5 in playground/src/pages/postprocessing/scanline.vue

View workflow job for this annotation

GitHub Actions / Lint (20)

'Vector2' is defined but never used
import { watchEffect } from 'vue'

Check failure on line 6 in playground/src/pages/postprocessing/scanline.vue

View workflow job for this annotation

GitHub Actions / Lint (20)

'watchEffect' is defined but never used
import { BlendFunction } from 'postprocessing'
import { EffectComposerPmndrs, ScanlinePmndrs } from '@tresjs/post-processing'
import '@tresjs/leches/styles'
const gl = {
clearColor: '#4f4f4f',
toneMapping: NoToneMapping,
multisampling: 8,
envMapIntensity: 10,
}
const { blendFunction, opacity, density, scrollSpeed } = useControls({
density: { value: 1.15, step: 0.001, max: 2 },
opacity: { value: 1, step: 0.1, min: 0, max: 1 },
scrollSpeed: { value: 0.05, step: 0.01, min: 0, max: 2 },
blendFunction: {
options: Object.keys(BlendFunction).map(key => ({
text: key,
value: BlendFunction[key],
})),
value: BlendFunction.OVERLAY,
},
})
</script>

<template>
<TresLeches />

<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera
:position="[5, 5, 5]"
:look-at="[0, 0, 0]"
/>
<OrbitControls auto-rotate />

<TresMesh :position="[0, .5, 0]">
<TresBoxGeometry :args="[2, 2, 2]" />
<TresMeshStandardMaterial color="white" :roughness="1" :metalness="1" />
</TresMesh>

<TresDirectionalLight color="white" />

<ContactShadows
:opacity="1"
:position-y="-.5"
/>

<Suspense>
<EffectComposerPmndrs>
<ScanlinePmndrs :density="density.value" :opacity="opacity.value" :scrollSpeed="scrollSpeed.value" :blendFunction="Number(blendFunction.value)" />
</EffectComposerPmndrs>
</Suspense>
</TresCanvas>
</template>
1 change: 1 addition & 0 deletions playground/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const postProcessingRoutes = [
makeRoute('Pixelation', '👾', false),
makeRoute('Bloom', '🌼', false),
makeRoute('Noise', '📟', false),
makeRoute('Scanline', '📺', false),
makeRoute('Vignette', '🕶️', false),
makeRoute('On-demand', '🔄', false),
]
Expand Down
52 changes: 52 additions & 0 deletions src/core/pmndrs/ScanlinePmndrs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script lang="ts" setup>
import type { BlendFunction } from 'postprocessing'
import { ScanlineEffect } from 'postprocessing'
import { makePropWatchers } from '../../util/prop'
import { useEffectPmndrs } from './composables/useEffectPmndrs'
export interface ScanlinePmndrsProps {
/**
* The blend function.
*/
blendFunction?: BlendFunction
/**
* The density of the scanlines.
*/
density?: number
/**
* The density of the scanlines.
*/
scrollSpeed?: number
/**
* The opacity of the scanlines.
*/
opacity?: number
}
const props = withDefaults(
defineProps<ScanlinePmndrsProps>(),
{
density: 1.25,
opacity: 1.0,
scrollSpeed: 0.0,
},
)
const { pass, effect } = useEffectPmndrs(() => new ScanlineEffect(props), props)
defineExpose({ pass, effect })
makePropWatchers(
[
[() => props.blendFunction, 'blendMode.blendFunction'],
[() => props.opacity, 'blendMode.opacity.value'],
[() => props.density, 'density'],
[() => props.scrollSpeed, 'scrollSpeed'],
],
effect,
() => new ScanlineEffect(),
)
</script>
3 changes: 3 additions & 0 deletions src/core/pmndrs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import NoisePmndrs, { type NoisePmndrsProps } from './NoisePmndrs.vue'
import OutlinePmndrs, { type OutlinePmndrsProps } from './OutlinePmndrs.vue'
import PixelationPmndrs, { type PixelationPmndrsProps } from './PixelationPmndrs.vue'
import VignettePmndrs, { type VignettePmndrsProps } from './VignettePmndrs.vue'
import ScanlinePmndrs, { type ScanlinePmndrsProps } from './ScanlinePmndrs.vue'

export {
BloomPmndrs,
Expand All @@ -20,6 +21,7 @@ export {
PixelationPmndrs,
useEffectPmndrs,
VignettePmndrs,
ScanlinePmndrs,

BloomPmndrsProps,
DepthOfFieldPmndrsProps,
Expand All @@ -29,4 +31,5 @@ export {
OutlinePmndrsProps,
PixelationPmndrsProps,
VignettePmndrsProps,
ScanlinePmndrsProps,
}

0 comments on commit f3da309

Please sign in to comment.