-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmain.ts
160 lines (149 loc) · 4.59 KB
/
main.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import * as THREE from "three";
import GUI from "lil-gui";
import ComparisonSlider from "comparison-slider";
// shaders
import vertexShader from "../vert.glsl?raw";
import easuFragmentShader from "../easu.glsl?raw";
import rcasFragmentShader from "../rcas.glsl?raw";
window.addEventListener("load", () => {
const DEFAULT_SHARPNESS = 0.2;
// dom size variables
let width = 0;
let height = 0;
let aspect = 0;
// dom
const container = document.getElementById("container");
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const video = document.getElementById("video") as HTMLVideoElement;
// calculate initial size
aspect = video.videoWidth / video.videoHeight;
width = window.innerWidth > video.videoWidth
? video.videoWidth
: window.innerWidth;
height = window.innerHeight > video.videoHeight
? video.videoHeight
: window.innerHeight;
// camera
const camera = new THREE.OrthographicCamera(
width / -2,
width / 2,
height / 2,
height / -2,
);
// common object
const videoTexture = new THREE.VideoTexture(video);
const geometry = new THREE.PlaneGeometry(2, 2);
// EASU stage setting
const easuScene = new THREE.Scene();
const easuMaterial = new THREE.ShaderMaterial({
uniforms: {
iChannel0: {
value: videoTexture,
},
iResolution: {
value: new THREE.Vector2(width, height),
},
},
vertexShader,
fragmentShader: easuFragmentShader,
glslVersion: THREE.GLSL3,
});
const easuMesh = new THREE.Mesh(geometry, easuMaterial);
easuScene.add(easuMesh);
easuScene.add(camera);
// create renderer
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
renderer.setSize(width, height);
renderer.setAnimationLoop(animation);
container!.appendChild(canvas);
canvas.setAttribute(
"class",
"ComparisonSlider__After",
);
// offscreen render target
const renderTarget = new THREE.WebGLRenderTarget(width, height, {
depthBuffer: false,
stencilBuffer: false,
});
// RCAS stage setting
const rcasScene = new THREE.Scene();
const rcasMaterial = new THREE.ShaderMaterial({
uniforms: {
iChannel0: {
value: videoTexture,
},
// I think that sampling source texture only seems to be better quality without sampleing EASU pass.🤔
// I can't make it out that is caused by ShaderToy porting or my misunderstanding.
// Set iChannel0.value to renderTarget.texture if you want to process correctly with the original algorithm.
iChannel1: {
value: renderTarget.texture,
},
iResolution: {
value: new THREE.Vector2(width, height),
},
sharpness: { value: DEFAULT_SHARPNESS },
},
vertexShader,
fragmentShader: rcasFragmentShader,
glslVersion: THREE.GLSL3,
});
const rcasMesh = new THREE.Mesh(geometry.clone(), rcasMaterial);
rcasScene.add(rcasMesh);
// tick
function animation() {
// render EASU stage
renderer.setRenderTarget(renderTarget);
renderer.render(easuScene, camera);
// render RCAS stage
renderer.setRenderTarget(null);
renderer.render(rcasScene, camera);
}
// initialize gui
const gui = new GUI();
const params = { sharpness: DEFAULT_SHARPNESS, comparison: true };
gui.add(params, "sharpness", 0, 2).onChange((value: number) => {
rcasMaterial.uniforms["sharpness"].value = value;
});
// initialize comparison slider
setTimeout(() => {
const comparisonSlider = new ComparisonSlider("#container");
gui.add(params, "comparison").onChange((value: boolean) => {
value
? comparisonSlider.$handle.removeAttribute("hidden")
: comparisonSlider.$handle.setAttribute("hidden", "true");
});
}, 10);
// check dom resize
const resizeObserver = new ResizeObserver(() => {
// recalculate size
width = window.innerWidth > video.videoWidth
? video.videoWidth
: window.innerWidth;
height = width / aspect;
renderer.setSize(width, height);
// update uniforms
easuMaterial.uniforms["iResolution"].value = new THREE.Vector2(
width,
height,
);
rcasMaterial.uniforms["iResolution"].value = new THREE.Vector2(
width,
height,
);
// update dom size
container.setAttribute(
"style",
`
width: ${width}px;
height: ${height}px;
`,
);
});
resizeObserver.observe(document.body);
// streaming examples
// initialize comparison slider
new ComparisonSlider("#example1");
new ComparisonSlider("#example2");
new ComparisonSlider("#example3");
new ComparisonSlider("#example4");
}, { once: true });