Skip to content

Commit c5584b9

Browse files
init
1 parent 5b99a65 commit c5584b9

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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 } from 'three'
6+
import { BlendFunction } from 'postprocessing'
7+
import { EffectComposerPmndrs, SeuratPmndrs } from '@tresjs/post-processing'
8+
9+
import '@tresjs/leches/styles'
10+
11+
const gl = {
12+
clearColor: '#ffffff',
13+
toneMapping: NoToneMapping,
14+
multisampling: 8,
15+
envMapIntensity: 10,
16+
}
17+
18+
const neonColors = [
19+
'#FF00FF', // Magenta
20+
'#00FFFF', // Cyan
21+
'#00FF00', // Lime
22+
'#FFFF00', // Yellow
23+
'#FF0000', // Red
24+
'#FF1493', // Deep Pink
25+
'#7FFF00', // Chartreuse
26+
'#FF4500', // Orange Red
27+
'#8A2BE2', // Blue Violet
28+
'#00FF7F', // Spring Green
29+
'#FFD700', // Gold
30+
'#FF69B4', // Hot Pink
31+
'#ADFF2F', // Green Yellow
32+
'#FF6347', // Tomato
33+
'#40E0D0', // Turquoise
34+
'#EE82EE', // Violet
35+
]
36+
37+
const { blendFunction, amount, offsetX, offsetY } = useControls({
38+
amount: { value: 0.2, step: 0.001, max: 1 },
39+
offsetX: { value: 0.5, step: 0.01, min: 0, max: 1 },
40+
offsetY: { value: 0.5, step: 0.01, min: 0, max: 1 },
41+
blendFunction: {
42+
options: Object.keys(BlendFunction).map(key => ({
43+
text: key,
44+
value: BlendFunction[key as keyof typeof BlendFunction],
45+
})),
46+
value: BlendFunction.OVERLAY,
47+
},
48+
})
49+
</script>
50+
51+
<template>
52+
<TresLeches />
53+
54+
<TresCanvas
55+
v-bind="gl"
56+
>
57+
<TresPerspectiveCamera
58+
:position="[0, 6.5, 6.5]"
59+
:look-at="[0, 0, 0]"
60+
/>
61+
<OrbitControls auto-rotate />
62+
63+
<TresAmbientLight :intensity="1" />
64+
65+
<template v-for="(color, index) in neonColors" :key="index">
66+
<TresMesh :position="[index % 4 * 2 - 3, 0, Math.floor(index / 4) * 2 - 3]">
67+
<TresBoxGeometry :args="[2, 2, 2]" />
68+
<TresMeshStandardMaterial :color="color" :roughness=".5" :metalness="1" />
69+
</TresMesh>
70+
</template>
71+
72+
<Suspense>
73+
<Environment :blur=".25" preset="snow" />
74+
</Suspense>
75+
76+
<TresDirectionalLight color="white" />
77+
78+
<ContactShadows
79+
:opacity=".65"
80+
:position-y="-1"
81+
:scale="35"
82+
:blur="1"
83+
/>
84+
85+
<Suspense>
86+
<EffectComposerPmndrs>
87+
<SeuratPmndrs :amount="amount" :offset="[offsetX, offsetY]" :blendFunction="Number(blendFunction)" />
88+
</EffectComposerPmndrs>
89+
</Suspense>
90+
</TresCanvas>
91+
</template>

