@craf-te/canvas-buffer-viewer 0.1.0
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/README.ja.md +261 -0
- package/README.md +261 -0
- package/dist/index.cjs +307 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +671 -0
- package/package.json +59 -0
package/README.ja.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Canvas Buffer Viewer
|
|
2
|
+
|
|
3
|
+
WebGLフレームバッファ、レンダーターゲット、Canvas2Dの内容をリアルタイムで可視化する軽量デバッグツールです。複雑なレンダリングパイプラインやポストプロセスエフェクトのデバッグに最適です。
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## 特徴
|
|
8
|
+
|
|
9
|
+
- フレームバッファとレンダーターゲットをサムネイルオーバーレイとして**リアルタイム表示**
|
|
10
|
+
- パフォーマンスへの影響を最小限に抑える**FPSスロットリング**
|
|
11
|
+
- **マルチフレームワーク対応**: Three.js、生WebGL、Canvas2D
|
|
12
|
+
- WebGLの下から上へのピクセル順序を**自動フリップ処理**
|
|
13
|
+
- **カスタマイズ可能な配置位置**(左上、右上、左下、右下)
|
|
14
|
+
- **依存関係なし** - Three.jsはオプションでヘルパー使用時のみ必要
|
|
15
|
+
- **Web Components ベース** - Shadow DOMによるカプセル化されたUI
|
|
16
|
+
|
|
17
|
+
## インストール
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install canvas-buffer-viewer
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## クイックスタート
|
|
24
|
+
|
|
25
|
+
### 基本的な使い方
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { BufferViewer } from 'canvas-buffer-viewer';
|
|
29
|
+
|
|
30
|
+
// シングルトンインスタンスを取得
|
|
31
|
+
const viewer = BufferViewer.getInstance({
|
|
32
|
+
fps: 10, // キャプチャレート(デフォルト: 10)
|
|
33
|
+
corner: 'top-right', // 表示位置(デフォルト: 'top-right')
|
|
34
|
+
active: true // 起動時にアクティブ(デフォルト: true)
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// レンダーループ内でバッファをキャプチャ
|
|
38
|
+
viewer.capture('My Buffer', () => ({
|
|
39
|
+
data: pixelData, // RGBA ピクセルの Uint8Array
|
|
40
|
+
width: 512,
|
|
41
|
+
height: 512,
|
|
42
|
+
flipY: true // WebGLはtrue(デフォルト)、Canvas2Dはfalse
|
|
43
|
+
}));
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Three.js との連携
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { BufferViewer, readRenderTarget } from 'canvas-buffer-viewer';
|
|
50
|
+
import * as THREE from 'three';
|
|
51
|
+
|
|
52
|
+
const renderer = new THREE.WebGLRenderer();
|
|
53
|
+
const renderTarget = new THREE.WebGLRenderTarget(512, 512);
|
|
54
|
+
const viewer = BufferViewer.getInstance({ fps: 20 });
|
|
55
|
+
|
|
56
|
+
function animate() {
|
|
57
|
+
// ターゲットにレンダリング
|
|
58
|
+
renderer.setRenderTarget(renderTarget);
|
|
59
|
+
renderer.render(scene, camera);
|
|
60
|
+
|
|
61
|
+
// 可視化用にキャプチャ
|
|
62
|
+
viewer.capture('Scene RT', () => readRenderTarget(renderer, renderTarget));
|
|
63
|
+
|
|
64
|
+
// 画面にレンダリング
|
|
65
|
+
renderer.setRenderTarget(null);
|
|
66
|
+
renderer.render(scene, camera);
|
|
67
|
+
|
|
68
|
+
requestAnimationFrame(animate);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 生 WebGL
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { BufferViewer, readPixels } from 'canvas-buffer-viewer';
|
|
76
|
+
|
|
77
|
+
const canvas = document.createElement('canvas');
|
|
78
|
+
const gl = canvas.getContext('webgl2');
|
|
79
|
+
const viewer = BufferViewer.getInstance();
|
|
80
|
+
|
|
81
|
+
function render() {
|
|
82
|
+
// ... WebGL レンダリングコード ...
|
|
83
|
+
|
|
84
|
+
// 現在のフレームバッファをキャプチャ
|
|
85
|
+
viewer.capture('Main FB', () => readPixels(gl));
|
|
86
|
+
|
|
87
|
+
// または特定のフレームバッファをキャプチャ
|
|
88
|
+
viewer.capture('Shadow Map', () => readPixels(gl, shadowFramebuffer));
|
|
89
|
+
|
|
90
|
+
requestAnimationFrame(render);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Canvas2D
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { BufferViewer, readCanvas } from 'canvas-buffer-viewer';
|
|
98
|
+
|
|
99
|
+
const canvas = document.createElement('canvas');
|
|
100
|
+
const ctx = canvas.getContext('2d');
|
|
101
|
+
const viewer = BufferViewer.getInstance();
|
|
102
|
+
|
|
103
|
+
function render() {
|
|
104
|
+
// ... Canvas2D 描画コード ...
|
|
105
|
+
|
|
106
|
+
// キャンバスの内容をキャプチャ
|
|
107
|
+
viewer.capture('2D Canvas', () => readCanvas(canvas));
|
|
108
|
+
// またはコンテキストを直接渡す
|
|
109
|
+
viewer.capture('2D Canvas', () => readCanvas(ctx));
|
|
110
|
+
|
|
111
|
+
requestAnimationFrame(render);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API リファレンス
|
|
116
|
+
|
|
117
|
+
### `BufferViewer`
|
|
118
|
+
|
|
119
|
+
バッファ可視化を管理するメインクラス。シングルトンパターンを使用。
|
|
120
|
+
|
|
121
|
+
#### `BufferViewer.getInstance(options?)`
|
|
122
|
+
|
|
123
|
+
シングルトンインスタンスを返す。必要に応じて作成。
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
interface ViewerOptions {
|
|
127
|
+
active?: boolean; // 起動時にアクティブ(デフォルト: true)
|
|
128
|
+
fps?: number; // キャプチャレート制限(デフォルト: 10)
|
|
129
|
+
corner?: Corner; // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### `viewer.capture(label, getData, note?)`
|
|
134
|
+
|
|
135
|
+
バッファデータをキャプチャして表示。
|
|
136
|
+
|
|
137
|
+
- `label`: このバッファスロットの一意の識別子
|
|
138
|
+
- `getData`: `CaptureData` を返すコールバック(FPSスロットルが許可した時のみ呼び出される)
|
|
139
|
+
- `note`: ラベルの下に表示されるオプションの説明テキスト
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
interface CaptureData {
|
|
143
|
+
data: Uint8Array; // RGBA ピクセルデータ
|
|
144
|
+
width?: number; // 初回キャプチャ時は必須
|
|
145
|
+
height?: number; // 初回キャプチャ時は必須
|
|
146
|
+
flipY?: boolean; // WebGLはtrue(デフォルト)、Canvas2Dはfalse
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### `viewer.active`
|
|
151
|
+
|
|
152
|
+
アクティブ状態の取得・設定。非アクティブ時はキャプチャがスキップされ、オーバーレイが非表示になる。
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
viewer.active = false; // ビューアを非表示
|
|
156
|
+
viewer.active = true; // ビューアを表示
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `viewer.toggle()`
|
|
160
|
+
|
|
161
|
+
ビューアのオン/オフを切り替え。
|
|
162
|
+
|
|
163
|
+
#### `viewer.setFps(fps)`
|
|
164
|
+
|
|
165
|
+
キャプチャレート制限を変更。
|
|
166
|
+
|
|
167
|
+
#### `viewer.removeBuffer(label)`
|
|
168
|
+
|
|
169
|
+
特定のバッファを表示から削除。
|
|
170
|
+
|
|
171
|
+
#### `viewer.dispose()`
|
|
172
|
+
|
|
173
|
+
全リソースをクリーンアップしてオーバーレイを削除。
|
|
174
|
+
|
|
175
|
+
### ヘルパー関数
|
|
176
|
+
|
|
177
|
+
#### `readRenderTarget(renderer, renderTarget)`
|
|
178
|
+
|
|
179
|
+
Three.js の `WebGLRenderTarget` からピクセルを読み取る。
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { readRenderTarget } from 'canvas-buffer-viewer';
|
|
183
|
+
|
|
184
|
+
viewer.capture('RT', () => readRenderTarget(renderer, myRenderTarget));
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### `readPixels(gl, framebuffer?)`
|
|
188
|
+
|
|
189
|
+
WebGL コンテキストからピクセルを読み取る。`framebuffer` を省略すると現在のバインディングから読み取る。
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { readPixels } from 'canvas-buffer-viewer';
|
|
193
|
+
|
|
194
|
+
// 現在のフレームバッファから読み取り
|
|
195
|
+
viewer.capture('Current', () => readPixels(gl));
|
|
196
|
+
|
|
197
|
+
// 特定のフレームバッファから読み取り
|
|
198
|
+
viewer.capture('Shadow', () => readPixels(gl, shadowFBO));
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### `readCanvas(source)`
|
|
202
|
+
|
|
203
|
+
Canvas2D コンテキストまたはキャンバス要素からピクセルを読み取る。
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { readCanvas } from 'canvas-buffer-viewer';
|
|
207
|
+
|
|
208
|
+
viewer.capture('Canvas', () => readCanvas(canvas));
|
|
209
|
+
viewer.capture('Canvas', () => readCanvas(ctx));
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## ポストプロセスパイプラインのデバッグ
|
|
213
|
+
|
|
214
|
+
マルチパスレンダリングのデバッグは一般的なユースケースです:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { BufferViewer, readRenderTarget } from 'canvas-buffer-viewer';
|
|
218
|
+
|
|
219
|
+
const viewer = BufferViewer.getInstance({ fps: 15 });
|
|
220
|
+
|
|
221
|
+
function render() {
|
|
222
|
+
// パス1: シーン
|
|
223
|
+
renderer.setRenderTarget(sceneRT);
|
|
224
|
+
renderer.render(scene, camera);
|
|
225
|
+
viewer.capture('Scene', () => readRenderTarget(renderer, sceneRT), 'ベースシーンレンダー');
|
|
226
|
+
|
|
227
|
+
// パス2: ブルームしきい値
|
|
228
|
+
renderer.setRenderTarget(bloomRT);
|
|
229
|
+
renderer.render(bloomScene, postCamera);
|
|
230
|
+
viewer.capture('Bloom', () => readRenderTarget(renderer, bloomRT), '明部抽出');
|
|
231
|
+
|
|
232
|
+
// パス3: ブラー
|
|
233
|
+
renderer.setRenderTarget(blurRT);
|
|
234
|
+
renderer.render(blurScene, postCamera);
|
|
235
|
+
viewer.capture('Blur', () => readRenderTarget(renderer, blurRT));
|
|
236
|
+
|
|
237
|
+
// 最終合成
|
|
238
|
+
renderer.setRenderTarget(null);
|
|
239
|
+
renderer.render(compositeScene, postCamera);
|
|
240
|
+
|
|
241
|
+
requestAnimationFrame(render);
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## キーボードショートカットの例
|
|
246
|
+
|
|
247
|
+
便利なトグルショートカットを追加:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
const viewer = BufferViewer.getInstance({ active: false });
|
|
251
|
+
|
|
252
|
+
window.addEventListener('keydown', (e) => {
|
|
253
|
+
if (e.key === 'F2') {
|
|
254
|
+
viewer.toggle();
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## ライセンス
|
|
260
|
+
|
|
261
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Canvas Buffer Viewer
|
|
2
|
+
|
|
3
|
+
A lightweight debug tool for visualizing WebGL framebuffers, render targets, and Canvas2D contents in real-time. Perfect for debugging complex rendering pipelines and post-processing effects.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Real-time visualization** of framebuffers and render targets as thumbnail overlays
|
|
10
|
+
- **FPS throttling** to minimize performance impact during debugging
|
|
11
|
+
- **Multi-framework support**: Three.js, raw WebGL, and Canvas2D
|
|
12
|
+
- **Automatic flip handling** for WebGL's bottom-to-top pixel order
|
|
13
|
+
- **Customizable positioning** (top-left, top-right, bottom-left, bottom-right)
|
|
14
|
+
- **Zero dependencies** - Three.js is optional and only needed for Three.js helpers
|
|
15
|
+
- **Web Components based** - encapsulated UI with Shadow DOM
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install canvas-buffer-viewer
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Basic Usage
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { BufferViewer } from 'canvas-buffer-viewer';
|
|
29
|
+
|
|
30
|
+
// Get the singleton instance
|
|
31
|
+
const viewer = BufferViewer.getInstance({
|
|
32
|
+
fps: 10, // Capture rate (default: 10)
|
|
33
|
+
corner: 'top-right', // Position (default: 'top-right')
|
|
34
|
+
active: true // Start active (default: true)
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// In your render loop, capture buffers
|
|
38
|
+
viewer.capture('My Buffer', () => ({
|
|
39
|
+
data: pixelData, // Uint8Array of RGBA pixels
|
|
40
|
+
width: 512,
|
|
41
|
+
height: 512,
|
|
42
|
+
flipY: true // true for WebGL (default), false for Canvas2D
|
|
43
|
+
}));
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Three.js Integration
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { BufferViewer, readRenderTarget } from 'canvas-buffer-viewer';
|
|
50
|
+
import * as THREE from 'three';
|
|
51
|
+
|
|
52
|
+
const renderer = new THREE.WebGLRenderer();
|
|
53
|
+
const renderTarget = new THREE.WebGLRenderTarget(512, 512);
|
|
54
|
+
const viewer = BufferViewer.getInstance({ fps: 20 });
|
|
55
|
+
|
|
56
|
+
function animate() {
|
|
57
|
+
// Render to target
|
|
58
|
+
renderer.setRenderTarget(renderTarget);
|
|
59
|
+
renderer.render(scene, camera);
|
|
60
|
+
|
|
61
|
+
// Capture for visualization
|
|
62
|
+
viewer.capture('Scene RT', () => readRenderTarget(renderer, renderTarget));
|
|
63
|
+
|
|
64
|
+
// Render to screen
|
|
65
|
+
renderer.setRenderTarget(null);
|
|
66
|
+
renderer.render(scene, camera);
|
|
67
|
+
|
|
68
|
+
requestAnimationFrame(animate);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Raw WebGL
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { BufferViewer, readPixels } from 'canvas-buffer-viewer';
|
|
76
|
+
|
|
77
|
+
const canvas = document.createElement('canvas');
|
|
78
|
+
const gl = canvas.getContext('webgl2');
|
|
79
|
+
const viewer = BufferViewer.getInstance();
|
|
80
|
+
|
|
81
|
+
function render() {
|
|
82
|
+
// ... your WebGL rendering code ...
|
|
83
|
+
|
|
84
|
+
// Capture the current framebuffer
|
|
85
|
+
viewer.capture('Main FB', () => readPixels(gl));
|
|
86
|
+
|
|
87
|
+
// Or capture a specific framebuffer
|
|
88
|
+
viewer.capture('Shadow Map', () => readPixels(gl, shadowFramebuffer));
|
|
89
|
+
|
|
90
|
+
requestAnimationFrame(render);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Canvas2D
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { BufferViewer, readCanvas } from 'canvas-buffer-viewer';
|
|
98
|
+
|
|
99
|
+
const canvas = document.createElement('canvas');
|
|
100
|
+
const ctx = canvas.getContext('2d');
|
|
101
|
+
const viewer = BufferViewer.getInstance();
|
|
102
|
+
|
|
103
|
+
function render() {
|
|
104
|
+
// ... your Canvas2D drawing code ...
|
|
105
|
+
|
|
106
|
+
// Capture the canvas contents
|
|
107
|
+
viewer.capture('2D Canvas', () => readCanvas(canvas));
|
|
108
|
+
// Or pass the context directly
|
|
109
|
+
viewer.capture('2D Canvas', () => readCanvas(ctx));
|
|
110
|
+
|
|
111
|
+
requestAnimationFrame(render);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API Reference
|
|
116
|
+
|
|
117
|
+
### `BufferViewer`
|
|
118
|
+
|
|
119
|
+
The main class for managing buffer visualization. Uses the singleton pattern.
|
|
120
|
+
|
|
121
|
+
#### `BufferViewer.getInstance(options?)`
|
|
122
|
+
|
|
123
|
+
Returns the singleton instance, creating it if necessary.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
interface ViewerOptions {
|
|
127
|
+
active?: boolean; // Start active (default: true)
|
|
128
|
+
fps?: number; // Capture rate limit (default: 10)
|
|
129
|
+
corner?: Corner; // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### `viewer.capture(label, getData, note?)`
|
|
134
|
+
|
|
135
|
+
Capture and display buffer data.
|
|
136
|
+
|
|
137
|
+
- `label`: Unique identifier for this buffer slot
|
|
138
|
+
- `getData`: Callback returning `CaptureData` (only called when FPS throttle allows)
|
|
139
|
+
- `note`: Optional description text displayed below the label
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
interface CaptureData {
|
|
143
|
+
data: Uint8Array; // RGBA pixel data
|
|
144
|
+
width?: number; // Required on first capture
|
|
145
|
+
height?: number; // Required on first capture
|
|
146
|
+
flipY?: boolean; // true for WebGL (default), false for Canvas2D
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### `viewer.active`
|
|
151
|
+
|
|
152
|
+
Get or set the active state. When inactive, captures are skipped and the overlay is hidden.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
viewer.active = false; // Hide the viewer
|
|
156
|
+
viewer.active = true; // Show the viewer
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `viewer.toggle()`
|
|
160
|
+
|
|
161
|
+
Toggle the viewer on/off.
|
|
162
|
+
|
|
163
|
+
#### `viewer.setFps(fps)`
|
|
164
|
+
|
|
165
|
+
Change the capture rate limit.
|
|
166
|
+
|
|
167
|
+
#### `viewer.removeBuffer(label)`
|
|
168
|
+
|
|
169
|
+
Remove a specific buffer from the display.
|
|
170
|
+
|
|
171
|
+
#### `viewer.dispose()`
|
|
172
|
+
|
|
173
|
+
Clean up all resources and remove the overlay.
|
|
174
|
+
|
|
175
|
+
### Helper Functions
|
|
176
|
+
|
|
177
|
+
#### `readRenderTarget(renderer, renderTarget)`
|
|
178
|
+
|
|
179
|
+
Read pixels from a Three.js `WebGLRenderTarget`.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { readRenderTarget } from 'canvas-buffer-viewer';
|
|
183
|
+
|
|
184
|
+
viewer.capture('RT', () => readRenderTarget(renderer, myRenderTarget));
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### `readPixels(gl, framebuffer?)`
|
|
188
|
+
|
|
189
|
+
Read pixels from a WebGL context. If `framebuffer` is omitted, reads from the current binding.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { readPixels } from 'canvas-buffer-viewer';
|
|
193
|
+
|
|
194
|
+
// Read from current framebuffer
|
|
195
|
+
viewer.capture('Current', () => readPixels(gl));
|
|
196
|
+
|
|
197
|
+
// Read from specific framebuffer
|
|
198
|
+
viewer.capture('Shadow', () => readPixels(gl, shadowFBO));
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### `readCanvas(source)`
|
|
202
|
+
|
|
203
|
+
Read pixels from a Canvas2D context or canvas element.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { readCanvas } from 'canvas-buffer-viewer';
|
|
207
|
+
|
|
208
|
+
viewer.capture('Canvas', () => readCanvas(canvas));
|
|
209
|
+
viewer.capture('Canvas', () => readCanvas(ctx));
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Debugging Post-Processing Pipelines
|
|
213
|
+
|
|
214
|
+
A common use case is debugging multi-pass rendering:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { BufferViewer, readRenderTarget } from 'canvas-buffer-viewer';
|
|
218
|
+
|
|
219
|
+
const viewer = BufferViewer.getInstance({ fps: 15 });
|
|
220
|
+
|
|
221
|
+
function render() {
|
|
222
|
+
// Pass 1: Scene
|
|
223
|
+
renderer.setRenderTarget(sceneRT);
|
|
224
|
+
renderer.render(scene, camera);
|
|
225
|
+
viewer.capture('Scene', () => readRenderTarget(renderer, sceneRT), 'Base scene render');
|
|
226
|
+
|
|
227
|
+
// Pass 2: Bloom threshold
|
|
228
|
+
renderer.setRenderTarget(bloomRT);
|
|
229
|
+
renderer.render(bloomScene, postCamera);
|
|
230
|
+
viewer.capture('Bloom', () => readRenderTarget(renderer, bloomRT), 'Bright pass');
|
|
231
|
+
|
|
232
|
+
// Pass 3: Blur
|
|
233
|
+
renderer.setRenderTarget(blurRT);
|
|
234
|
+
renderer.render(blurScene, postCamera);
|
|
235
|
+
viewer.capture('Blur', () => readRenderTarget(renderer, blurRT));
|
|
236
|
+
|
|
237
|
+
// Final composite
|
|
238
|
+
renderer.setRenderTarget(null);
|
|
239
|
+
renderer.render(compositeScene, postCamera);
|
|
240
|
+
|
|
241
|
+
requestAnimationFrame(render);
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Keyboard Shortcut Example
|
|
246
|
+
|
|
247
|
+
Add a toggle shortcut for convenience:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
const viewer = BufferViewer.getInstance({ active: false });
|
|
251
|
+
|
|
252
|
+
window.addEventListener('keydown', (e) => {
|
|
253
|
+
if (e.key === 'F2') {
|
|
254
|
+
viewer.toggle();
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
MIT
|