topazcube 0.1.30 → 0.1.33
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.txt +0 -0
- package/README.md +0 -0
- package/dist/Renderer.cjs +18200 -0
- package/dist/Renderer.cjs.map +1 -0
- package/dist/Renderer.js +18183 -0
- package/dist/Renderer.js.map +1 -0
- package/dist/client.cjs +94 -260
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +71 -215
- package/dist/client.js.map +1 -1
- package/dist/server.cjs +165 -432
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +117 -370
- package/dist/server.js.map +1 -1
- package/dist/terminal.cjs +113 -200
- package/dist/terminal.cjs.map +1 -1
- package/dist/terminal.js +50 -51
- package/dist/terminal.js.map +1 -1
- package/dist/utils-CRhi1BDa.cjs +259 -0
- package/dist/utils-CRhi1BDa.cjs.map +1 -0
- package/dist/utils-D7tXt6-2.js +260 -0
- package/dist/utils-D7tXt6-2.js.map +1 -0
- package/package.json +19 -15
- package/src/{client.ts → network/client.js} +173 -403
- package/src/{compress-browser.ts → network/compress-browser.js} +2 -4
- package/src/{compress-node.ts → network/compress-node.js} +8 -14
- package/src/{server.ts → network/server.js} +229 -317
- package/src/{terminal.js → network/terminal.js} +0 -0
- package/src/{topazcube.ts → network/topazcube.js} +2 -2
- package/src/network/utils.js +375 -0
- package/src/renderer/Camera.js +191 -0
- package/src/renderer/DebugUI.js +572 -0
- package/src/renderer/Geometry.js +1049 -0
- package/src/renderer/Material.js +61 -0
- package/src/renderer/Mesh.js +211 -0
- package/src/renderer/Node.js +112 -0
- package/src/renderer/Pipeline.js +643 -0
- package/src/renderer/Renderer.js +1324 -0
- package/src/renderer/Skin.js +792 -0
- package/src/renderer/Texture.js +584 -0
- package/src/renderer/core/AssetManager.js +359 -0
- package/src/renderer/core/CullingSystem.js +307 -0
- package/src/renderer/core/EntityManager.js +541 -0
- package/src/renderer/core/InstanceManager.js +343 -0
- package/src/renderer/core/ParticleEmitter.js +358 -0
- package/src/renderer/core/ParticleSystem.js +564 -0
- package/src/renderer/core/SpriteSystem.js +349 -0
- package/src/renderer/gltf.js +546 -0
- package/src/renderer/math.js +161 -0
- package/src/renderer/rendering/HistoryBufferManager.js +333 -0
- package/src/renderer/rendering/ProbeCapture.js +1495 -0
- package/src/renderer/rendering/ReflectionProbeManager.js +352 -0
- package/src/renderer/rendering/RenderGraph.js +2064 -0
- package/src/renderer/rendering/passes/AOPass.js +308 -0
- package/src/renderer/rendering/passes/AmbientCapturePass.js +593 -0
- package/src/renderer/rendering/passes/BasePass.js +101 -0
- package/src/renderer/rendering/passes/BloomPass.js +417 -0
- package/src/renderer/rendering/passes/FogPass.js +419 -0
- package/src/renderer/rendering/passes/GBufferPass.js +706 -0
- package/src/renderer/rendering/passes/HiZPass.js +714 -0
- package/src/renderer/rendering/passes/LightingPass.js +739 -0
- package/src/renderer/rendering/passes/ParticlePass.js +835 -0
- package/src/renderer/rendering/passes/PlanarReflectionPass.js +456 -0
- package/src/renderer/rendering/passes/PostProcessPass.js +282 -0
- package/src/renderer/rendering/passes/ReflectionPass.js +157 -0
- package/src/renderer/rendering/passes/RenderPostPass.js +364 -0
- package/src/renderer/rendering/passes/SSGIPass.js +265 -0
- package/src/renderer/rendering/passes/SSGITilePass.js +296 -0
- package/src/renderer/rendering/passes/ShadowPass.js +1822 -0
- package/src/renderer/rendering/passes/TransparentPass.js +831 -0
- package/src/renderer/rendering/shaders/ao.wgsl +182 -0
- package/src/renderer/rendering/shaders/bloom.wgsl +97 -0
- package/src/renderer/rendering/shaders/bloom_blur.wgsl +80 -0
- package/src/renderer/rendering/shaders/depth_copy.wgsl +17 -0
- package/src/renderer/rendering/shaders/geometry.wgsl +550 -0
- package/src/renderer/rendering/shaders/hiz_reduce.wgsl +114 -0
- package/src/renderer/rendering/shaders/light_culling.wgsl +204 -0
- package/src/renderer/rendering/shaders/lighting.wgsl +932 -0
- package/src/renderer/rendering/shaders/lighting_common.wgsl +143 -0
- package/src/renderer/rendering/shaders/particle_render.wgsl +525 -0
- package/src/renderer/rendering/shaders/particle_simulate.wgsl +440 -0
- package/src/renderer/rendering/shaders/postproc.wgsl +272 -0
- package/src/renderer/rendering/shaders/render_post.wgsl +289 -0
- package/src/renderer/rendering/shaders/shadow.wgsl +76 -0
- package/src/renderer/rendering/shaders/ssgi.wgsl +266 -0
- package/src/renderer/rendering/shaders/ssgi_accumulate.wgsl +114 -0
- package/src/renderer/rendering/shaders/ssgi_propagate.wgsl +132 -0
- package/src/renderer/utils/BoundingSphere.js +439 -0
- package/src/renderer/utils/Frustum.js +281 -0
- package/dist/client.d.cts +0 -211
- package/dist/client.d.ts +0 -211
- package/dist/server.d.cts +0 -120
- package/dist/server.d.ts +0 -120
- package/dist/terminal.d.cts +0 -64
- package/dist/terminal.d.ts +0 -64
- package/src/utils.ts +0 -403
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { BasePass } from "./BasePass.js"
|
|
2
|
+
import { Pipeline } from "../../Pipeline.js"
|
|
3
|
+
|
|
4
|
+
import postProcessingWGSL from "../shaders/postproc.wgsl"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* PostProcessPass - Final post-processing and tone mapping
|
|
8
|
+
*
|
|
9
|
+
* Pass 7 in the 7-pass pipeline (final pass).
|
|
10
|
+
* Applies tone mapping and outputs to the canvas.
|
|
11
|
+
*
|
|
12
|
+
* Input: HDR lit image from LightingPass
|
|
13
|
+
* Output: Final SDR image to canvas
|
|
14
|
+
*/
|
|
15
|
+
class PostProcessPass extends BasePass {
|
|
16
|
+
constructor(engine = null) {
|
|
17
|
+
super('PostProcess', engine)
|
|
18
|
+
|
|
19
|
+
this.pipeline = null
|
|
20
|
+
this.inputTexture = null
|
|
21
|
+
this.bloomTexture = null
|
|
22
|
+
this.dummyBloomTexture = null // 1x1 black texture when bloom disabled
|
|
23
|
+
this.noiseTexture = null
|
|
24
|
+
this.noiseSize = 64
|
|
25
|
+
this.noiseAnimated = true
|
|
26
|
+
this.guiCanvas = null // 2D canvas for GUI overlay
|
|
27
|
+
this.guiTexture = null // GPU texture for GUI
|
|
28
|
+
this.guiSampler = null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Convenience getter for exposure setting
|
|
32
|
+
get exposure() { return this.settings?.environment?.exposure ?? 1.6 }
|
|
33
|
+
|
|
34
|
+
// Convenience getter for fxaa setting
|
|
35
|
+
get fxaa() { return this.settings?.rendering?.fxaa ?? true }
|
|
36
|
+
|
|
37
|
+
// Convenience getter for dithering settings
|
|
38
|
+
get ditheringEnabled() { return this.settings?.dithering?.enabled ?? true }
|
|
39
|
+
get colorLevels() { return this.settings?.dithering?.colorLevels ?? 32 }
|
|
40
|
+
|
|
41
|
+
// Convenience getters for bloom settings
|
|
42
|
+
get bloomEnabled() { return this.settings?.bloom?.enabled ?? true }
|
|
43
|
+
get bloomIntensity() { return this.settings?.bloom?.intensity ?? 1.0 }
|
|
44
|
+
get bloomRadius() { return this.settings?.bloom?.radius ?? 5 }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Set the input texture (HDR image from LightingPass)
|
|
48
|
+
* @param {Texture} texture - Input HDR texture
|
|
49
|
+
*/
|
|
50
|
+
setInputTexture(texture) {
|
|
51
|
+
if (this.inputTexture !== texture) {
|
|
52
|
+
this.inputTexture = texture
|
|
53
|
+
this._needsRebuild = true
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Set the bloom texture (from BloomPass)
|
|
59
|
+
* @param {Object} bloomTexture - Bloom texture with mip levels
|
|
60
|
+
*/
|
|
61
|
+
setBloomTexture(bloomTexture) {
|
|
62
|
+
if (this.bloomTexture !== bloomTexture) {
|
|
63
|
+
this.bloomTexture = bloomTexture
|
|
64
|
+
this._needsRebuild = true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Set the noise texture for dithering
|
|
70
|
+
* @param {Texture} texture - Noise texture (blue noise or bayer dither)
|
|
71
|
+
* @param {number} size - Texture size
|
|
72
|
+
* @param {boolean} animated - Whether to animate noise offset each frame
|
|
73
|
+
*/
|
|
74
|
+
setNoise(texture, size = 64, animated = true) {
|
|
75
|
+
this.noiseTexture = texture
|
|
76
|
+
this.noiseSize = size
|
|
77
|
+
this.noiseAnimated = animated
|
|
78
|
+
this._needsRebuild = true
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Set the GUI canvas for overlay rendering
|
|
83
|
+
* @param {HTMLCanvasElement} canvas - 2D canvas with GUI content
|
|
84
|
+
*/
|
|
85
|
+
setGuiCanvas(canvas) {
|
|
86
|
+
this.guiCanvas = canvas
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async _init() {
|
|
90
|
+
// Create dummy 1x1 black bloom texture for when bloom is disabled
|
|
91
|
+
// This ensures shader bindings are always valid
|
|
92
|
+
const { device } = this.engine
|
|
93
|
+
|
|
94
|
+
const dummyTexture = device.createTexture({
|
|
95
|
+
label: 'Dummy Bloom Texture',
|
|
96
|
+
size: [1, 1, 1],
|
|
97
|
+
format: 'rgba16float',
|
|
98
|
+
mipLevelCount: 1,
|
|
99
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Fill with black (no bloom)
|
|
103
|
+
device.queue.writeTexture(
|
|
104
|
+
{ texture: dummyTexture },
|
|
105
|
+
new Float32Array([0, 0, 0, 0]).buffer,
|
|
106
|
+
{ bytesPerRow: 8 },
|
|
107
|
+
{ width: 1, height: 1 }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
const dummySampler = device.createSampler({
|
|
111
|
+
label: 'Dummy Bloom Sampler',
|
|
112
|
+
minFilter: 'linear',
|
|
113
|
+
magFilter: 'linear',
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
this.dummyBloomTexture = {
|
|
117
|
+
texture: dummyTexture,
|
|
118
|
+
view: dummyTexture.createView(),
|
|
119
|
+
sampler: dummySampler,
|
|
120
|
+
mipCount: 1,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Create sampler for GUI texture
|
|
124
|
+
this.guiSampler = device.createSampler({
|
|
125
|
+
label: 'GUI Sampler',
|
|
126
|
+
minFilter: 'linear',
|
|
127
|
+
magFilter: 'linear',
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Create dummy 1x1 transparent GUI texture
|
|
131
|
+
const dummyGuiTexture = device.createTexture({
|
|
132
|
+
label: 'Dummy GUI Texture',
|
|
133
|
+
size: [1, 1, 1],
|
|
134
|
+
format: 'rgba8unorm',
|
|
135
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
|
136
|
+
})
|
|
137
|
+
device.queue.writeTexture(
|
|
138
|
+
{ texture: dummyGuiTexture },
|
|
139
|
+
new Uint8Array([0, 0, 0, 0]),
|
|
140
|
+
{ bytesPerRow: 4 },
|
|
141
|
+
{ width: 1, height: 1 }
|
|
142
|
+
)
|
|
143
|
+
this.dummyGuiTexture = {
|
|
144
|
+
texture: dummyGuiTexture,
|
|
145
|
+
view: dummyGuiTexture.createView(),
|
|
146
|
+
sampler: this.guiSampler,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Build or rebuild the pipeline
|
|
152
|
+
*/
|
|
153
|
+
async _buildPipeline() {
|
|
154
|
+
if (!this.inputTexture) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const textures = [this.inputTexture]
|
|
159
|
+
if (this.noiseTexture) {
|
|
160
|
+
textures.push(this.noiseTexture)
|
|
161
|
+
}
|
|
162
|
+
// Always include bloom texture (real or dummy) so shader bindings are valid
|
|
163
|
+
const effectiveBloomTexture = this.bloomTexture || this.dummyBloomTexture
|
|
164
|
+
textures.push(effectiveBloomTexture)
|
|
165
|
+
|
|
166
|
+
// Always include GUI texture (real or dummy) so shader bindings are valid
|
|
167
|
+
const effectiveGuiTexture = this.guiTexture || this.dummyGuiTexture
|
|
168
|
+
textures.push(effectiveGuiTexture)
|
|
169
|
+
|
|
170
|
+
const hasBloom = this.bloomTexture && this.bloomEnabled
|
|
171
|
+
|
|
172
|
+
this.pipeline = await Pipeline.create(this.engine, {
|
|
173
|
+
label: 'postProcess',
|
|
174
|
+
wgslSource: postProcessingWGSL,
|
|
175
|
+
isPostProcessing: true,
|
|
176
|
+
textures: textures,
|
|
177
|
+
uniforms: () => ({
|
|
178
|
+
noiseParams: [this.noiseSize, this.noiseAnimated ? Math.random() : 0, this.noiseAnimated ? Math.random() : 0, this.fxaa ? 1.0 : 0.0],
|
|
179
|
+
ditherParams: [this.ditheringEnabled ? 1.0 : 0.0, this.colorLevels, 0, 0],
|
|
180
|
+
bloomParams: [hasBloom ? 1.0 : 0.0, this.bloomIntensity, this.bloomRadius, effectiveBloomTexture?.mipCount ?? 1]
|
|
181
|
+
}),
|
|
182
|
+
// No renderTarget = output to canvas
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
this._needsRebuild = false
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async _execute(context) {
|
|
189
|
+
const { device } = this.engine
|
|
190
|
+
|
|
191
|
+
// Update GUI texture from canvas if available
|
|
192
|
+
if (this.guiCanvas && this.guiCanvas.width > 0 && this.guiCanvas.height > 0) {
|
|
193
|
+
// Check if we need to recreate the texture (size changed)
|
|
194
|
+
const needsNewTexture = !this.guiTexture ||
|
|
195
|
+
this.guiTexture.width !== this.guiCanvas.width ||
|
|
196
|
+
this.guiTexture.height !== this.guiCanvas.height
|
|
197
|
+
|
|
198
|
+
if (needsNewTexture) {
|
|
199
|
+
// Destroy old texture if it exists
|
|
200
|
+
if (this.guiTexture?.texture) {
|
|
201
|
+
this.guiTexture.texture.destroy()
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Create new texture matching canvas size
|
|
205
|
+
const texture = device.createTexture({
|
|
206
|
+
label: 'GUI Texture',
|
|
207
|
+
size: [this.guiCanvas.width, this.guiCanvas.height, 1],
|
|
208
|
+
format: 'rgba8unorm',
|
|
209
|
+
usage: GPUTextureUsage.TEXTURE_BINDING |
|
|
210
|
+
GPUTextureUsage.COPY_DST |
|
|
211
|
+
GPUTextureUsage.RENDER_ATTACHMENT,
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
this.guiTexture = {
|
|
215
|
+
texture: texture,
|
|
216
|
+
view: texture.createView(),
|
|
217
|
+
sampler: this.guiSampler,
|
|
218
|
+
width: this.guiCanvas.width,
|
|
219
|
+
height: this.guiCanvas.height,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Force pipeline rebuild to use new texture
|
|
223
|
+
this._needsRebuild = true
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Copy canvas content to GPU texture
|
|
227
|
+
device.queue.copyExternalImageToTexture(
|
|
228
|
+
{ source: this.guiCanvas },
|
|
229
|
+
{ texture: this.guiTexture.texture },
|
|
230
|
+
[this.guiCanvas.width, this.guiCanvas.height]
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Rebuild pipeline if needed
|
|
235
|
+
if (this._needsRebuild) {
|
|
236
|
+
await this._buildPipeline()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// If rebuild was attempted but failed, don't use stale pipeline with old bind groups
|
|
240
|
+
if (!this.pipeline || this._needsRebuild) {
|
|
241
|
+
console.warn('PostProcessPass: Pipeline not ready')
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Determine if bloom is effectively enabled
|
|
246
|
+
const hasBloom = this.bloomTexture && this.bloomEnabled
|
|
247
|
+
const effectiveBloomTexture = this.bloomTexture || this.dummyBloomTexture
|
|
248
|
+
|
|
249
|
+
// Update uniforms each frame
|
|
250
|
+
this.pipeline.uniformValues.set({
|
|
251
|
+
noiseParams: [this.noiseSize, this.noiseAnimated ? Math.random() : 0, this.noiseAnimated ? Math.random() : 0, this.fxaa ? 1.0 : 0.0],
|
|
252
|
+
ditherParams: [this.ditheringEnabled ? 1.0 : 0.0, this.colorLevels, 0, 0],
|
|
253
|
+
bloomParams: [hasBloom ? 1.0 : 0.0, this.bloomIntensity, this.bloomRadius, effectiveBloomTexture?.mipCount ?? 1]
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
// Render to canvas
|
|
257
|
+
this.pipeline.render()
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async _resize(width, height) {
|
|
261
|
+
// Pipeline needs rebuild since canvas size changed
|
|
262
|
+
this._needsRebuild = true
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
_destroy() {
|
|
266
|
+
this.pipeline = null
|
|
267
|
+
if (this.dummyBloomTexture?.texture) {
|
|
268
|
+
this.dummyBloomTexture.texture.destroy()
|
|
269
|
+
this.dummyBloomTexture = null
|
|
270
|
+
}
|
|
271
|
+
if (this.guiTexture?.texture) {
|
|
272
|
+
this.guiTexture.texture.destroy()
|
|
273
|
+
this.guiTexture = null
|
|
274
|
+
}
|
|
275
|
+
if (this.dummyGuiTexture?.texture) {
|
|
276
|
+
this.dummyGuiTexture.texture.destroy()
|
|
277
|
+
this.dummyGuiTexture = null
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { PostProcessPass }
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { BasePass } from "./BasePass.js"
|
|
2
|
+
import { Texture } from "../../Texture.js"
|
|
3
|
+
import { ProbeCapture } from "../ProbeCapture.js"
|
|
4
|
+
import { ReflectionProbeManager } from "../ReflectionProbeManager.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ReflectionPass - Manages reflection probes and environment lighting
|
|
8
|
+
*
|
|
9
|
+
* Pass 2 in the 7-pass pipeline.
|
|
10
|
+
* Handles:
|
|
11
|
+
* - Loading/managing reflection probes
|
|
12
|
+
* - Real-time probe capture (when triggered)
|
|
13
|
+
* - Probe interpolation based on camera position
|
|
14
|
+
*
|
|
15
|
+
* Configuration:
|
|
16
|
+
* - 1024x1024 octahedral HDR texture per probe
|
|
17
|
+
* - Interpolates between closest 2 probes
|
|
18
|
+
*/
|
|
19
|
+
class ReflectionPass extends BasePass {
|
|
20
|
+
constructor(engine = null) {
|
|
21
|
+
super('Reflection', engine)
|
|
22
|
+
|
|
23
|
+
// Probe capture system
|
|
24
|
+
this.probeCapture = null
|
|
25
|
+
|
|
26
|
+
// Probe manager for loading/interpolating
|
|
27
|
+
this.probeManager = null
|
|
28
|
+
|
|
29
|
+
// Current world ID
|
|
30
|
+
this.currentWorldId = 'default'
|
|
31
|
+
|
|
32
|
+
// Capture request queue
|
|
33
|
+
this.captureRequests = []
|
|
34
|
+
|
|
35
|
+
// Output: combined/interpolated probe texture
|
|
36
|
+
this.outputTexture = null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async _init() {
|
|
40
|
+
// Initialize probe manager (lightweight, always works)
|
|
41
|
+
this.probeManager = new ReflectionProbeManager(this.engine)
|
|
42
|
+
|
|
43
|
+
// Initialize probe capture system (can fail on some systems)
|
|
44
|
+
try {
|
|
45
|
+
this.probeCapture = new ProbeCapture(this.engine)
|
|
46
|
+
await this.probeCapture.initialize()
|
|
47
|
+
} catch (e) {
|
|
48
|
+
console.warn('ReflectionPass: Probe capture initialization failed:', e)
|
|
49
|
+
this.probeCapture = null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Set fallback environment map (used when no probes available)
|
|
55
|
+
* @param {Texture} envMap - Environment map texture
|
|
56
|
+
* @param {number} encoding - 0 = equirectangular, 1 = octahedral
|
|
57
|
+
*/
|
|
58
|
+
setFallbackEnvironment(envMap, encoding = 0) {
|
|
59
|
+
if (this.probeManager) {
|
|
60
|
+
this.probeManager.setFallbackEnvironment(envMap)
|
|
61
|
+
}
|
|
62
|
+
if (this.probeCapture) {
|
|
63
|
+
this.probeCapture.setFallbackEnvironment(envMap)
|
|
64
|
+
this.probeCapture.envEncoding = encoding
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Load probes for a world
|
|
70
|
+
*/
|
|
71
|
+
async loadWorldProbes(worldId) {
|
|
72
|
+
this.currentWorldId = worldId
|
|
73
|
+
if (this.probeManager) {
|
|
74
|
+
await this.probeManager.loadWorldProbes(worldId)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Request a probe capture at position
|
|
80
|
+
* Will be processed during next execute()
|
|
81
|
+
*/
|
|
82
|
+
requestCapture(position, worldId = null) {
|
|
83
|
+
this.captureRequests.push({
|
|
84
|
+
position: [...position],
|
|
85
|
+
worldId: worldId || this.currentWorldId
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Load a specific probe from URL
|
|
91
|
+
*/
|
|
92
|
+
async loadProbe(url, position, worldId = null) {
|
|
93
|
+
if (this.probeManager) {
|
|
94
|
+
return await this.probeManager.loadProbe(url, position, worldId || this.currentWorldId)
|
|
95
|
+
}
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async _execute(context) {
|
|
100
|
+
const { camera } = context
|
|
101
|
+
|
|
102
|
+
// Update active probes based on camera position
|
|
103
|
+
if (this.probeManager && camera) {
|
|
104
|
+
this.probeManager.updateActiveProbes(camera.position, this.currentWorldId)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Process capture requests (one per frame max)
|
|
108
|
+
if (this.captureRequests.length > 0 && !this.probeCapture?.isCapturing) {
|
|
109
|
+
const request = this.captureRequests.shift()
|
|
110
|
+
// Capture would happen here - requires renderGraph reference
|
|
111
|
+
// For now, log the request
|
|
112
|
+
console.log(`ReflectionPass: Capture requested at [${request.position.join(', ')}]`)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async _resize(width, height) {
|
|
117
|
+
// Reflection maps are fixed size, doesn't resize with screen
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
_destroy() {
|
|
121
|
+
if (this.probeCapture) {
|
|
122
|
+
this.probeCapture.destroy()
|
|
123
|
+
}
|
|
124
|
+
if (this.probeManager) {
|
|
125
|
+
this.probeManager.destroy()
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get probe manager for external access
|
|
131
|
+
*/
|
|
132
|
+
getProbeManager() {
|
|
133
|
+
return this.probeManager
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get probe capture system for manual triggering
|
|
138
|
+
*/
|
|
139
|
+
getProbeCapture() {
|
|
140
|
+
return this.probeCapture
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get active probe data for lighting pass
|
|
145
|
+
*/
|
|
146
|
+
getActiveProbeData() {
|
|
147
|
+
if (this.probeManager) {
|
|
148
|
+
return this.probeManager.getActiveProbeData()
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
textures: [null, null],
|
|
152
|
+
weights: [1.0, 0.0]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { ReflectionPass }
|