@driftengine/core 4.8.5 → 4.8.7
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/CHANGELOG.json +4392 -4250
- package/README.md +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.js +12 -2
- package/dist/render/ambientHarmonics.d.ts +46 -0
- package/dist/render/ambientHarmonics.js +80 -0
- package/dist/render/anisotropicLobe.d.ts +10 -0
- package/dist/render/anisotropicLobe.js +19 -0
- package/dist/render/areaLights.d.ts +54 -0
- package/dist/render/areaLights.js +55 -0
- package/dist/render/backend/api.d.ts +43 -2
- package/dist/render/backend/webgl2/instanced.d.ts +2 -0
- package/dist/render/backend/webgl2/instanced.js +11 -2
- package/dist/render/backend/webgl2/renderer.d.ts +120 -11
- package/dist/render/backend/webgl2/renderer.js +356 -53
- package/dist/render/backend/webgl2/sceneCaptureTarget.d.ts +29 -0
- package/dist/render/backend/webgl2/sceneCaptureTarget.js +96 -0
- package/dist/render/backend/webgl2/skinScatter.d.ts +14 -0
- package/dist/render/backend/webgl2/skinScatter.js +88 -26
- package/dist/render/backend/webgpu/buffers.js +2 -1
- package/dist/render/backend/webgpu/clusterBinner.js +3 -2
- package/dist/render/backend/webgpu/flatPass.d.ts +7 -5
- package/dist/render/backend/webgpu/flatPass.js +15 -13
- package/dist/render/backend/webgpu/particlePass.d.ts +37 -4
- package/dist/render/backend/webgpu/particlePass.js +81 -12
- package/dist/render/backend/webgpu/postPass.d.ts +6 -1
- package/dist/render/backend/webgpu/postPass.js +7 -2
- package/dist/render/backend/webgpu/renderer.d.ts +93 -8
- package/dist/render/backend/webgpu/renderer.js +483 -93
- package/dist/render/backend/webgpu/sceneCaptureTarget.d.ts +24 -0
- package/dist/render/backend/webgpu/sceneCaptureTarget.js +59 -0
- package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.d.ts +1 -1
- package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.js +41 -1
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +40 -28
- package/dist/render/backend/webgpu/skinPaletteRing.js +69 -32
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +10 -2
- package/dist/render/backend/webgpu/skinScatterPass.js +59 -9
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +5 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.js +45 -5
- package/dist/render/backend/webgpu/waterPass.d.ts +1 -1
- package/dist/render/bloomChain.d.ts +44 -0
- package/dist/render/bloomChain.js +28 -0
- package/dist/render/bloomPass.d.ts +3 -1
- package/dist/render/bloomPass.js +16 -2
- package/dist/render/clusteredLights.d.ts +78 -6
- package/dist/render/clusteredLights.js +214 -13
- package/dist/render/driftLight/bake.d.ts +2 -0
- package/dist/render/driftLight/bake.js +1 -1
- package/dist/render/driftLight/falloff.d.ts +4 -2
- package/dist/render/driftLight/falloff.js +8 -2
- package/dist/render/fixtureAtlas.js +1 -1
- package/dist/render/gi/bounceLights.d.ts +3 -2
- package/dist/render/gi/bounceLights.js +8 -3
- package/dist/render/instanceCull.js +12 -0
- package/dist/render/instances.d.ts +47 -11
- package/dist/render/instances.js +24 -9
- package/dist/render/lightBudget.d.ts +38 -2
- package/dist/render/lightBudget.js +48 -5
- package/dist/render/lightmap.d.ts +116 -0
- package/dist/render/lightmap.js +140 -0
- package/dist/render/mesh.js +2 -1
- package/dist/render/particleBatch.d.ts +59 -3
- package/dist/render/particleBatch.js +53 -2
- package/dist/render/particleMaterial.d.ts +6 -1
- package/dist/render/particleMaterial.js +10 -2
- package/dist/render/particlePool.d.ts +32 -0
- package/dist/render/particlePool.js +9 -0
- package/dist/render/particleSort.d.ts +34 -0
- package/dist/render/particleSort.js +96 -0
- package/dist/render/pointLightSelection.d.ts +13 -0
- package/dist/render/pointLightSelection.js +3 -1
- package/dist/render/renderQuality.d.ts +8 -7
- package/dist/render/rendererHarness.js +3 -0
- package/dist/render/rgb9e5.d.ts +22 -0
- package/dist/render/rgb9e5.js +47 -0
- package/dist/render/sceneCapture.d.ts +29 -0
- package/dist/render/sceneCapture.js +36 -0
- package/dist/render/sceneTarget.d.ts +5 -0
- package/dist/render/sceneTarget.js +8 -1
- package/dist/render/screenSpaceReflection.d.ts +27 -1
- package/dist/render/screenSpaceReflection.js +9 -0
- package/dist/render/shaders/bloom.d.ts +8 -4
- package/dist/render/shaders/bloom.js +20 -3
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/bolt.js +7 -1
- package/dist/render/shaders/depth.js +11 -0
- package/dist/render/shaders/flat/anisotropic.d.ts +1 -1
- package/dist/render/shaders/flat/anisotropic.js +37 -3
- package/dist/render/shaders/flat/areaLight.d.ts +10 -0
- package/dist/render/shaders/flat/areaLight.js +142 -0
- package/dist/render/shaders/flat/glassTint.d.ts +3 -2
- package/dist/render/shaders/flat/glassTint.js +3 -1
- package/dist/render/shaders/flat/index.d.ts +5 -0
- package/dist/render/shaders/flat/index.js +46 -6
- package/dist/render/shaders/flat/lobes.d.ts +6 -0
- package/dist/render/shaders/flat/lobes.js +49 -43
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +158 -121
- package/dist/render/shaders/flat/models.d.ts +21 -6
- package/dist/render/shaders/flat/models.js +161 -17
- package/dist/render/shaders/flat/normalMap.d.ts +10 -0
- package/dist/render/shaders/flat/normalMap.js +25 -0
- package/dist/render/shaders/flat/preamble.js +84 -40
- package/dist/render/shaders/flat/skin.js +6 -5
- package/dist/render/shaders/generated/bloom.wgsl.d.ts +13 -3
- package/dist/render/shaders/generated/bloom.wgsl.js +13 -3
- package/dist/render/shaders/generated/bolt.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/bolt.wgsl.js +1 -1
- package/dist/render/shaders/generated/depth.wgsl.d.ts +4 -4
- package/dist/render/shaders/generated/depth.wgsl.js +4 -4
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1647 -2044
- package/dist/render/shaders/generated/flat.wgsl.js +1685 -2082
- package/dist/render/shaders/generated/particle.wgsl.d.ts +115 -1
- package/dist/render/shaders/generated/particle.wgsl.js +115 -1
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +12 -2
- package/dist/render/shaders/generated/skinBlur.wgsl.js +12 -2
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +11 -6
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +11 -6
- package/dist/render/shaders/generated/water.wgsl.d.ts +23 -16
- package/dist/render/shaders/generated/water.wgsl.js +23 -16
- package/dist/render/shaders/gi/probeBake.wgsl.js +9 -5
- package/dist/render/shaders/particle.d.ts +17 -1
- package/dist/render/shaders/particle.js +133 -1
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +13 -2
- package/dist/render/shaders/skinBlur.js +25 -3
- package/dist/render/shaders/ssrTrace.js +20 -1
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/shaders/water.js +12 -3
- package/dist/render/skinBlur.d.ts +8 -5
- package/dist/render/skinBlur.js +8 -5
- package/dist/render/skinScatter.d.ts +3 -1
- package/dist/render/skinScatter.js +3 -1
- package/dist/render/ssrPass.js +1 -0
- package/dist/render/surfaceModel.d.ts +49 -8
- package/dist/render/surfaceModel.js +54 -8
- package/dist/render/surfaceTexture.d.ts +38 -1
- package/dist/render/surfaceTexture.js +37 -2
- package/package.json +6 -6
- package/src/index.ts +26 -3
- package/src/render/ambientHarmonics.ts +92 -0
- package/src/render/anisotropicLobe.ts +29 -0
- package/src/render/areaLights.ts +97 -0
- package/src/render/backend/api.ts +61 -1
- package/src/render/backend/webgl2/instanced.ts +12 -2
- package/src/render/backend/webgl2/renderer.ts +470 -59
- package/src/render/backend/webgl2/sceneCaptureTarget.ts +130 -0
- package/src/render/backend/webgl2/skinScatter.ts +120 -43
- package/src/render/backend/webgpu/buffers.ts +2 -1
- package/src/render/backend/webgpu/clusterBinner.ts +3 -1
- package/src/render/backend/webgpu/flatPass.ts +18 -13
- package/src/render/backend/webgpu/particlePass.ts +119 -12
- package/src/render/backend/webgpu/postPass.ts +7 -2
- package/src/render/backend/webgpu/renderer.ts +589 -113
- package/src/render/backend/webgpu/sceneCaptureTarget.ts +63 -0
- package/src/render/backend/webgpu/shaders/clusterBin.wgsl.ts +41 -1
- package/src/render/backend/webgpu/skinPaletteRing.ts +65 -33
- package/src/render/backend/webgpu/skinScatterPass.ts +59 -9
- package/src/render/backend/webgpu/surfaceTexturePass.ts +57 -6
- package/src/render/bloomChain.ts +69 -0
- package/src/render/bloomPass.ts +26 -2
- package/src/render/clusteredLights.ts +259 -12
- package/src/render/driftLight/bake.ts +3 -1
- package/src/render/driftLight/falloff.ts +13 -2
- package/src/render/fixtureAtlas.ts +1 -1
- package/src/render/gi/bounceLights.ts +12 -3
- package/src/render/instanceCull.ts +9 -0
- package/src/render/instances.ts +61 -12
- package/src/render/lightBudget.ts +88 -4
- package/src/render/lightmap.ts +243 -0
- package/src/render/mesh.ts +2 -1
- package/src/render/particleBatch.ts +95 -4
- package/src/render/particleMaterial.ts +11 -1
- package/src/render/particlePool.ts +36 -0
- package/src/render/particleSort.ts +133 -0
- package/src/render/pointLightSelection.ts +20 -1
- package/src/render/renderQuality.ts +8 -7
- package/src/render/rendererHarness.ts +3 -0
- package/src/render/rgb9e5.ts +52 -0
- package/src/render/sceneCapture.ts +56 -0
- package/src/render/sceneTarget.ts +18 -1
- package/src/render/screenSpaceReflection.ts +33 -1
- package/src/render/shaders/bloom.ts +20 -3
- package/src/render/shaders/bolt.ts +7 -1
- package/src/render/shaders/depth.ts +11 -0
- package/src/render/shaders/flat/anisotropic.ts +37 -3
- package/src/render/shaders/flat/areaLight.ts +142 -0
- package/src/render/shaders/flat/glassTint.ts +9 -2
- package/src/render/shaders/flat/index.ts +51 -6
- package/src/render/shaders/flat/lobes.ts +50 -43
- package/src/render/shaders/flat/main.ts +158 -121
- package/src/render/shaders/flat/models.ts +170 -21
- package/src/render/shaders/flat/normalMap.ts +25 -0
- package/src/render/shaders/flat/preamble.ts +84 -40
- package/src/render/shaders/flat/skin.ts +6 -5
- package/src/render/shaders/generated/bloom.wgsl.ts +13 -3
- package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
- package/src/render/shaders/generated/depth.wgsl.ts +4 -4
- package/src/render/shaders/generated/flat.wgsl.ts +1685 -2082
- package/src/render/shaders/generated/particle.wgsl.ts +116 -1
- package/src/render/shaders/generated/skinBlur.wgsl.ts +12 -2
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +11 -6
- package/src/render/shaders/generated/water.wgsl.ts +23 -16
- package/src/render/shaders/gi/probeBake.wgsl.ts +9 -5
- package/src/render/shaders/particle.ts +134 -1
- package/src/render/shaders/recon/motion.wgsl.ts +13 -2
- package/src/render/shaders/skinBlur.ts +25 -3
- package/src/render/shaders/ssrTrace.ts +20 -1
- package/src/render/shaders/water.ts +12 -3
- package/src/render/skinBlur.ts +8 -5
- package/src/render/skinScatter.ts +3 -1
- package/src/render/ssrPass.ts +1 -0
- package/src/render/surfaceModel.ts +82 -10
- package/src/render/surfaceTexture.ts +101 -3
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ carries the loop, the renderer, cameras, input, the scene graph, geometry, text
|
|
|
6
6
|
and the whole of [`@driftengine/physics`](https://driftengine.dev/docs/simulation/rigid-bodies),
|
|
7
7
|
which it re-exports. The rest of the engine is separate packages you add when you need them.
|
|
8
8
|
|
|
9
|
-
**Cost:
|
|
9
|
+
**Cost: 828.1 KB gzipped, importing `createRenderer`.** Measured by `scripts/size-gate.test.mjs`,
|
|
10
10
|
which fails the build if the figure drifts by more than 3%.
|
|
11
11
|
|
|
12
12
|
The manual is at **[driftengine.dev/docs](https://driftengine.dev/docs)**, with an example running
|
package/dist/index.d.ts
CHANGED
|
@@ -145,12 +145,20 @@ export { placeCascade } from './render/gi/globalField.ts';
|
|
|
145
145
|
export type { ReflectionOptions, ReflectiveSample } from './render/gi/reflection.ts';
|
|
146
146
|
export { GRADE_PLACEHOLDER_SIZE, MAX_GRADE_SIZE, identityGradeLut } from './render/colourGrade.ts';
|
|
147
147
|
export type { ColourGradeLut } from './render/colourGrade.ts';
|
|
148
|
+
/**
|
|
149
|
+
* How bloom answers past its threshold — a ramp in place of the subtraction, and a tint for each
|
|
150
|
+
* of the pyramid's `BLOOM_LEVELS` octaves — the third argument of `setBloom`.
|
|
151
|
+
*/
|
|
152
|
+
export { BLOOM_LEVELS } from './render/bloomChain.ts';
|
|
153
|
+
export type { BloomResponse } from './render/bloomChain.ts';
|
|
148
154
|
export { probeDevice } from './render/backend/probe.ts';
|
|
149
155
|
export type { ProbeVerdict } from './render/backend/probe.ts';
|
|
150
156
|
export type { BoltHandle, CausticsHandle, ClothBindingHandle, ClothParticlesHandle, FlockHandle, IncrementalMeshHandle, LineHandle, MeshHandle, MeshOptions, RenderBackend, RendererApi, ParticleHandle, PlumeHandle, ScatterHandle, InstancedHandle, SdfTextHandle, SurfaceTextureHandle, TextHandle, WaterHandle, WindStreakHandle, } from './render/backend/api.ts';
|
|
151
157
|
export type { ClothBindingData } from './render/clothBindingData.ts';
|
|
152
|
-
export { anisotropicModel, eyeModel, hairModel, skinModel } from './render/surfaceModel.ts';
|
|
153
|
-
export type { AnisotropicModel, EyeModel, HairModel, SkinModel, SurfaceModel, SurfaceModelKind, } from './render/surfaceModel.ts';
|
|
158
|
+
export { anisotropicModel, eyeModel, hairModel, lightmapModel, skinModel, } from './render/surfaceModel.ts';
|
|
159
|
+
export type { AnisotropicModel, EyeModel, HairModel, LightmapModel, SkinModel, SurfaceModel, SurfaceModelKind, } from './render/surfaceModel.ts';
|
|
160
|
+
export { WHOLE_PAGE } from './render/lightmap.ts';
|
|
161
|
+
export type { LightmapPage, LightmapRegion } from './render/lightmap.ts';
|
|
154
162
|
export { createSkinnedCloth } from './render/skinnedClothRun.ts';
|
|
155
163
|
export type { SkinnedClothSolver } from './render/skinnedClothRun.ts';
|
|
156
164
|
/**
|
|
@@ -359,8 +367,8 @@ export { seaStateForAgitation, seaStateForWind } from './render/seaState.ts';
|
|
|
359
367
|
export type { SeaState } from './render/seaState.ts';
|
|
360
368
|
export { InstancedMesh, createInstanceData, writeInstance } from './render/instancedMesh.ts';
|
|
361
369
|
export { createMeshInstances, packInstances, INSTANCE_FLOATS, INSTANCE_STRIDE, } from './render/instances.ts';
|
|
362
|
-
export { ParticlePool } from './render/particlePool.ts';
|
|
363
|
-
export type { ParticlePoolOptions, ParticleInstances } from './render/particlePool.ts';
|
|
370
|
+
export { ParticlePool, DEVICE_PARTICLE_FLOATS } from './render/particlePool.ts';
|
|
371
|
+
export type { DeviceParticles, ParticlePoolOptions, ParticleInstances, } from './render/particlePool.ts';
|
|
364
372
|
export { ParticleBatch } from './render/particleBatch.ts';
|
|
365
373
|
export type { ParticleBatchOptions, ParticleBlend, ParticleFacing, } from './render/particleBatch.ts';
|
|
366
374
|
export { PARTICLE_MOTE_FRAG, PARTICLE_SMOKE_FRAG, PARTICLE_SPARK_FRAG, PARTICLE_VERT, } from './render/shaders/particle.ts';
|
package/dist/index.js
CHANGED
|
@@ -209,13 +209,23 @@ export { placeCascade } from './render/gi/globalField.js';
|
|
|
209
209
|
* take the identity, bend it, hand it back — and because it is what the placeholder is.
|
|
210
210
|
*/
|
|
211
211
|
export { GRADE_PLACEHOLDER_SIZE, MAX_GRADE_SIZE, identityGradeLut } from './render/colourGrade.js';
|
|
212
|
+
/**
|
|
213
|
+
* How bloom answers past its threshold — a ramp in place of the subtraction, and a tint for each
|
|
214
|
+
* of the pyramid's `BLOOM_LEVELS` octaves — the third argument of `setBloom`.
|
|
215
|
+
*/
|
|
216
|
+
export { BLOOM_LEVELS } from './render/bloomChain.js';
|
|
212
217
|
export { probeDevice } from './render/backend/probe.js';
|
|
213
218
|
/*
|
|
214
219
|
* A material's shading model, for what the standard one is not: brushed metal, hair, skin, an eye.
|
|
215
220
|
* A frozen descriptor made by a factory and set as `SurfaceMaterial.model`; each is a pipeline of
|
|
216
221
|
* its own, compiled the first time a draw asks.
|
|
217
222
|
*/
|
|
218
|
-
export { anisotropicModel, eyeModel, hairModel, skinModel } from './render/surfaceModel.js';
|
|
223
|
+
export { anisotropicModel, eyeModel, hairModel, lightmapModel, skinModel, } from './render/surfaceModel.js';
|
|
224
|
+
/*
|
|
225
|
+
* A baked lightmap: the page a consumer decoded, which `createLightmap` uploads as a lightmapped
|
|
226
|
+
* material's `modelMap`, and the region of it a material or an instance reads.
|
|
227
|
+
*/
|
|
228
|
+
export { WHOLE_PAGE } from './render/lightmap.js';
|
|
219
229
|
/*
|
|
220
230
|
* A skinned cloth solved where the renderer can: compute on WebGPU, the CPU under WebGL2. A function
|
|
221
231
|
* rather than a renderer method so only a game that imports it carries the solver.
|
|
@@ -464,7 +474,7 @@ export { InstancedMesh, createInstanceData, writeInstance } from './render/insta
|
|
|
464
474
|
* pitches and rolls and a yaw cannot say so.
|
|
465
475
|
*/
|
|
466
476
|
export { createMeshInstances, packInstances, INSTANCE_FLOATS, INSTANCE_STRIDE, } from './render/instances.js';
|
|
467
|
-
export { ParticlePool } from './render/particlePool.js';
|
|
477
|
+
export { ParticlePool, DEVICE_PARTICLE_FLOATS } from './render/particlePool.js';
|
|
468
478
|
export { ParticleBatch } from './render/particleBatch.js';
|
|
469
479
|
export { PARTICLE_MOTE_FRAG, PARTICLE_SMOKE_FRAG, PARTICLE_SPARK_FRAG, PARTICLE_VERT, } from './render/shaders/particle.js';
|
|
470
480
|
export { BoltPool } from './render/boltPool.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A draw's own ambient light, as nine spherical-harmonic coefficients: what `setAmbientSH` takes,
|
|
3
|
+
* how both backends pack it, and the arithmetic the lit stage evaluates, which its tests hold.
|
|
4
|
+
*
|
|
5
|
+
* **Why a draw needs its own.** The engine's diffuse ambient is one answer for a whole frame — the
|
|
6
|
+
* sky-and-ground gradient, or the probe grid's irradiance — so everything standing in one place is
|
|
7
|
+
* lit alike. A stage with a baked volume of indirect light (Unreal's volumetric lightmap) lights a
|
|
8
|
+
* character by sampling that volume where the character stands; a consumer that samples it each
|
|
9
|
+
* frame hands the result here, around that character's draws, and the character takes the light of
|
|
10
|
+
* the spot it is in rather than the frame's average.
|
|
11
|
+
*
|
|
12
|
+
* **The coefficients are of incoming radiance**, `L(ω) ≈ Σ c_lm Y_lm(ω)`, on the standard real
|
|
13
|
+
* basis in its usual order — `Y00`, then `Y1,-1 Y1,0 Y1,1`, then `Y2,-2 Y2,-1 Y2,0 Y2,1 Y2,2` —
|
|
14
|
+
* evaluated on the engine's own world axes as written: `Y1,-1 = 0.488603 y`, `Y1,0 = 0.488603 z`,
|
|
15
|
+
* `Y1,1 = 0.488603 x`, `Y2,-2 = 1.092548 xy`, `Y2,-1 = 1.092548 yz`, `Y2,0 = 0.315392 (3z² − 1)`,
|
|
16
|
+
* `Y2,1 = 1.092548 xz`, `Y2,2 = 0.546274 (x² − y²)`, with y up. Three numbers a coefficient, red
|
|
17
|
+
* green blue, twenty-seven in all. A source in another engine's axes is rotated into these first.
|
|
18
|
+
*
|
|
19
|
+
* **What the surface receives is the cosine convolution**, Ramamoorthi and Hanrahan's: the bands
|
|
20
|
+
* scaled by π, 2π/3 and π/4 and divided by π, which is the irradiance over π a Lambertian surface
|
|
21
|
+
* multiplies its albedo by — the same quantity the gradient and the probes hand the shader. A
|
|
22
|
+
* constant radiance `L` everywhere is `c00 = L / 0.282095` and lights a surface exactly as an
|
|
23
|
+
* ambient of `L` does. Negative ringing, which a second-order fit of a sharp source has, is clamped
|
|
24
|
+
* to zero.
|
|
25
|
+
*
|
|
26
|
+
* **What it gives up** is the reflections: these replace the diffuse ambient only, and a glossy
|
|
27
|
+
* surface still reflects the frame's probes or sky. **What would make it wrong** is light the
|
|
28
|
+
* volume holds at a frequency nine coefficients cannot carry — a sharp sun patch — which is the
|
|
29
|
+
* stage's own direct light's job and not this.
|
|
30
|
+
*/
|
|
31
|
+
/** Numbers `setAmbientSH` takes: nine coefficients of three channels. */
|
|
32
|
+
export declare const AMBIENT_SH_VALUES = 27;
|
|
33
|
+
/** Floats the lit stage's `uAmbientSH` holds: the coefficients, and whether they are on. */
|
|
34
|
+
export declare const AMBIENT_SH_FLOATS = 28;
|
|
35
|
+
/**
|
|
36
|
+
* The coefficients as the lit stage reads them, into `out` of `AMBIENT_SH_FLOATS`: the twenty-seven
|
|
37
|
+
* numbers in order and a last one that is 1, or every float zero for `null` — the frame's own
|
|
38
|
+
* ambient. Refuses a list that is not twenty-seven numbers, naming its length.
|
|
39
|
+
*/
|
|
40
|
+
export declare function packAmbientSH(coefficients: ArrayLike<number> | null, out: Float32Array): void;
|
|
41
|
+
/**
|
|
42
|
+
* The ambient a surface facing `nx, ny, nz` (unit) receives from these coefficients, into `out`
|
|
43
|
+
* (three floats): what `ambientHarmonics` in the lit stage computes. Run at no point by the engine;
|
|
44
|
+
* the reference its tests hold.
|
|
45
|
+
*/
|
|
46
|
+
export declare function ambientFromSH(coefficients: ArrayLike<number>, nx: number, ny: number, nz: number, out: Float32Array): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A draw's own ambient light, as nine spherical-harmonic coefficients: what `setAmbientSH` takes,
|
|
3
|
+
* how both backends pack it, and the arithmetic the lit stage evaluates, which its tests hold.
|
|
4
|
+
*
|
|
5
|
+
* **Why a draw needs its own.** The engine's diffuse ambient is one answer for a whole frame — the
|
|
6
|
+
* sky-and-ground gradient, or the probe grid's irradiance — so everything standing in one place is
|
|
7
|
+
* lit alike. A stage with a baked volume of indirect light (Unreal's volumetric lightmap) lights a
|
|
8
|
+
* character by sampling that volume where the character stands; a consumer that samples it each
|
|
9
|
+
* frame hands the result here, around that character's draws, and the character takes the light of
|
|
10
|
+
* the spot it is in rather than the frame's average.
|
|
11
|
+
*
|
|
12
|
+
* **The coefficients are of incoming radiance**, `L(ω) ≈ Σ c_lm Y_lm(ω)`, on the standard real
|
|
13
|
+
* basis in its usual order — `Y00`, then `Y1,-1 Y1,0 Y1,1`, then `Y2,-2 Y2,-1 Y2,0 Y2,1 Y2,2` —
|
|
14
|
+
* evaluated on the engine's own world axes as written: `Y1,-1 = 0.488603 y`, `Y1,0 = 0.488603 z`,
|
|
15
|
+
* `Y1,1 = 0.488603 x`, `Y2,-2 = 1.092548 xy`, `Y2,-1 = 1.092548 yz`, `Y2,0 = 0.315392 (3z² − 1)`,
|
|
16
|
+
* `Y2,1 = 1.092548 xz`, `Y2,2 = 0.546274 (x² − y²)`, with y up. Three numbers a coefficient, red
|
|
17
|
+
* green blue, twenty-seven in all. A source in another engine's axes is rotated into these first.
|
|
18
|
+
*
|
|
19
|
+
* **What the surface receives is the cosine convolution**, Ramamoorthi and Hanrahan's: the bands
|
|
20
|
+
* scaled by π, 2π/3 and π/4 and divided by π, which is the irradiance over π a Lambertian surface
|
|
21
|
+
* multiplies its albedo by — the same quantity the gradient and the probes hand the shader. A
|
|
22
|
+
* constant radiance `L` everywhere is `c00 = L / 0.282095` and lights a surface exactly as an
|
|
23
|
+
* ambient of `L` does. Negative ringing, which a second-order fit of a sharp source has, is clamped
|
|
24
|
+
* to zero.
|
|
25
|
+
*
|
|
26
|
+
* **What it gives up** is the reflections: these replace the diffuse ambient only, and a glossy
|
|
27
|
+
* surface still reflects the frame's probes or sky. **What would make it wrong** is light the
|
|
28
|
+
* volume holds at a frequency nine coefficients cannot carry — a sharp sun patch — which is the
|
|
29
|
+
* stage's own direct light's job and not this.
|
|
30
|
+
*/
|
|
31
|
+
/** Numbers `setAmbientSH` takes: nine coefficients of three channels. */
|
|
32
|
+
export const AMBIENT_SH_VALUES = 27;
|
|
33
|
+
/** Floats the lit stage's `uAmbientSH` holds: the coefficients, and whether they are on. */
|
|
34
|
+
export const AMBIENT_SH_FLOATS = 28;
|
|
35
|
+
/**
|
|
36
|
+
* The coefficients as the lit stage reads them, into `out` of `AMBIENT_SH_FLOATS`: the twenty-seven
|
|
37
|
+
* numbers in order and a last one that is 1, or every float zero for `null` — the frame's own
|
|
38
|
+
* ambient. Refuses a list that is not twenty-seven numbers, naming its length.
|
|
39
|
+
*/
|
|
40
|
+
export function packAmbientSH(coefficients, out) {
|
|
41
|
+
if (coefficients === null) {
|
|
42
|
+
out.fill(0);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (coefficients.length !== AMBIENT_SH_VALUES) {
|
|
46
|
+
throw new Error(`setAmbientSH: ${coefficients.length} values, where nine coefficients of red, green and ` +
|
|
47
|
+
`blue are ${AMBIENT_SH_VALUES}`);
|
|
48
|
+
}
|
|
49
|
+
for (let i = 0; i < AMBIENT_SH_VALUES; i++) {
|
|
50
|
+
const value = coefficients[i];
|
|
51
|
+
out[i] = Number.isFinite(value) ? value : 0;
|
|
52
|
+
}
|
|
53
|
+
out[AMBIENT_SH_VALUES] = 1;
|
|
54
|
+
}
|
|
55
|
+
/** The band factors of the cosine convolution, over π: 1, 2/3 and 1/4. */
|
|
56
|
+
const BAND = [1, 2 / 3, 1 / 4];
|
|
57
|
+
/**
|
|
58
|
+
* The ambient a surface facing `nx, ny, nz` (unit) receives from these coefficients, into `out`
|
|
59
|
+
* (three floats): what `ambientHarmonics` in the lit stage computes. Run at no point by the engine;
|
|
60
|
+
* the reference its tests hold.
|
|
61
|
+
*/
|
|
62
|
+
export function ambientFromSH(coefficients, nx, ny, nz, out) {
|
|
63
|
+
const basis = [
|
|
64
|
+
0.282095 * BAND[0],
|
|
65
|
+
0.488603 * ny * BAND[1],
|
|
66
|
+
0.488603 * nz * BAND[1],
|
|
67
|
+
0.488603 * nx * BAND[1],
|
|
68
|
+
1.092548 * nx * ny * BAND[2],
|
|
69
|
+
1.092548 * ny * nz * BAND[2],
|
|
70
|
+
0.315392 * (3 * nz * nz - 1) * BAND[2],
|
|
71
|
+
1.092548 * nx * nz * BAND[2],
|
|
72
|
+
0.546274 * (nx * nx - ny * ny) * BAND[2],
|
|
73
|
+
];
|
|
74
|
+
for (let c = 0; c < 3; c++) {
|
|
75
|
+
let sum = 0;
|
|
76
|
+
for (let k = 0; k < 9; k++)
|
|
77
|
+
sum += coefficients[k * 3 + c] * basis[k];
|
|
78
|
+
out[c] = Math.max(sum, 0);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -5,3 +5,13 @@ export declare function anisotropicAlphas(roughness: number, strength: number, o
|
|
|
5
5
|
* are `th`, `bh` and `nh`. 1 at the mirror direction.
|
|
6
6
|
*/
|
|
7
7
|
export declare function anisotropicLobe(th: number, bh: number, nh: number, alphaT: number, alphaB: number): number;
|
|
8
|
+
/** Three components in the lobe's frame: along the direction, across it, along the normal. */
|
|
9
|
+
export type FrameVector = readonly [number, number, number];
|
|
10
|
+
/**
|
|
11
|
+
* The physical form of the same lobe, `π · D · Vis · N·L`, for a surface whose highlight is GGX's
|
|
12
|
+
* own (`SurfaceMaterial.physicalSpecular`): the stretched distribution normalised as a BRDF's, and
|
|
13
|
+
* Smith's height-correlated masking stretched with it (Heitz 2014, as Filament writes it), Fresnel
|
|
14
|
+
* left to the caller. The half vector, the light and the view are each in the lobe's frame. At
|
|
15
|
+
* strength 0 it is isotropic GGX, the term skin's and the eye's highlights are.
|
|
16
|
+
*/
|
|
17
|
+
export declare function anisotropicPhysicalLobe(half: FrameVector, light: FrameVector, view: FrameVector, alphaT: number, alphaB: number): number;
|
|
@@ -31,3 +31,22 @@ export function anisotropicLobe(th, bh, nh, alphaT, alphaB) {
|
|
|
31
31
|
const d = x * x + y * y + nh * nh;
|
|
32
32
|
return 1 / Math.max(d * d, 1e-8);
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The physical form of the same lobe, `π · D · Vis · N·L`, for a surface whose highlight is GGX's
|
|
36
|
+
* own (`SurfaceMaterial.physicalSpecular`): the stretched distribution normalised as a BRDF's, and
|
|
37
|
+
* Smith's height-correlated masking stretched with it (Heitz 2014, as Filament writes it), Fresnel
|
|
38
|
+
* left to the caller. The half vector, the light and the view are each in the lobe's frame. At
|
|
39
|
+
* strength 0 it is isotropic GGX, the term skin's and the eye's highlights are.
|
|
40
|
+
*/
|
|
41
|
+
export function anisotropicPhysicalLobe(half, light, view, alphaT, alphaB) {
|
|
42
|
+
const x = half[0] / alphaT;
|
|
43
|
+
const y = half[1] / alphaB;
|
|
44
|
+
const d = x * x + y * y + half[2] * half[2];
|
|
45
|
+
const distribution = 1 / (Math.PI * alphaT * alphaB * d * d);
|
|
46
|
+
const ndl = light[2];
|
|
47
|
+
const ndv = view[2];
|
|
48
|
+
const lambdaView = ndl * Math.hypot(alphaT * view[0], alphaB * view[1], ndv);
|
|
49
|
+
const lambdaLight = ndv * Math.hypot(alphaT * light[0], alphaB * light[1], ndl);
|
|
50
|
+
const visibility = 0.5 / Math.max(lambdaView + lambdaLight, 1e-5);
|
|
51
|
+
return Math.PI * distribution * visibility * ndl;
|
|
52
|
+
}
|
|
@@ -86,7 +86,34 @@ export interface AreaLightSource {
|
|
|
86
86
|
* every caster, not just the fixture.
|
|
87
87
|
*/
|
|
88
88
|
shadowNear?: number;
|
|
89
|
+
/**
|
|
90
|
+
* How far the rectangle's light reaches, in metres from its centre: past it the light is zero,
|
|
91
|
+
* windowed down to it, so a clustered rectangle can be binned into the froxels it reaches and no
|
|
92
|
+
* others. **Read only where the rectangle is shaded through the froxel table** — the ones past
|
|
93
|
+
* `maxAreaLights` with `clusteredLights` on; the fixed four light everything they face, as they
|
|
94
|
+
* always have. Absent, it is where the rectangle's irradiance on its axis falls to a thousandth
|
|
95
|
+
* of a scene unit, and never inside the rectangle itself. Unreal's `AttenuationRadius`, in metres.
|
|
96
|
+
*/
|
|
97
|
+
range?: number;
|
|
98
|
+
/**
|
|
99
|
+
* Barn doors: a flap hinged at each of the rectangle's four edges, standing this many degrees from
|
|
100
|
+
* its normal. 90, or absent, folds them flat and they hide nothing; smaller closes them, so the
|
|
101
|
+
* light narrows to the opening they leave — a rectangle at 50° throws a beam rather than filling
|
|
102
|
+
* its hemisphere. Unreal's `BarnDoorAngle`, whose default of 88° is nearly flat.
|
|
103
|
+
*
|
|
104
|
+
* What a fragment sees past the doors is the part of the rectangle no door's tip hides, one axis
|
|
105
|
+
* at a time, and the rectangle then shades as that smaller rectangle, its highlight included.
|
|
106
|
+
* Its shadow map is still baked from the whole rectangle's centre. **What it gives up**: each
|
|
107
|
+
* door is taken as endless along its hinge, so the two axes clip apart and the corner where two
|
|
108
|
+
* doors meet hides a square rather than the mitre two real flaps make. One-sided: a two-sided
|
|
109
|
+
* rectangle's back face has none.
|
|
110
|
+
*/
|
|
111
|
+
barnDoorAngle?: number;
|
|
112
|
+
/** The barn doors' length in metres. Absent, 0.2: Unreal's default of 20 cm. */
|
|
113
|
+
barnDoorLength?: number;
|
|
89
114
|
}
|
|
115
|
+
/** The irradiance a derived `range` ends at, in scene units. See `AreaLightSource.range`. */
|
|
116
|
+
export declare const AREA_RANGE_CUTOFF = 0.001;
|
|
90
117
|
/** The five arrays the shader declares, filled once a frame from whatever a caller supplied. */
|
|
91
118
|
export interface AreaLightBuffer {
|
|
92
119
|
count: number;
|
|
@@ -96,8 +123,35 @@ export interface AreaLightBuffer {
|
|
|
96
123
|
readonly up: Float32Array;
|
|
97
124
|
readonly sizes: Float32Array;
|
|
98
125
|
readonly twoSided: Float32Array;
|
|
126
|
+
/** One a rectangle: how far its light reaches. See `AreaLightSource.range`. */
|
|
127
|
+
readonly ranges?: Float32Array;
|
|
128
|
+
/**
|
|
129
|
+
* Two a rectangle: the cosine of its barn doors' angle from its normal, then their length in
|
|
130
|
+
* metres — 0 and 0 for none. See `AreaLightSource.barnDoorAngle`.
|
|
131
|
+
*/
|
|
132
|
+
readonly barnDoors?: Float32Array;
|
|
99
133
|
}
|
|
100
134
|
export declare function createAreaLightBuffer(capacity?: number): AreaLightBuffer;
|
|
135
|
+
/** Unreal's default barn door length, in metres. See `AreaLightSource.barnDoorLength`. */
|
|
136
|
+
export declare const DEFAULT_BARN_DOOR_LENGTH = 0.2;
|
|
137
|
+
/**
|
|
138
|
+
* A rectangle's barn doors as the shader reads them, into `out[at]` and `out[at + 1]`: the cosine of
|
|
139
|
+
* their angle and their length. An angle not between 0 and 90 degrees, or a length not above zero,
|
|
140
|
+
* is no doors at all, written as 0 and 0 — which the shader reads as "nothing hidden".
|
|
141
|
+
*/
|
|
142
|
+
export declare function barnDoorsOf(light: AreaLightSource, out: Float32Array, at: number): void;
|
|
143
|
+
/**
|
|
144
|
+
* The fixed arm's half extents and barn doors, four a rectangle as `uAreaLightSize` holds them: the
|
|
145
|
+
* two half extents, then the doors' cosine and length. Into a target the binder owns, for the first
|
|
146
|
+
* `MAX_AREA_LIGHTS` alone, which are all the fixed arm reads.
|
|
147
|
+
*/
|
|
148
|
+
export declare function packAreaSizesAndDoors(lights: AreaLightBuffer, out: Float32Array): void;
|
|
149
|
+
/**
|
|
150
|
+
* How far a rectangle's light reaches when it names no range: where its irradiance on its own axis,
|
|
151
|
+
* `L · A / d²` for a rectangle of radiance `L` and area `A` seen from far, falls to
|
|
152
|
+
* `AREA_RANGE_CUTOFF`. Never less than the rectangle's own half-diagonal.
|
|
153
|
+
*/
|
|
154
|
+
export declare function areaRange(r: number, g: number, b: number, halfWidth: number, halfHeight: number): number;
|
|
101
155
|
/**
|
|
102
156
|
* Fill the buffer from a caller's list, normalising the axes and orthogonalising them.
|
|
103
157
|
*
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* iteration of the loop, exactly as `MAX_POINT_LIGHTS` is.
|
|
9
9
|
*/
|
|
10
10
|
export const MAX_AREA_LIGHTS = 4;
|
|
11
|
+
/** The irradiance a derived `range` ends at, in scene units. See `AreaLightSource.range`. */
|
|
12
|
+
export const AREA_RANGE_CUTOFF = 1e-3;
|
|
11
13
|
export function createAreaLightBuffer(capacity = MAX_AREA_LIGHTS) {
|
|
12
14
|
return {
|
|
13
15
|
count: 0,
|
|
@@ -17,8 +19,53 @@ export function createAreaLightBuffer(capacity = MAX_AREA_LIGHTS) {
|
|
|
17
19
|
up: new Float32Array(capacity * 3),
|
|
18
20
|
sizes: new Float32Array(capacity * 2),
|
|
19
21
|
twoSided: new Float32Array(capacity),
|
|
22
|
+
ranges: new Float32Array(capacity),
|
|
23
|
+
barnDoors: new Float32Array(capacity * 2),
|
|
20
24
|
};
|
|
21
25
|
}
|
|
26
|
+
/** Unreal's default barn door length, in metres. See `AreaLightSource.barnDoorLength`. */
|
|
27
|
+
export const DEFAULT_BARN_DOOR_LENGTH = 0.2;
|
|
28
|
+
/**
|
|
29
|
+
* A rectangle's barn doors as the shader reads them, into `out[at]` and `out[at + 1]`: the cosine of
|
|
30
|
+
* their angle and their length. An angle not between 0 and 90 degrees, or a length not above zero,
|
|
31
|
+
* is no doors at all, written as 0 and 0 — which the shader reads as "nothing hidden".
|
|
32
|
+
*/
|
|
33
|
+
export function barnDoorsOf(light, out, at) {
|
|
34
|
+
const angle = light.barnDoorAngle;
|
|
35
|
+
const length = light.barnDoorLength ?? DEFAULT_BARN_DOOR_LENGTH;
|
|
36
|
+
if (angle === undefined || !(angle >= 0 && angle < 90) || !(length > 0)) {
|
|
37
|
+
out[at] = 0;
|
|
38
|
+
out[at + 1] = 0;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
out[at] = Math.cos((angle * Math.PI) / 180);
|
|
42
|
+
out[at + 1] = length;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The fixed arm's half extents and barn doors, four a rectangle as `uAreaLightSize` holds them: the
|
|
46
|
+
* two half extents, then the doors' cosine and length. Into a target the binder owns, for the first
|
|
47
|
+
* `MAX_AREA_LIGHTS` alone, which are all the fixed arm reads.
|
|
48
|
+
*/
|
|
49
|
+
export function packAreaSizesAndDoors(lights, out) {
|
|
50
|
+
const doors = lights.barnDoors;
|
|
51
|
+
for (let a = 0; a < MAX_AREA_LIGHTS; a++) {
|
|
52
|
+
out[a * 4] = lights.sizes[a * 2] ?? 0;
|
|
53
|
+
out[a * 4 + 1] = lights.sizes[a * 2 + 1] ?? 0;
|
|
54
|
+
out[a * 4 + 2] = doors?.[a * 2] ?? 0;
|
|
55
|
+
out[a * 4 + 3] = doors?.[a * 2 + 1] ?? 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* How far a rectangle's light reaches when it names no range: where its irradiance on its own axis,
|
|
60
|
+
* `L · A / d²` for a rectangle of radiance `L` and area `A` seen from far, falls to
|
|
61
|
+
* `AREA_RANGE_CUTOFF`. Never less than the rectangle's own half-diagonal.
|
|
62
|
+
*/
|
|
63
|
+
export function areaRange(r, g, b, halfWidth, halfHeight) {
|
|
64
|
+
const radiance = Math.max(r, g, b, 0);
|
|
65
|
+
const area = 4 * halfWidth * halfHeight;
|
|
66
|
+
const diagonal = Math.hypot(halfWidth, halfHeight);
|
|
67
|
+
return Math.max(Math.sqrt((radiance * area) / AREA_RANGE_CUTOFF), diagonal);
|
|
68
|
+
}
|
|
22
69
|
/**
|
|
23
70
|
* Fill the buffer from a caller's list, normalising the axes and orthogonalising them.
|
|
24
71
|
*
|
|
@@ -86,6 +133,14 @@ export function selectAreaLights(lights, out) {
|
|
|
86
133
|
out.sizes[slot * 2] = Math.max(1e-4, light.halfWidth);
|
|
87
134
|
out.sizes[slot * 2 + 1] = Math.max(1e-4, light.halfHeight);
|
|
88
135
|
out.twoSided[slot] = light.twoSided === true ? 1 : 0;
|
|
136
|
+
if (out.ranges !== undefined) {
|
|
137
|
+
out.ranges[slot] =
|
|
138
|
+
light.range !== undefined && light.range > 0
|
|
139
|
+
? light.range
|
|
140
|
+
: areaRange(light.r, light.g, light.b, light.halfWidth, light.halfHeight);
|
|
141
|
+
}
|
|
142
|
+
if (out.barnDoors !== undefined)
|
|
143
|
+
barnDoorsOf(light, out.barnDoors, slot * 2);
|
|
89
144
|
}
|
|
90
145
|
return out;
|
|
91
146
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Bounds } from '../../math/bounds.ts';
|
|
2
2
|
import type { Vec3 } from '../../math/color.ts';
|
|
3
|
+
import type { Camera } from '../camera.ts';
|
|
3
4
|
import type { ReadonlyMat4 } from 'gl-matrix';
|
|
4
5
|
import type { MeshData } from '../mesh.ts';
|
|
5
6
|
import type { ProbeBakeOptions } from '../reflectionProbe.ts';
|
|
@@ -7,6 +8,8 @@ import type { Renderer, TranslucentMeshOptions } from './webgl2/renderer.ts';
|
|
|
7
8
|
import type { InstancedOptions, MeshInstances } from '../instances.ts';
|
|
8
9
|
import type { SurfaceMaterial } from '../surfaceTexture.ts';
|
|
9
10
|
import type { SurfaceSource } from '../compressedSource.ts';
|
|
11
|
+
import type { LightmapPage } from '../lightmap.ts';
|
|
12
|
+
import type { DeviceParticles } from '../particlePool.ts';
|
|
10
13
|
import type { ClothBindingData } from '../clothBindingData.ts';
|
|
11
14
|
import type { TextStyle } from '../textLayout.ts';
|
|
12
15
|
import type { SdfFont } from '../sdfFont.ts';
|
|
@@ -186,7 +189,7 @@ export interface MeshOptions {
|
|
|
186
189
|
}
|
|
187
190
|
export type RendererApi = Omit<{
|
|
188
191
|
[K in keyof Renderer]: Renderer[K];
|
|
189
|
-
}, 'gpuTimer' | 'createMesh' | 'createMeshIncremental' | 'updateMesh' | 'drawMesh' | 'disposeMesh' | 'drawTranslucentMesh' | 'drawLightVolume' | 'drawFilm' | 'createScatter' | 'drawScatter' | 'uploadScatter' | 'disposeScatter' | 'createInstanced' | 'uploadInstanced' | 'drawInstanced' | 'drawTranslucentInstanced' | 'disposeInstanced' | 'createWater' | 'drawWater' | 'disposeWater' | 'createPlumes' | 'drawPlumes' | 'disposePlumes' | 'setPlumeScale' | 'createCaustics' | 'drawCaustics' | 'disposeCaustics' | 'createParticles' | 'drawParticles' | 'disposeParticles' | 'createWindStreaks' | 'drawWindStreaks' | 'disposeWindStreaks' | 'createFlock' | 'drawFlock' | 'disposeFlock' | 'createBolts' | 'drawBolts' | 'disposeBolts' | 'createLines' | 'drawLines' | 'disposeLines' | 'createText' | 'setText' | 'setPlate' | 'drawText' | 'textWidth' | 'disposeText' | 'createSdfText' | 'setSdfText' | 'drawSdfText' | 'disposeSdfText' | 'createSurfaceTexture' | 'createSurfaceTextureArray' | 'updateSurfaceTexture' | 'disposeSurfaceTexture' | 'setSurfaceTexture' | 'setMaterial' | 'createClothBinding' | 'createClothParticles' | 'updateClothParticles' | 'setCloth' | 'disposeClothBinding' | 'disposeClothParticles'> & {
|
|
192
|
+
}, 'gpuTimer' | 'createMesh' | 'createMeshIncremental' | 'updateMesh' | 'drawMesh' | 'disposeMesh' | 'drawTranslucentMesh' | 'drawLightVolume' | 'drawFilm' | 'createScatter' | 'drawScatter' | 'uploadScatter' | 'disposeScatter' | 'createInstanced' | 'uploadInstanced' | 'drawInstanced' | 'drawTranslucentInstanced' | 'disposeInstanced' | 'createWater' | 'drawWater' | 'disposeWater' | 'createPlumes' | 'drawPlumes' | 'disposePlumes' | 'setPlumeScale' | 'createCaustics' | 'drawCaustics' | 'disposeCaustics' | 'createParticles' | 'drawParticles' | 'drawDeviceParticles' | 'disposeParticles' | 'createWindStreaks' | 'drawWindStreaks' | 'disposeWindStreaks' | 'createFlock' | 'drawFlock' | 'disposeFlock' | 'createBolts' | 'drawBolts' | 'disposeBolts' | 'createLines' | 'drawLines' | 'disposeLines' | 'createText' | 'setText' | 'setPlate' | 'drawText' | 'textWidth' | 'disposeText' | 'createSdfText' | 'setSdfText' | 'drawSdfText' | 'disposeSdfText' | 'createSurfaceTexture' | 'createSurfaceTextureArray' | 'createLightmap' | 'createSceneCapture' | 'captureScene' | 'updateSurfaceTexture' | 'disposeSurfaceTexture' | 'setSurfaceTexture' | 'setMaterial' | 'createClothBinding' | 'createClothParticles' | 'updateClothParticles' | 'setCloth' | 'disposeClothBinding' | 'disposeClothParticles'> & {
|
|
190
193
|
/**
|
|
191
194
|
* A mesh's cloth binding: which simulation triangle each of its vertices follows, where on it and
|
|
192
195
|
* by how much (`ClothBindingData`). The mesh must be skinned — a binding blends each vertex
|
|
@@ -229,6 +232,35 @@ export type RendererApi = Omit<{
|
|
|
229
232
|
* `updateSurfaceTexture` refuses an array.
|
|
230
233
|
*/
|
|
231
234
|
createSurfaceTextureArray(sources: readonly SurfaceSource[], options?: Parameters<Renderer['createSurfaceTexture']>[1]): SurfaceTextureHandle;
|
|
235
|
+
/**
|
|
236
|
+
* A baked lightmap page on the device, as the texture a `lightmapModel` material takes for its
|
|
237
|
+
* `modelMap`: two layers of four bytes a texel, the irradiance as an rgb9e5 word and the
|
|
238
|
+
* direction, which the lit stage decodes and filters itself, clamped at the page's edges, with no
|
|
239
|
+
* mip chain. A page whose irradiance arrives packed uploads where it lies. Disposed as any texture is, with
|
|
240
|
+
* `disposeSurfaceTexture`; `updateSurfaceTexture` refuses it, as it refuses any array. See
|
|
241
|
+
* `lightmap.ts` for what a surface does with it.
|
|
242
|
+
*/
|
|
243
|
+
createLightmap(page: LightmapPage): SurfaceTextureHandle;
|
|
244
|
+
/**
|
|
245
|
+
* A texture the scene can be drawn into from a camera of the caller's (`captureScene`), which a
|
|
246
|
+
* material then shows like any image — most often as its `emissive`, for a screen in the world
|
|
247
|
+
* showing what a camera elsewhere sees. `width` and `height` in pixels, 1 to 4096. It holds
|
|
248
|
+
* radiance, at the colour format a probe takes: half floats under `hdrScene`, bytes otherwise.
|
|
249
|
+
* Disposed as any texture is; `updateSurfaceTexture` refuses it. See `sceneCapture.ts`.
|
|
250
|
+
*/
|
|
251
|
+
createSceneCapture(width: number, height: number): SurfaceTextureHandle;
|
|
252
|
+
/**
|
|
253
|
+
* Draw the scene into a capture from `camera`, at the moment a caller says, usually once a frame
|
|
254
|
+
* before the frame's own world. `draw` is handed the camera, its matrices updated for the
|
|
255
|
+
* capture's shape, and submits the scene exactly as it would to the screen — `bindMeshPass`,
|
|
256
|
+
* `drawMesh` and the rest; `bindMeshPass` the frame's own camera again afterwards. The output
|
|
257
|
+
* transform is held off, so a screen showing it is graded once, with the frame.
|
|
258
|
+
*
|
|
259
|
+
* **The mesh pass alone**, as a probe bake is: what a scene draws after its world is in the
|
|
260
|
+
* capture only if `draw` draws it, and no temporal resolve or effect after the world runs on it.
|
|
261
|
+
* Returns whether it drew: false for a texture that is not a capture.
|
|
262
|
+
*/
|
|
263
|
+
captureScene(capture: SurfaceTextureHandle, camera: Camera, clearColor: Vec3, draw: (camera: Camera) => void): boolean;
|
|
232
264
|
/**
|
|
233
265
|
* Replace a texture's pixels, keeping the GPU object and its sampler state.
|
|
234
266
|
*
|
|
@@ -428,11 +460,20 @@ export type RendererApi = Omit<{
|
|
|
428
460
|
* have shared one already do. WebGL2 still needs telling, and still checks that the two
|
|
429
461
|
* materials match.
|
|
430
462
|
*/
|
|
431
|
-
createParticles(capacity: number, options: Omit<Parameters<Renderer['createParticles']>[1], 'reuse'> & {
|
|
463
|
+
createParticles(capacity: number, options: Omit<Parameters<Renderer['createParticles']>[1], 'reuse' | 'texture'> & {
|
|
432
464
|
readonly reuse?: ParticleHandle;
|
|
465
|
+
/** A `'sprite'`'s image. Re-typed to the handle for `reuse`'s reason. */
|
|
466
|
+
readonly texture?: SurfaceTextureHandle;
|
|
433
467
|
}): ParticleHandle;
|
|
434
468
|
/** Draw a pool's live particles, after the opaque scene. */
|
|
435
469
|
drawParticles(batch: ParticleHandle, data: Parameters<Renderer['drawParticles']>[1], camera: Parameters<Renderer['drawParticles']>[2], env: Parameters<Renderer['drawParticles']>[3], timeSeconds: number): void;
|
|
470
|
+
/**
|
|
471
|
+
* Draw a pool's particles from a buffer a caller's own compute wrote (`registerCompute`), where
|
|
472
|
+
* they lie: the pool's material, blend, flipbook and fades, its instance stream the caller's
|
|
473
|
+
* buffer. WebGPU only; WebGL2 says so once and draws nothing. Not sorted. See `DeviceParticles`
|
|
474
|
+
* for the layout.
|
|
475
|
+
*/
|
|
476
|
+
drawDeviceParticles(batch: ParticleHandle, particles: DeviceParticles, camera: Parameters<Renderer['drawParticles']>[2], env: Parameters<Renderer['drawParticles']>[3], timeSeconds: number): void;
|
|
436
477
|
/** Release a particle pool. */
|
|
437
478
|
disposeParticles(batch: ParticleHandle): void;
|
|
438
479
|
/** Draw a wet film over geometry, using a handle as the surface it lies on. */
|
|
@@ -26,6 +26,8 @@ export declare class InstancedBatch {
|
|
|
26
26
|
private readonly buffer;
|
|
27
27
|
private readonly vao;
|
|
28
28
|
private readonly staging;
|
|
29
|
+
/** The survivors of a lightmapped batch's cull, made the first time one is culled. */
|
|
30
|
+
private keptRegioned;
|
|
29
31
|
private readonly kept;
|
|
30
32
|
constructor(gl: WebGL2RenderingContext, mesh: Mesh, capacity: number, cull?: boolean);
|
|
31
33
|
upload(gl: WebGL2RenderingContext, data: MeshInstances): void;
|
|
@@ -25,6 +25,8 @@ export class InstancedBatch {
|
|
|
25
25
|
buffer;
|
|
26
26
|
vao;
|
|
27
27
|
staging;
|
|
28
|
+
/** The survivors of a lightmapped batch's cull, made the first time one is culled. */
|
|
29
|
+
keptRegioned = null;
|
|
28
30
|
kept;
|
|
29
31
|
constructor(gl, mesh, capacity, cull = false) {
|
|
30
32
|
this.mesh = mesh;
|
|
@@ -67,10 +69,17 @@ export class InstancedBatch {
|
|
|
67
69
|
const kept = this.kept;
|
|
68
70
|
if (kept === null)
|
|
69
71
|
return 0;
|
|
70
|
-
|
|
72
|
+
/* A lightmapped batch's survivors keep their regions, in a copy that carries them. */
|
|
73
|
+
const into = data.lightmapRegions === undefined
|
|
74
|
+
? kept.instances
|
|
75
|
+
: (this.keptRegioned ??= {
|
|
76
|
+
...createMeshInstances(this.capacity),
|
|
77
|
+
lightmapRegions: new Float32Array(this.capacity * 4),
|
|
78
|
+
});
|
|
79
|
+
const count = cullInstances(data, this.mesh.bounds, frustum, into);
|
|
71
80
|
if (count === 0)
|
|
72
81
|
return 0;
|
|
73
|
-
packInstances(
|
|
82
|
+
packInstances(into, this.staging);
|
|
74
83
|
gl.bindBuffer(gl.ARRAY_BUFFER, kept.buffer);
|
|
75
84
|
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.staging, 0, count * INSTANCE_FLOATS);
|
|
76
85
|
this.mesh.drawInstancesThrough(gl, kept.vao, count);
|