-
Notifications
You must be signed in to change notification settings - Fork 38
/
customEffect.ts
99 lines (81 loc) · 2.41 KB
/
customEffect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import * as THREE from "three";
import { EffectComposer, RenderPass, ShaderPass } from "three-stdlib";
import type { Base } from "../base/base";
import { Component } from "../components/component";
import { UniformInjector } from "../components/uniformInjector";
export interface CustomEffectConfig {
vertexShader: string;
fragmentShader: string;
uniforms: { [uniform: string]: THREE.IUniform<any> };
}
const defaultVertexShader = /* glsl */ `
uniform float iTime;
uniform vec2 iResolution;
uniform vec2 iMouse;
varying vec2 vUv;
void main(){
vec3 p=position;
gl_Position=projectionMatrix*modelViewMatrix*vec4(p,1.);
vUv=uv;
}
`;
const defaultFragmentShader = /* glsl */ `
uniform float iTime;
uniform vec2 iResolution;
uniform vec2 iMouse;
uniform sampler2D tDiffuse;
varying vec2 vUv;
void main(){
vec2 p=vUv;
vec4 color=texture(tDiffuse,p);
gl_FragColor=color;
}
`;
/**
* With this, you can just provide your vertex and fragment shader to make a customized postprocessing effect.
*
* Demo: https://kokomi-playground.vercel.app/entries/#volumetricLight
*/
class CustomEffect extends Component {
composer: EffectComposer;
customPass: ShaderPass;
uniformInjector: UniformInjector;
constructor(base: Base, config: Partial<CustomEffectConfig> = {}) {
super(base);
const {
vertexShader = defaultVertexShader,
fragmentShader = defaultFragmentShader,
uniforms = {},
} = config;
const composer = new EffectComposer(base.renderer);
this.composer = composer;
const renderPass = new RenderPass(base.scene, base.camera);
composer.addPass(renderPass);
const uniformInjector = new UniformInjector(base);
this.uniformInjector = uniformInjector;
const customPass = new ShaderPass({
vertexShader,
fragmentShader,
uniforms: {
...{
tDiffuse: {
value: null,
},
},
...uniformInjector.shadertoyUniforms,
...uniforms,
},
});
this.customPass = customPass;
customPass.renderToScreen = true;
composer.addPass(customPass);
}
addExisting(): void {
this.base.composer = this.composer;
}
update(time: number): void {
const uniforms = this.customPass.uniforms;
this.uniformInjector.injectShadertoyUniforms(uniforms);
}
}
export { CustomEffect };