playground/src/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const postProcessingRoutes = [
5050
makeRoute('Sepia', '🌅', false),
5151
makeRoute('Scanline', '📽️', false),
5252
makeRoute('Shock Wave', '🌊', false),
53+
makeRoute('Seurat', '🎩', false),
5354
makeRoute('Vignette', '🕶️', false),
5455
makeRoute('Barrel blur', '🌀', false),
5556
makeRoute('On-demand', '🔄', false),

src/core/pmndrs/SeuratPmndrs.vue

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<script lang="ts" setup>
2+
import type { BlendFunction } from 'postprocessing'
3+
import { Vector2 } from 'three'
4+
import { SeuratEffect } from './custom/seurat/index'
5+
import { makePropWatchers } from '../../util/prop'
6+
import { useEffectPmndrs } from './composables/useEffectPmndrs'
7+
8+
export interface SeuratPmndrsProps {
9+
/**
10+
* The blend function for the effect.
11+
* Determines how this effect blends with other effects.
12+
*/
13+
blendFunction?: BlendFunction
14+
15+
/**
16+
* The intensity of the barrel distortion.
17+
* A value between 0 (no distortion) and 1 (maximum distortion).
18+
*/
19+
amount?: number
20+
21+
/**
22+
* The offset of the barrel distortion center.
23+
* A Vector2 value or an A value or an array of two numbers, with both values ranging from 0 to 1.
24+
* This allows you to change the position of the distortion effect.
25+
*/
26+
offset?: Vector2 | [number, number]
27+
}
28+
29+
const props = defineProps<SeuratPmndrsProps>()
30+
31+
const { pass, effect } = useEffectPmndrs(
32+
() => new SeuratEffect({
33+
...props,
34+
offset: Array.isArray(props.offset) ? new Vector2(...props.offset) : props.offset,
35+
}),
36+
props,
37+
)
38+
39+
defineExpose({ pass, effect })
40+
41+
makePropWatchers(
42+
[
43+
[() => props.blendFunction, 'blendMode.blendFunction'],
44+
[() => props.amount, 'amount'],
45+
[() => props.offset, 'offset'],
46+
],
47+
effect,
48+
() => new SeuratEffect(),
49+
)
50+
</script>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Uniform, Vector2 } from 'three'
2+
import { BlendFunction, Effect } from 'postprocessing'
3+
4+
/**
5+
* SeuratEffect - A custom effect for applying a barrel distortion
6+
* with chromatic aberration blur.
7+
*/
8+
9+
export class SeuratEffect extends Effect {
10+
/**
11+
* Creates a new SeuratEffect instance.
12+
*
13+
* @param {object} [options] - Configuration options for the effect.
14+
* @param {BlendFunction} [options.blendFunction] - Blend mode.
15+
* @param {number} [options.amount] - Intensity of the barrel distortion (0 to 1).
16+
* @param {Vector2} [options.offset] - Offset of the barrel distortion center (0 to 1 for both x and y). This allows you to change the position of the distortion effect.
17+
*
18+
*/
19+
constructor({ blendFunction = BlendFunction.NORMAL, amount = 0.15, offset = new Vector2(0.5, 0.5) } = {}) {
20+
super('SeuratEffect', `
21+
uniform float amount;
22+
uniform vec2 offset;
23+
24+
#define NUM_ITER 16
25+
26+
void mainUv(inout vec2 uv) {
27+
uv = uv;
28+
}
29+
30+
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
31+
vec3 color = inputColor.rgb;
32+
33+
outputColor = vec4(color, inputColor.a); // Preserves original alpha
34+
}
35+
`, {
36+
blendFunction,
37+
uniforms: new Map<string, Uniform<number | Vector2>>([
38+
['amount', new Uniform(amount)], // Uniform controlling the intensity of distortion
39+
['offset', new Uniform(offset)], // Uniform controlling the offset of distortion
40+
]),
41+
})
42+
}
43+
44+
/**
45+
* The amount.
46+
*
47+
* @type {number}
48+
*/
49+
50+
get amount() {
51+
return this.uniforms.get('amount')?.value
52+
}
53+
54+
set amount(value) {
55+
this.uniforms.get('amount')!.value = value
56+
}
57+
58+
/**
59+
* The offset.
60+
*
61+
* @type {Vector2}
62+
*/
63+
64+
get offset() {
65+
return this.uniforms.get('offset')?.value
66+
}
67+
68+
set offset(value) {
69+
this.uniforms.get('offset')!.value = value
70+
}
71+
}

src/core/pmndrs/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import DotScreenPmndrs, { type DotScreenPmndrsProps } from './DotScreenPmndrs.vu
2323
import SepiaPmndrs, { type SepiaPmndrsProps } from './SepiaPmndrs.vue'
2424
import LinocutPmndrs, { type LinocutPmndrsProps } from './LinocutPmndrs.vue'
2525
import DepthPickingPassPmndrs, { type DepthPickingPassPmndrsProps } from './DepthPickingPassPmndrs.vue'
26+
import SeuratPmndrs, { type SeuratPmndrsProps } from './SeuratPmndrs.vue'
2627

2728
export {
2829
BloomPmndrs,
@@ -48,6 +49,7 @@ export {
4849
SepiaPmndrs,
4950
LinocutPmndrs,
5051
DepthPickingPassPmndrs,
52+
SeuratPmndrs,
5153
BloomPmndrsProps,
5254
DepthOfFieldPmndrsProps,
5355
EffectComposerPmndrsProps,
@@ -70,4 +72,5 @@ export {
7072
SepiaPmndrsProps,
7173
LinocutPmndrsProps,
7274
DepthPickingPassPmndrsProps,
75+
SeuratPmndrsProps,
7376
}

0 commit comments

Comments
 (0)