@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/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# @pixagram/renderart
|
|
2
2
|
|
|
3
|
-
High-performance pixel art rendering engines with GPU
|
|
3
|
+
High-performance pixel art rendering engines with WebGL2 GPU acceleration and WebAssembly support.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **CRT Effect** -
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
7
|
+
- **CRT Effect** - Authentic CRT display simulation with scanlines, shadow mask, and barrel distortion
|
|
8
|
+
- **Hexagonal Grid** - Transform pixel art into hexagonal pixel representations
|
|
9
|
+
- **xBRZ Upscaling** - Advanced pixel art upscaling algorithm (2x-6x) that preserves sharp edges
|
|
10
|
+
|
|
11
|
+
All renderers are available in two implementations:
|
|
12
|
+
- **GPU (WebGL2)** - High-performance fragment shader-based rendering
|
|
13
|
+
- **WASM** - Rust-compiled WebAssembly for environments without WebGL2
|
|
10
14
|
|
|
11
15
|
## Installation
|
|
12
16
|
|
|
@@ -16,102 +20,202 @@ npm install @pixagram/renderart
|
|
|
16
20
|
|
|
17
21
|
## Quick Start
|
|
18
22
|
|
|
19
|
-
### GPU Only (Simplest)
|
|
20
|
-
|
|
21
23
|
```typescript
|
|
22
|
-
import {
|
|
24
|
+
import { CrtGpuRenderer, HexGpuRenderer, XbrzGpuRenderer } from '@pixagram/renderart';
|
|
25
|
+
|
|
26
|
+
// Create a renderer
|
|
27
|
+
const crt = CrtGpuRenderer.create();
|
|
28
|
+
|
|
29
|
+
// Render an image
|
|
30
|
+
const result = crt.render(imageData, {
|
|
31
|
+
scale: 3,
|
|
32
|
+
warpX: 0.015,
|
|
33
|
+
warpY: 0.02,
|
|
34
|
+
scanOpacity: 0.5,
|
|
35
|
+
maskOpacity: 0.3,
|
|
36
|
+
});
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
const
|
|
38
|
+
// Use the result
|
|
39
|
+
const outputImageData = new ImageData(result.data, result.width, result.height);
|
|
40
|
+
|
|
41
|
+
// Clean up when done
|
|
42
|
+
crt.dispose();
|
|
26
43
|
```
|
|
27
44
|
|
|
28
|
-
|
|
45
|
+
## CRT Renderer
|
|
46
|
+
|
|
47
|
+
Simulates classic CRT display characteristics including barrel distortion, scanlines, and RGB shadow mask.
|
|
29
48
|
|
|
30
49
|
```typescript
|
|
31
|
-
|
|
32
|
-
import init, * as wasm from '@pixagram/renderart/wasm';
|
|
50
|
+
import { CrtGpuRenderer, CRT_PRESETS } from '@pixagram/renderart';
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
import { initWasm, RenderArt } from '@pixagram/renderart';
|
|
52
|
+
const renderer = CrtGpuRenderer.create();
|
|
36
53
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
54
|
+
// Use default settings
|
|
55
|
+
const output = renderer.render(input, { scale: 3 });
|
|
56
|
+
|
|
57
|
+
// Or use a preset
|
|
58
|
+
const output = renderer.render(input, {
|
|
59
|
+
...CRT_PRESETS.authentic,
|
|
60
|
+
scale: 4,
|
|
61
|
+
});
|
|
40
62
|
|
|
41
|
-
//
|
|
42
|
-
const renderer = RenderArt.create();
|
|
43
|
-
const result = renderer.crt.render(imageData, { scale: 3 });
|
|
63
|
+
// Available presets: default, authentic, subtle, flat
|
|
44
64
|
```
|
|
45
65
|
|
|
46
|
-
###
|
|
66
|
+
### CRT Options
|
|
67
|
+
|
|
68
|
+
| Option | Type | Default | Description |
|
|
69
|
+
|--------|------|---------|-------------|
|
|
70
|
+
| `scale` | number | 3 | Output scale factor (2-32) |
|
|
71
|
+
| `warpX` | number | 0.015 | Horizontal barrel distortion |
|
|
72
|
+
| `warpY` | number | 0.02 | Vertical barrel distortion |
|
|
73
|
+
| `scanHardness` | number | -4.0 | Scanline edge sharpness |
|
|
74
|
+
| `scanOpacity` | number | 0.5 | Scanline visibility (0-1) |
|
|
75
|
+
| `maskOpacity` | number | 0.3 | Shadow mask visibility (0-1) |
|
|
76
|
+
| `enableWarp` | boolean | true | Enable barrel distortion |
|
|
77
|
+
| `enableScanlines` | boolean | true | Enable scanline effect |
|
|
78
|
+
| `enableMask` | boolean | true | Enable shadow mask |
|
|
79
|
+
|
|
80
|
+
## Hexagonal Renderer
|
|
81
|
+
|
|
82
|
+
Transforms rectangular pixels into a hexagonal grid pattern.
|
|
47
83
|
|
|
48
84
|
```typescript
|
|
49
|
-
import {
|
|
85
|
+
import { HexGpuRenderer, hexGetDimensions, HEX_PRESETS } from '@pixagram/renderart';
|
|
50
86
|
|
|
51
|
-
const
|
|
52
|
-
const result = crt.render(imageData, { scale: 3 });
|
|
53
|
-
crt.dispose();
|
|
54
|
-
```
|
|
87
|
+
const renderer = HexGpuRenderer.create();
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
// Get output dimensions before rendering
|
|
90
|
+
const dims = hexGetDimensions(inputWidth, inputHeight, 16, 'flat-top');
|
|
91
|
+
console.log(`Output: ${dims.width}x${dims.height}`);
|
|
57
92
|
|
|
58
|
-
|
|
93
|
+
// Render
|
|
94
|
+
const output = renderer.render(input, {
|
|
95
|
+
scale: 16,
|
|
96
|
+
orientation: 'flat-top',
|
|
97
|
+
drawBorders: true,
|
|
98
|
+
borderColor: '#282828',
|
|
99
|
+
});
|
|
59
100
|
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
scale: 3, // 2-32
|
|
63
|
-
warpX: 0.015, // Horizontal curvature
|
|
64
|
-
warpY: 0.02, // Vertical curvature
|
|
65
|
-
scanHardness: -4.0,
|
|
66
|
-
scanOpacity: 0.5,
|
|
67
|
-
maskOpacity: 0.3,
|
|
68
|
-
enableWarp: true,
|
|
69
|
-
enableScanlines: true,
|
|
70
|
-
enableMask: true,
|
|
71
|
-
}
|
|
101
|
+
// Available presets: default, bordered, pointy
|
|
72
102
|
```
|
|
73
103
|
|
|
74
|
-
###
|
|
104
|
+
### Hex Options
|
|
105
|
+
|
|
106
|
+
| Option | Type | Default | Description |
|
|
107
|
+
|--------|------|---------|-------------|
|
|
108
|
+
| `scale` | number | 16 | Hexagon size (2-32) |
|
|
109
|
+
| `orientation` | string | 'flat-top' | 'flat-top' or 'pointy-top' |
|
|
110
|
+
| `drawBorders` | boolean | false | Draw borders between hexagons |
|
|
111
|
+
| `borderColor` | string/number | '#282828' | Border color |
|
|
112
|
+
| `borderThickness` | number | 1 | Border width in pixels |
|
|
113
|
+
| `backgroundColor` | string/number | 'transparent' | Background color |
|
|
114
|
+
|
|
115
|
+
## xBRZ Renderer
|
|
116
|
+
|
|
117
|
+
Implements the xBRZ pixel art upscaling algorithm, which intelligently interpolates edges while preserving pixel art characteristics.
|
|
75
118
|
|
|
76
119
|
```typescript
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
120
|
+
import { XbrzGpuRenderer, XBRZ_PRESETS } from '@pixagram/renderart';
|
|
121
|
+
|
|
122
|
+
const renderer = XbrzGpuRenderer.create();
|
|
123
|
+
|
|
124
|
+
// 4x upscale with default settings
|
|
125
|
+
const output = renderer.render(input, { scale: 4 });
|
|
126
|
+
|
|
127
|
+
// Use sharp preset for crisper edges
|
|
128
|
+
const output = renderer.render(input, {
|
|
129
|
+
...XBRZ_PRESETS.sharp,
|
|
130
|
+
scale: 3,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Available presets: default, sharp, smooth, colorful
|
|
84
134
|
```
|
|
85
135
|
|
|
86
|
-
###
|
|
136
|
+
### xBRZ Options
|
|
137
|
+
|
|
138
|
+
| Option | Type | Default | Description |
|
|
139
|
+
|--------|------|---------|-------------|
|
|
140
|
+
| `scale` | number | 2 | Scale factor (2-6) |
|
|
141
|
+
| `luminanceWeight` | number | 1.0 | Weight for luminance in color comparison |
|
|
142
|
+
| `equalColorTolerance` | number | 30 | Tolerance for color equality (0-255) |
|
|
143
|
+
| `steepDirectionThreshold` | number | 2.2 | Threshold for steep edge detection |
|
|
144
|
+
| `dominantDirectionThreshold` | number | 3.6 | Threshold for dominant direction |
|
|
145
|
+
|
|
146
|
+
## WASM Module
|
|
147
|
+
|
|
148
|
+
For environments without WebGL2 support, use the WASM implementation:
|
|
87
149
|
|
|
88
150
|
```typescript
|
|
89
|
-
{
|
|
90
|
-
scale: 4, // 2-6
|
|
91
|
-
luminanceWeight: 1.0,
|
|
92
|
-
equalColorTolerance: 30,
|
|
93
|
-
}
|
|
94
|
-
```
|
|
151
|
+
import init, { crt_upscale, hex_upscale, xbrz_upscale, get_memory } from '@pixagram/renderart/wasm';
|
|
95
152
|
|
|
96
|
-
|
|
153
|
+
// Initialize WASM module
|
|
154
|
+
await init();
|
|
97
155
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
156
|
+
// Convert ImageData to Uint8Array
|
|
157
|
+
const inputData = new Uint8Array(imageData.data.buffer);
|
|
158
|
+
|
|
159
|
+
// Render
|
|
160
|
+
const result = crt_upscale(inputData, width, height, scale);
|
|
161
|
+
|
|
162
|
+
// Read output from WASM memory
|
|
163
|
+
const memory = get_memory();
|
|
164
|
+
const output = new Uint8ClampedArray(
|
|
165
|
+
memory.buffer,
|
|
166
|
+
result.ptr,
|
|
167
|
+
result.len
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// Create ImageData
|
|
171
|
+
const outputImageData = new ImageData(
|
|
172
|
+
new Uint8ClampedArray(output), // Copy the data
|
|
173
|
+
result.width,
|
|
174
|
+
result.height
|
|
175
|
+
);
|
|
104
176
|
```
|
|
105
177
|
|
|
106
178
|
## Building from Source
|
|
107
179
|
|
|
180
|
+
### Prerequisites
|
|
181
|
+
|
|
182
|
+
- Node.js 18+
|
|
183
|
+
- Rust toolchain with `wasm32-unknown-unknown` target
|
|
184
|
+
- wasm-pack
|
|
185
|
+
|
|
186
|
+
### Build
|
|
187
|
+
|
|
108
188
|
```bash
|
|
109
|
-
#
|
|
110
|
-
npm
|
|
111
|
-
|
|
112
|
-
|
|
189
|
+
# Install dependencies
|
|
190
|
+
npm install
|
|
191
|
+
|
|
192
|
+
# Build everything (TypeScript + WASM)
|
|
193
|
+
npm run build
|
|
194
|
+
|
|
195
|
+
# Build only TypeScript
|
|
196
|
+
npm run build:ts
|
|
197
|
+
|
|
198
|
+
# Build only WASM
|
|
199
|
+
npm run build:wasm
|
|
113
200
|
```
|
|
114
201
|
|
|
202
|
+
## Browser Support
|
|
203
|
+
|
|
204
|
+
- **GPU Renderers**: Requires WebGL2 (Chrome 56+, Firefox 51+, Safari 15+, Edge 79+)
|
|
205
|
+
- **WASM Module**: Requires WebAssembly (all modern browsers)
|
|
206
|
+
|
|
207
|
+
## Performance
|
|
208
|
+
|
|
209
|
+
The GPU renderers leverage fragment shaders for parallel pixel processing:
|
|
210
|
+
|
|
211
|
+
| Renderer | 256x256 → 3x | 512x512 → 3x |
|
|
212
|
+
|----------|--------------|--------------|
|
|
213
|
+
| CRT GPU | ~2ms | ~5ms |
|
|
214
|
+
| HEX GPU | ~3ms | ~8ms |
|
|
215
|
+
| xBRZ GPU | ~4ms | ~12ms |
|
|
216
|
+
|
|
217
|
+
WASM performance is typically 3-5x slower but provides consistent results across all platforms.
|
|
218
|
+
|
|
115
219
|
## License
|
|
116
220
|
|
|
117
|
-
MIT
|
|
221
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRT GPU Renderer using WebGL2
|
|
3
|
+
*
|
|
4
|
+
* High-performance CRT effect rendering using fragment shaders.
|
|
5
|
+
*/
|
|
6
|
+
import type { CrtOptions, ImageInput, ImageOutput, Renderer } from './types.js';
|
|
7
|
+
/** CRT GPU Renderer */
|
|
8
|
+
export declare class CrtGpuRenderer implements Renderer<CrtOptions> {
|
|
9
|
+
private gl;
|
|
10
|
+
private canvas;
|
|
11
|
+
private program;
|
|
12
|
+
private texture;
|
|
13
|
+
private uniforms;
|
|
14
|
+
private initialized;
|
|
15
|
+
private currentCanvasSize;
|
|
16
|
+
private currentTexSize;
|
|
17
|
+
/** Create a new CRT GPU renderer */
|
|
18
|
+
static create(): CrtGpuRenderer;
|
|
19
|
+
private init;
|
|
20
|
+
private createShader;
|
|
21
|
+
/** Check if renderer is ready */
|
|
22
|
+
isReady(): boolean;
|
|
23
|
+
/** Render CRT effect */
|
|
24
|
+
render(input: ImageInput | ImageData, options?: CrtOptions): ImageOutput;
|
|
25
|
+
/** Dispose resources */
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
/** CRT presets */
|
|
29
|
+
export declare const CRT_PRESETS: Record<string, Partial<CrtOptions>>;
|
|
30
|
+
//# sourceMappingURL=crt-gpu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crt-gpu.d.ts","sourceRoot":"","sources":["../src/crt-gpu.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAuGhF,uBAAuB;AACvB,qBAAa,cAAe,YAAW,QAAQ,CAAC,UAAU,CAAC;IACzD,OAAO,CAAC,EAAE,CAAuC;IACjD,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAAmD;IACnE,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,cAAc,CAA2B;IAEjD,oCAAoC;IACpC,MAAM,CAAC,MAAM,IAAI,cAAc;IAM/B,OAAO,CAAC,IAAI;IAuEZ,OAAO,CAAC,YAAY;IAepB,iCAAiC;IACjC,OAAO,IAAI,OAAO;IAIlB,wBAAwB;IACxB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,OAAO,GAAE,UAAe,GAAG,WAAW;IAwD5E,wBAAwB;IACxB,OAAO,IAAI,IAAI;CAShB;AAED,kBAAkB;AAClB,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAwB3D,CAAC"}
|
package/dist/crt-gpu.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRT GPU Renderer using WebGL2
|
|
3
|
+
*
|
|
4
|
+
* High-performance CRT effect rendering using fragment shaders.
|
|
5
|
+
*/
|
|
6
|
+
// Vertex shader
|
|
7
|
+
const VERTEX_SHADER = `#version 300 es
|
|
8
|
+
layout(location = 0) in vec2 position;
|
|
9
|
+
out vec2 vUv;
|
|
10
|
+
|
|
11
|
+
void main() {
|
|
12
|
+
vUv = position * 0.5 + 0.5;
|
|
13
|
+
gl_Position = vec4(position, 0.0, 1.0);
|
|
14
|
+
}`;
|
|
15
|
+
// Fragment shader with configurable CRT effects
|
|
16
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
17
|
+
precision highp float;
|
|
18
|
+
|
|
19
|
+
uniform sampler2D uTex;
|
|
20
|
+
uniform vec2 uRes;
|
|
21
|
+
uniform vec2 uWarp;
|
|
22
|
+
uniform float uScanHardness;
|
|
23
|
+
uniform float uScanOpacity;
|
|
24
|
+
uniform float uMaskOpacity;
|
|
25
|
+
uniform int uEnableWarp;
|
|
26
|
+
uniform int uEnableScanlines;
|
|
27
|
+
uniform int uEnableMask;
|
|
28
|
+
|
|
29
|
+
in vec2 vUv;
|
|
30
|
+
out vec4 outColor;
|
|
31
|
+
|
|
32
|
+
// Gamma 2.0 approximation
|
|
33
|
+
vec3 toLinear(vec3 c) { return c * c; }
|
|
34
|
+
vec3 toSrgb(vec3 c) { return sqrt(c); }
|
|
35
|
+
|
|
36
|
+
vec2 warp(vec2 uv) {
|
|
37
|
+
if (uEnableWarp == 0) return uv;
|
|
38
|
+
vec2 dc = abs(0.5 - uv);
|
|
39
|
+
vec2 dc2 = dc * dc;
|
|
40
|
+
uv.x -= 0.5; uv.x *= 1.0 + (dc2.y * (0.3 * uWarp.x)); uv.x += 0.5;
|
|
41
|
+
uv.y -= 0.5; uv.y *= 1.0 + (dc2.x * (0.4 * uWarp.y)); uv.y += 0.5;
|
|
42
|
+
return uv;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
float scanline(float y, float sourceHeight) {
|
|
46
|
+
if (uEnableScanlines == 0) return 1.0;
|
|
47
|
+
float v = fract(y * sourceHeight);
|
|
48
|
+
float d = abs(v - 0.5);
|
|
49
|
+
float line = exp(d * d * uScanHardness);
|
|
50
|
+
return mix(1.0, line, uScanOpacity);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
vec3 mask(vec2 pos) {
|
|
54
|
+
if (uEnableMask == 0) return vec3(1.0);
|
|
55
|
+
float x = fract(pos.x / 6.0);
|
|
56
|
+
vec3 m = vec3(1.0);
|
|
57
|
+
float step1 = 0.333;
|
|
58
|
+
float step2 = 0.666;
|
|
59
|
+
|
|
60
|
+
m.r = step(0.0, x) - step(step1, x);
|
|
61
|
+
m.g = step(step1, x) - step(step2, x);
|
|
62
|
+
m.b = step(step2, x) - step(1.0, x);
|
|
63
|
+
|
|
64
|
+
return mix(vec3(1.0), m, uMaskOpacity);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
void main() {
|
|
68
|
+
// 1. Geometry
|
|
69
|
+
vec2 uv = warp(vUv);
|
|
70
|
+
|
|
71
|
+
// 2. Bounds Check
|
|
72
|
+
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
|
73
|
+
outColor = vec4(0.0);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 3. Texture Sample
|
|
78
|
+
vec4 texSample = texture(uTex, uv);
|
|
79
|
+
|
|
80
|
+
if (texSample.a == 0.0) {
|
|
81
|
+
outColor = vec4(0.0);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
vec3 linearColor = toLinear(texSample.rgb);
|
|
86
|
+
|
|
87
|
+
// 4. CRT Effects
|
|
88
|
+
ivec2 texSize = textureSize(uTex, 0);
|
|
89
|
+
|
|
90
|
+
// Smart Bloom
|
|
91
|
+
float luma = dot(linearColor, vec3(0.299, 0.587, 0.114));
|
|
92
|
+
float bloom = luma * 0.7;
|
|
93
|
+
|
|
94
|
+
// Calculate patterns
|
|
95
|
+
float scan = scanline(uv.y, float(texSize.y));
|
|
96
|
+
vec3 m = mask(gl_FragCoord.xy);
|
|
97
|
+
|
|
98
|
+
// Apply effects
|
|
99
|
+
vec3 effects = m * scan;
|
|
100
|
+
vec3 finalRGB = linearColor * mix(effects, vec3(1.0), bloom);
|
|
101
|
+
|
|
102
|
+
// 5. Output
|
|
103
|
+
outColor = vec4(toSrgb(finalRGB), texSample.a);
|
|
104
|
+
}`;
|
|
105
|
+
/** CRT GPU Renderer */
|
|
106
|
+
export class CrtGpuRenderer {
|
|
107
|
+
gl = null;
|
|
108
|
+
canvas = null;
|
|
109
|
+
program = null;
|
|
110
|
+
texture = null;
|
|
111
|
+
uniforms = {};
|
|
112
|
+
initialized = false;
|
|
113
|
+
currentCanvasSize = { width: 0, height: 0 };
|
|
114
|
+
currentTexSize = { width: 0, height: 0 };
|
|
115
|
+
/** Create a new CRT GPU renderer */
|
|
116
|
+
static create() {
|
|
117
|
+
const renderer = new CrtGpuRenderer();
|
|
118
|
+
renderer.init();
|
|
119
|
+
return renderer;
|
|
120
|
+
}
|
|
121
|
+
init() {
|
|
122
|
+
if (typeof OffscreenCanvas === 'undefined') {
|
|
123
|
+
throw new Error('OffscreenCanvas not supported');
|
|
124
|
+
}
|
|
125
|
+
this.canvas = new OffscreenCanvas(1, 1);
|
|
126
|
+
this.gl = this.canvas.getContext('webgl2', {
|
|
127
|
+
alpha: true,
|
|
128
|
+
premultipliedAlpha: false,
|
|
129
|
+
desynchronized: true,
|
|
130
|
+
powerPreference: 'high-performance',
|
|
131
|
+
antialias: false,
|
|
132
|
+
});
|
|
133
|
+
if (!this.gl) {
|
|
134
|
+
throw new Error('WebGL2 not supported');
|
|
135
|
+
}
|
|
136
|
+
const gl = this.gl;
|
|
137
|
+
// Create shaders
|
|
138
|
+
const vs = this.createShader(gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
139
|
+
const fs = this.createShader(gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
140
|
+
// Create program
|
|
141
|
+
this.program = gl.createProgram();
|
|
142
|
+
gl.attachShader(this.program, vs);
|
|
143
|
+
gl.attachShader(this.program, fs);
|
|
144
|
+
gl.linkProgram(this.program);
|
|
145
|
+
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) {
|
|
146
|
+
throw new Error('Shader program link failed: ' + gl.getProgramInfoLog(this.program));
|
|
147
|
+
}
|
|
148
|
+
gl.useProgram(this.program);
|
|
149
|
+
// Get uniform locations
|
|
150
|
+
this.uniforms = {
|
|
151
|
+
uTex: gl.getUniformLocation(this.program, 'uTex'),
|
|
152
|
+
uRes: gl.getUniformLocation(this.program, 'uRes'),
|
|
153
|
+
uWarp: gl.getUniformLocation(this.program, 'uWarp'),
|
|
154
|
+
uScanHardness: gl.getUniformLocation(this.program, 'uScanHardness'),
|
|
155
|
+
uScanOpacity: gl.getUniformLocation(this.program, 'uScanOpacity'),
|
|
156
|
+
uMaskOpacity: gl.getUniformLocation(this.program, 'uMaskOpacity'),
|
|
157
|
+
uEnableWarp: gl.getUniformLocation(this.program, 'uEnableWarp'),
|
|
158
|
+
uEnableScanlines: gl.getUniformLocation(this.program, 'uEnableScanlines'),
|
|
159
|
+
uEnableMask: gl.getUniformLocation(this.program, 'uEnableMask'),
|
|
160
|
+
};
|
|
161
|
+
gl.uniform1i(this.uniforms.uTex, 0);
|
|
162
|
+
// Setup geometry (fullscreen triangle)
|
|
163
|
+
const buf = gl.createBuffer();
|
|
164
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
165
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
|
166
|
+
gl.enableVertexAttribArray(0);
|
|
167
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
168
|
+
// Create texture
|
|
169
|
+
this.texture = gl.createTexture();
|
|
170
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
171
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
172
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
173
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
174
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
175
|
+
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
176
|
+
this.initialized = true;
|
|
177
|
+
}
|
|
178
|
+
createShader(type, source) {
|
|
179
|
+
const gl = this.gl;
|
|
180
|
+
const shader = gl.createShader(type);
|
|
181
|
+
gl.shaderSource(shader, source);
|
|
182
|
+
gl.compileShader(shader);
|
|
183
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
184
|
+
const info = gl.getShaderInfoLog(shader);
|
|
185
|
+
gl.deleteShader(shader);
|
|
186
|
+
throw new Error('Shader compile failed: ' + info);
|
|
187
|
+
}
|
|
188
|
+
return shader;
|
|
189
|
+
}
|
|
190
|
+
/** Check if renderer is ready */
|
|
191
|
+
isReady() {
|
|
192
|
+
return this.initialized;
|
|
193
|
+
}
|
|
194
|
+
/** Render CRT effect */
|
|
195
|
+
render(input, options = {}) {
|
|
196
|
+
if (!this.initialized || !this.gl || !this.canvas) {
|
|
197
|
+
throw new Error('Renderer not initialized');
|
|
198
|
+
}
|
|
199
|
+
const gl = this.gl;
|
|
200
|
+
const data = input instanceof ImageData ? input.data : input.data;
|
|
201
|
+
const width = input.width;
|
|
202
|
+
const height = input.height;
|
|
203
|
+
const scale = Math.min(32, Math.max(2, options.scale ?? 3));
|
|
204
|
+
const outWidth = width * scale;
|
|
205
|
+
const outHeight = height * scale;
|
|
206
|
+
// Resize canvas if needed
|
|
207
|
+
if (this.currentCanvasSize.width !== outWidth || this.currentCanvasSize.height !== outHeight) {
|
|
208
|
+
this.canvas.width = outWidth;
|
|
209
|
+
this.canvas.height = outHeight;
|
|
210
|
+
this.currentCanvasSize = { width: outWidth, height: outHeight };
|
|
211
|
+
gl.viewport(0, 0, outWidth, outHeight);
|
|
212
|
+
}
|
|
213
|
+
// Update uniforms
|
|
214
|
+
gl.uniform2f(this.uniforms.uRes, outWidth, outHeight);
|
|
215
|
+
gl.uniform2f(this.uniforms.uWarp, options.warpX ?? 0.015, options.warpY ?? 0.02);
|
|
216
|
+
gl.uniform1f(this.uniforms.uScanHardness, options.scanHardness ?? -4.0);
|
|
217
|
+
gl.uniform1f(this.uniforms.uScanOpacity, options.scanOpacity ?? 0.5);
|
|
218
|
+
gl.uniform1f(this.uniforms.uMaskOpacity, options.maskOpacity ?? 0.3);
|
|
219
|
+
gl.uniform1i(this.uniforms.uEnableWarp, options.enableWarp !== false ? 1 : 0);
|
|
220
|
+
gl.uniform1i(this.uniforms.uEnableScanlines, options.enableScanlines !== false ? 1 : 0);
|
|
221
|
+
gl.uniform1i(this.uniforms.uEnableMask, options.enableMask !== false ? 1 : 0);
|
|
222
|
+
// Update texture
|
|
223
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
224
|
+
if (this.currentTexSize.width !== width || this.currentTexSize.height !== height) {
|
|
225
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
226
|
+
this.currentTexSize = { width, height };
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
230
|
+
}
|
|
231
|
+
// Render
|
|
232
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
233
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
234
|
+
// Read pixels
|
|
235
|
+
const pixels = new Uint8ClampedArray(outWidth * outHeight * 4);
|
|
236
|
+
gl.readPixels(0, 0, outWidth, outHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
237
|
+
return {
|
|
238
|
+
data: pixels,
|
|
239
|
+
width: outWidth,
|
|
240
|
+
height: outHeight,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/** Dispose resources */
|
|
244
|
+
dispose() {
|
|
245
|
+
if (this.gl) {
|
|
246
|
+
if (this.texture)
|
|
247
|
+
this.gl.deleteTexture(this.texture);
|
|
248
|
+
if (this.program)
|
|
249
|
+
this.gl.deleteProgram(this.program);
|
|
250
|
+
this.gl = null;
|
|
251
|
+
}
|
|
252
|
+
this.canvas = null;
|
|
253
|
+
this.initialized = false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/** CRT presets */
|
|
257
|
+
export const CRT_PRESETS = {
|
|
258
|
+
default: {},
|
|
259
|
+
authentic: {
|
|
260
|
+
warpX: 0.02,
|
|
261
|
+
warpY: 0.025,
|
|
262
|
+
scanHardness: -6.0,
|
|
263
|
+
scanOpacity: 0.6,
|
|
264
|
+
maskOpacity: 0.4,
|
|
265
|
+
},
|
|
266
|
+
subtle: {
|
|
267
|
+
warpX: 0.008,
|
|
268
|
+
warpY: 0.01,
|
|
269
|
+
scanHardness: -3.0,
|
|
270
|
+
scanOpacity: 0.3,
|
|
271
|
+
maskOpacity: 0.15,
|
|
272
|
+
},
|
|
273
|
+
flat: {
|
|
274
|
+
warpX: 0,
|
|
275
|
+
warpY: 0,
|
|
276
|
+
enableWarp: false,
|
|
277
|
+
scanHardness: -4.0,
|
|
278
|
+
scanOpacity: 0.5,
|
|
279
|
+
maskOpacity: 0.3,
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
//# sourceMappingURL=crt-gpu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crt-gpu.js","sourceRoot":"","sources":["../src/crt-gpu.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hexagonal GPU Renderer using WebGL2
|
|
3
|
+
*
|
|
4
|
+
* High-performance hexagonal pixel grid transformation using fragment shaders.
|
|
5
|
+
*/
|
|
6
|
+
import type { HexOptions, HexOrientation, ImageInput, ImageOutput, Renderer } from './types.js';
|
|
7
|
+
/** Calculate output dimensions for hex rendering */
|
|
8
|
+
export declare function hexGetDimensions(srcWidth: number, srcHeight: number, scale: number, orientation?: HexOrientation): {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
/** HEX GPU Renderer */
|
|
13
|
+
export declare class HexGpuRenderer implements Renderer<HexOptions> {
|
|
14
|
+
private gl;
|
|
15
|
+
private canvas;
|
|
16
|
+
private program;
|
|
17
|
+
private texture;
|
|
18
|
+
private uniforms;
|
|
19
|
+
private initialized;
|
|
20
|
+
private currentCanvasSize;
|
|
21
|
+
private currentTexSize;
|
|
22
|
+
/** Create a new HEX GPU renderer */
|
|
23
|
+
static create(): HexGpuRenderer;
|
|
24
|
+
private init;
|
|
25
|
+
private createShader;
|
|
26
|
+
/** Check if renderer is ready */
|
|
27
|
+
isReady(): boolean;
|
|
28
|
+
/** Render hexagonal effect */
|
|
29
|
+
render(input: ImageInput | ImageData, options?: HexOptions): ImageOutput;
|
|
30
|
+
/** Dispose resources */
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|
|
33
|
+
/** HEX presets */
|
|
34
|
+
export declare const HEX_PRESETS: Record<string, Partial<HexOptions>>;
|
|
35
|
+
//# sourceMappingURL=hex-gpu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hex-gpu.d.ts","sourceRoot":"","sources":["../src/hex-gpu.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiMhG,oDAAoD;AACpD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,cAA2B,GACvC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAwBnC;AAED,uBAAuB;AACvB,qBAAa,cAAe,YAAW,QAAQ,CAAC,UAAU,CAAC;IACzD,OAAO,CAAC,EAAE,CAAuC;IACjD,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAAmD;IACnE,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA2B;IACpD,OAAO,CAAC,cAAc,CAA2B;IAEjD,oCAAoC;IACpC,MAAM,CAAC,MAAM,IAAI,cAAc;IAM/B,OAAO,CAAC,IAAI;IAuEZ,OAAO,CAAC,YAAY;IAepB,iCAAiC;IACjC,OAAO,IAAI,OAAO;IAIlB,8BAA8B;IAC9B,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,OAAO,GAAE,UAAe,GAAG,WAAW;IA4D5E,wBAAwB;IACxB,OAAO,IAAI,IAAI;CAShB;AAED,kBAAkB;AAClB,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAW3D,CAAC"}
|