@pixagram/renderart 0.4.5 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +171 -67
- package/dist/crt-gpu.d.ts +30 -0
- package/dist/crt-gpu.d.ts.map +1 -0
- package/dist/crt-gpu.js +282 -0
- package/dist/crt-gpu.js.map +1 -0
- package/dist/hex-gpu.d.ts +35 -0
- package/dist/hex-gpu.d.ts.map +1 -0
- package/dist/hex-gpu.js +382 -0
- package/dist/hex-gpu.js.map +1 -0
- package/dist/index.d.ts +24 -300
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -963
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +84 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/wasm-wrapper.d.ts +71 -0
- package/dist/wasm-wrapper.d.ts.map +1 -0
- package/dist/wasm-wrapper.js +76 -0
- package/dist/wasm-wrapper.js.map +1 -0
- package/dist/xbrz-gpu.d.ts +34 -0
- package/dist/xbrz-gpu.d.ts.map +1 -0
- package/dist/xbrz-gpu.js +640 -0
- package/dist/xbrz-gpu.js.map +1 -0
- package/package.json +47 -35
- package/src/crt-gpu.ts +313 -0
- package/src/hex-gpu.ts +426 -0
- package/src/index.ts +47 -0
- package/src/types.ts +90 -0
- package/src/wasm/crt.rs +181 -0
- package/src/wasm/hex.rs +324 -0
- package/src/wasm/lib.rs +285 -0
- package/src/wasm/xbrz.rs +262 -0
- package/src/wasm-wrapper.ts +195 -0
- package/src/xbrz-gpu.ts +671 -0
- package/dist/index.d.mts +0 -305
- package/dist/index.mjs +0 -948
- package/dist/index.mjs.map +0 -1
- package/pkg/LICENSE +0 -21
- package/pkg/README.md +0 -117
- package/pkg/renderart_wasm.d.ts +0 -52
- package/pkg/renderart_wasm.js +0 -5
- package/pkg/renderart_wasm_bg.js +0 -283
- package/pkg/renderart_wasm_bg.wasm +0 -0
- package/pkg/renderart_wasm_bg.wasm.d.ts +0 -24
package/package.json
CHANGED
|
@@ -1,59 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixagram/renderart",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "High-performance pixel art rendering engines
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "High-performance pixel art rendering engines with WebGL2 GPU acceleration and WASM support",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pixel-art",
|
|
7
|
+
"upscaling",
|
|
8
|
+
"xbrz",
|
|
9
|
+
"crt",
|
|
10
|
+
"hexagonal",
|
|
11
|
+
"webgl",
|
|
12
|
+
"wasm",
|
|
13
|
+
"image-processing",
|
|
14
|
+
"retro",
|
|
15
|
+
"gamedev"
|
|
16
|
+
],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": ""
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
5
24
|
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.
|
|
25
|
+
"module": "./dist/index.js",
|
|
7
26
|
"types": "./dist/index.d.ts",
|
|
8
27
|
"exports": {
|
|
9
28
|
".": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts"
|
|
31
|
+
},
|
|
32
|
+
"./crt": {
|
|
33
|
+
"import": "./dist/crt-gpu.js",
|
|
34
|
+
"types": "./dist/crt-gpu.d.ts"
|
|
35
|
+
},
|
|
36
|
+
"./hex": {
|
|
37
|
+
"import": "./dist/hex-gpu.js",
|
|
38
|
+
"types": "./dist/hex-gpu.d.ts"
|
|
39
|
+
},
|
|
40
|
+
"./xbrz": {
|
|
41
|
+
"import": "./dist/xbrz-gpu.js",
|
|
42
|
+
"types": "./dist/xbrz-gpu.d.ts"
|
|
13
43
|
},
|
|
14
44
|
"./wasm": {
|
|
15
|
-
"import": "./
|
|
16
|
-
"
|
|
45
|
+
"import": "./dist/wasm/renderart.js",
|
|
46
|
+
"types": "./dist/wasm/renderart.d.ts"
|
|
17
47
|
}
|
|
18
48
|
},
|
|
19
49
|
"files": [
|
|
20
50
|
"dist",
|
|
21
|
-
"
|
|
51
|
+
"src",
|
|
22
52
|
"README.md",
|
|
23
53
|
"LICENSE"
|
|
24
54
|
],
|
|
25
55
|
"scripts": {
|
|
26
|
-
"build:wasm": "wasm-pack build --target bundler --out-dir pkg --release && rm -f pkg/.gitignore pkg/package.json",
|
|
27
|
-
"build:ts": "tsup",
|
|
28
56
|
"build": "npm run build:wasm && npm run build:ts",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"upscale",
|
|
35
|
-
"crt",
|
|
36
|
-
"hexagon",
|
|
37
|
-
"xbrz",
|
|
38
|
-
"webgl",
|
|
39
|
-
"wasm",
|
|
40
|
-
"shader",
|
|
41
|
-
"rendering",
|
|
42
|
-
"image-processing"
|
|
43
|
-
],
|
|
44
|
-
"author": "Pixagram SA",
|
|
45
|
-
"license": "MIT",
|
|
46
|
-
"repository": {
|
|
47
|
-
"type": "git",
|
|
48
|
-
"url": "https://github.com/pixagram/renderart.git"
|
|
57
|
+
"build:ts": "tsc",
|
|
58
|
+
"build:wasm": "wasm-pack build --target web --out-dir dist/wasm",
|
|
59
|
+
"clean": "rm -rf dist",
|
|
60
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
61
|
+
"test": "node --test dist/**/*.test.js"
|
|
49
62
|
},
|
|
50
63
|
"devDependencies": {
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"typescript": "^5.3.0"
|
|
64
|
+
"typescript": "^5.3.0",
|
|
65
|
+
"wasm-pack": "^0.12.0"
|
|
54
66
|
},
|
|
55
67
|
"engines": {
|
|
56
|
-
"node": ">=
|
|
68
|
+
"node": ">=18.0.0"
|
|
57
69
|
},
|
|
58
70
|
"sideEffects": false
|
|
59
71
|
}
|
package/src/crt-gpu.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRT GPU Renderer using WebGL2
|
|
3
|
+
*
|
|
4
|
+
* High-performance CRT effect rendering using fragment shaders.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { CrtOptions, ImageInput, ImageOutput, Renderer } from './types.js';
|
|
8
|
+
|
|
9
|
+
// Vertex shader
|
|
10
|
+
const VERTEX_SHADER = `#version 300 es
|
|
11
|
+
layout(location = 0) in vec2 position;
|
|
12
|
+
out vec2 vUv;
|
|
13
|
+
|
|
14
|
+
void main() {
|
|
15
|
+
vUv = position * 0.5 + 0.5;
|
|
16
|
+
gl_Position = vec4(position, 0.0, 1.0);
|
|
17
|
+
}`;
|
|
18
|
+
|
|
19
|
+
// Fragment shader with configurable CRT effects
|
|
20
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
21
|
+
precision highp float;
|
|
22
|
+
|
|
23
|
+
uniform sampler2D uTex;
|
|
24
|
+
uniform vec2 uRes;
|
|
25
|
+
uniform vec2 uWarp;
|
|
26
|
+
uniform float uScanHardness;
|
|
27
|
+
uniform float uScanOpacity;
|
|
28
|
+
uniform float uMaskOpacity;
|
|
29
|
+
uniform int uEnableWarp;
|
|
30
|
+
uniform int uEnableScanlines;
|
|
31
|
+
uniform int uEnableMask;
|
|
32
|
+
|
|
33
|
+
in vec2 vUv;
|
|
34
|
+
out vec4 outColor;
|
|
35
|
+
|
|
36
|
+
// Gamma 2.0 approximation
|
|
37
|
+
vec3 toLinear(vec3 c) { return c * c; }
|
|
38
|
+
vec3 toSrgb(vec3 c) { return sqrt(c); }
|
|
39
|
+
|
|
40
|
+
vec2 warp(vec2 uv) {
|
|
41
|
+
if (uEnableWarp == 0) return uv;
|
|
42
|
+
vec2 dc = abs(0.5 - uv);
|
|
43
|
+
vec2 dc2 = dc * dc;
|
|
44
|
+
uv.x -= 0.5; uv.x *= 1.0 + (dc2.y * (0.3 * uWarp.x)); uv.x += 0.5;
|
|
45
|
+
uv.y -= 0.5; uv.y *= 1.0 + (dc2.x * (0.4 * uWarp.y)); uv.y += 0.5;
|
|
46
|
+
return uv;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
float scanline(float y, float sourceHeight) {
|
|
50
|
+
if (uEnableScanlines == 0) return 1.0;
|
|
51
|
+
float v = fract(y * sourceHeight);
|
|
52
|
+
float d = abs(v - 0.5);
|
|
53
|
+
float line = exp(d * d * uScanHardness);
|
|
54
|
+
return mix(1.0, line, uScanOpacity);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
vec3 mask(vec2 pos) {
|
|
58
|
+
if (uEnableMask == 0) return vec3(1.0);
|
|
59
|
+
float x = fract(pos.x / 6.0);
|
|
60
|
+
vec3 m = vec3(1.0);
|
|
61
|
+
float step1 = 0.333;
|
|
62
|
+
float step2 = 0.666;
|
|
63
|
+
|
|
64
|
+
m.r = step(0.0, x) - step(step1, x);
|
|
65
|
+
m.g = step(step1, x) - step(step2, x);
|
|
66
|
+
m.b = step(step2, x) - step(1.0, x);
|
|
67
|
+
|
|
68
|
+
return mix(vec3(1.0), m, uMaskOpacity);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void main() {
|
|
72
|
+
// 1. Geometry
|
|
73
|
+
vec2 uv = warp(vUv);
|
|
74
|
+
|
|
75
|
+
// 2. Bounds Check
|
|
76
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
77
|
+
outColor = vec4(0.0);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3. Texture Sample
|
|
82
|
+
vec4 texSample = texture(uTex, uv);
|
|
83
|
+
|
|
84
|
+
if (texSample.a == 0.0) {
|
|
85
|
+
outColor = vec4(0.0);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
vec3 linearColor = toLinear(texSample.rgb);
|
|
90
|
+
|
|
91
|
+
// 4. CRT Effects
|
|
92
|
+
ivec2 texSize = textureSize(uTex, 0);
|
|
93
|
+
|
|
94
|
+
// Smart Bloom
|
|
95
|
+
float luma = dot(linearColor, vec3(0.299, 0.587, 0.114));
|
|
96
|
+
float bloom = luma * 0.7;
|
|
97
|
+
|
|
98
|
+
// Calculate patterns
|
|
99
|
+
float scan = scanline(uv.y, float(texSize.y));
|
|
100
|
+
vec3 m = mask(gl_FragCoord.xy);
|
|
101
|
+
|
|
102
|
+
// Apply effects
|
|
103
|
+
vec3 effects = m * scan;
|
|
104
|
+
vec3 finalRGB = linearColor * mix(effects, vec3(1.0), bloom);
|
|
105
|
+
|
|
106
|
+
// 5. Output
|
|
107
|
+
outColor = vec4(toSrgb(finalRGB), texSample.a);
|
|
108
|
+
}`;
|
|
109
|
+
|
|
110
|
+
/** CRT GPU Renderer */
|
|
111
|
+
export class CrtGpuRenderer implements Renderer<CrtOptions> {
|
|
112
|
+
private gl: WebGL2RenderingContext | null = null;
|
|
113
|
+
private canvas: OffscreenCanvas | null = null;
|
|
114
|
+
private program: WebGLProgram | null = null;
|
|
115
|
+
private texture: WebGLTexture | null = null;
|
|
116
|
+
private uniforms: Record<string, WebGLUniformLocation | null> = {};
|
|
117
|
+
private initialized = false;
|
|
118
|
+
private currentCanvasSize = { width: 0, height: 0 };
|
|
119
|
+
private currentTexSize = { width: 0, height: 0 };
|
|
120
|
+
|
|
121
|
+
/** Create a new CRT GPU renderer */
|
|
122
|
+
static create(): CrtGpuRenderer {
|
|
123
|
+
const renderer = new CrtGpuRenderer();
|
|
124
|
+
renderer.init();
|
|
125
|
+
return renderer;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private init(): void {
|
|
129
|
+
if (typeof OffscreenCanvas === 'undefined') {
|
|
130
|
+
throw new Error('OffscreenCanvas not supported');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
this.canvas = new OffscreenCanvas(1, 1);
|
|
134
|
+
this.gl = this.canvas.getContext('webgl2', {
|
|
135
|
+
alpha: true,
|
|
136
|
+
premultipliedAlpha: false,
|
|
137
|
+
desynchronized: true,
|
|
138
|
+
powerPreference: 'high-performance',
|
|
139
|
+
antialias: false,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (!this.gl) {
|
|
143
|
+
throw new Error('WebGL2 not supported');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const gl = this.gl;
|
|
147
|
+
|
|
148
|
+
// Create shaders
|
|
149
|
+
const vs = this.createShader(gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
150
|
+
const fs = this.createShader(gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
151
|
+
|
|
152
|
+
// Create program
|
|
153
|
+
this.program = gl.createProgram()!;
|
|
154
|
+
gl.attachShader(this.program, vs);
|
|
155
|
+
gl.attachShader(this.program, fs);
|
|
156
|
+
gl.linkProgram(this.program);
|
|
157
|
+
|
|
158
|
+
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
|
|
159
|
+
throw new Error('Shader program link failed: ' + gl.getProgramInfoLog(this.program));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
gl.useProgram(this.program);
|
|
163
|
+
|
|
164
|
+
// Get uniform locations
|
|
165
|
+
this.uniforms = {
|
|
166
|
+
uTex: gl.getUniformLocation(this.program, 'uTex'),
|
|
167
|
+
uRes: gl.getUniformLocation(this.program, 'uRes'),
|
|
168
|
+
uWarp: gl.getUniformLocation(this.program, 'uWarp'),
|
|
169
|
+
uScanHardness: gl.getUniformLocation(this.program, 'uScanHardness'),
|
|
170
|
+
uScanOpacity: gl.getUniformLocation(this.program, 'uScanOpacity'),
|
|
171
|
+
uMaskOpacity: gl.getUniformLocation(this.program, 'uMaskOpacity'),
|
|
172
|
+
uEnableWarp: gl.getUniformLocation(this.program, 'uEnableWarp'),
|
|
173
|
+
uEnableScanlines: gl.getUniformLocation(this.program, 'uEnableScanlines'),
|
|
174
|
+
uEnableMask: gl.getUniformLocation(this.program, 'uEnableMask'),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
gl.uniform1i(this.uniforms.uTex, 0);
|
|
178
|
+
|
|
179
|
+
// Setup geometry (fullscreen triangle)
|
|
180
|
+
const buf = gl.createBuffer();
|
|
181
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
182
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
|
183
|
+
gl.enableVertexAttribArray(0);
|
|
184
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
185
|
+
|
|
186
|
+
// Create texture
|
|
187
|
+
this.texture = gl.createTexture();
|
|
188
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
189
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
190
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
191
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
192
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
193
|
+
|
|
194
|
+
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
195
|
+
|
|
196
|
+
this.initialized = true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private createShader(type: number, source: string): WebGLShader {
|
|
200
|
+
const gl = this.gl!;
|
|
201
|
+
const shader = gl.createShader(type)!;
|
|
202
|
+
gl.shaderSource(shader, source);
|
|
203
|
+
gl.compileShader(shader);
|
|
204
|
+
|
|
205
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
206
|
+
const info = gl.getShaderInfoLog(shader);
|
|
207
|
+
gl.deleteShader(shader);
|
|
208
|
+
throw new Error('Shader compile failed: ' + info);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return shader;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Check if renderer is ready */
|
|
215
|
+
isReady(): boolean {
|
|
216
|
+
return this.initialized;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Render CRT effect */
|
|
220
|
+
render(input: ImageInput | ImageData, options: CrtOptions = {}): ImageOutput {
|
|
221
|
+
if (!this.initialized || !this.gl || !this.canvas) {
|
|
222
|
+
throw new Error('Renderer not initialized');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const gl = this.gl;
|
|
226
|
+
const data = input instanceof ImageData ? input.data : input.data;
|
|
227
|
+
const width = input.width;
|
|
228
|
+
const height = input.height;
|
|
229
|
+
|
|
230
|
+
const scale = Math.min(32, Math.max(2, options.scale ?? 3));
|
|
231
|
+
const outWidth = width * scale;
|
|
232
|
+
const outHeight = height * scale;
|
|
233
|
+
|
|
234
|
+
// Resize canvas if needed
|
|
235
|
+
if (this.currentCanvasSize.width !== outWidth || this.currentCanvasSize.height !== outHeight) {
|
|
236
|
+
this.canvas.width = outWidth;
|
|
237
|
+
this.canvas.height = outHeight;
|
|
238
|
+
this.currentCanvasSize = { width: outWidth, height: outHeight };
|
|
239
|
+
gl.viewport(0, 0, outWidth, outHeight);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Update uniforms
|
|
243
|
+
gl.uniform2f(this.uniforms.uRes, outWidth, outHeight);
|
|
244
|
+
gl.uniform2f(this.uniforms.uWarp, options.warpX ?? 0.015, options.warpY ?? 0.02);
|
|
245
|
+
gl.uniform1f(this.uniforms.uScanHardness, options.scanHardness ?? -4.0);
|
|
246
|
+
gl.uniform1f(this.uniforms.uScanOpacity, options.scanOpacity ?? 0.5);
|
|
247
|
+
gl.uniform1f(this.uniforms.uMaskOpacity, options.maskOpacity ?? 0.3);
|
|
248
|
+
gl.uniform1i(this.uniforms.uEnableWarp, options.enableWarp !== false ? 1 : 0);
|
|
249
|
+
gl.uniform1i(this.uniforms.uEnableScanlines, options.enableScanlines !== false ? 1 : 0);
|
|
250
|
+
gl.uniform1i(this.uniforms.uEnableMask, options.enableMask !== false ? 1 : 0);
|
|
251
|
+
|
|
252
|
+
// Update texture
|
|
253
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
254
|
+
if (this.currentTexSize.width !== width || this.currentTexSize.height !== height) {
|
|
255
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
256
|
+
this.currentTexSize = { width, height };
|
|
257
|
+
} else {
|
|
258
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Render
|
|
262
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
263
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
264
|
+
|
|
265
|
+
// Read pixels
|
|
266
|
+
const pixels = new Uint8ClampedArray(outWidth * outHeight * 4);
|
|
267
|
+
gl.readPixels(0, 0, outWidth, outHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
data: pixels,
|
|
271
|
+
width: outWidth,
|
|
272
|
+
height: outHeight,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** Dispose resources */
|
|
277
|
+
dispose(): void {
|
|
278
|
+
if (this.gl) {
|
|
279
|
+
if (this.texture) this.gl.deleteTexture(this.texture);
|
|
280
|
+
if (this.program) this.gl.deleteProgram(this.program);
|
|
281
|
+
this.gl = null;
|
|
282
|
+
}
|
|
283
|
+
this.canvas = null;
|
|
284
|
+
this.initialized = false;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** CRT presets */
|
|
289
|
+
export const CRT_PRESETS: Record<string, Partial<CrtOptions>> = {
|
|
290
|
+
default: {},
|
|
291
|
+
authentic: {
|
|
292
|
+
warpX: 0.02,
|
|
293
|
+
warpY: 0.025,
|
|
294
|
+
scanHardness: -6.0,
|
|
295
|
+
scanOpacity: 0.6,
|
|
296
|
+
maskOpacity: 0.4,
|
|
297
|
+
},
|
|
298
|
+
subtle: {
|
|
299
|
+
warpX: 0.008,
|
|
300
|
+
warpY: 0.01,
|
|
301
|
+
scanHardness: -3.0,
|
|
302
|
+
scanOpacity: 0.3,
|
|
303
|
+
maskOpacity: 0.15,
|
|
304
|
+
},
|
|
305
|
+
flat: {
|
|
306
|
+
warpX: 0,
|
|
307
|
+
warpY: 0,
|
|
308
|
+
enableWarp: false,
|
|
309
|
+
scanHardness: -4.0,
|
|
310
|
+
scanOpacity: 0.5,
|
|
311
|
+
maskOpacity: 0.3,
|
|
312
|
+
},
|
|
313
|
+
};
|