@driftengine/core 4.8.7 → 4.10.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/CHANGELOG.json +123 -11
- package/README.md +43 -38
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -3
- package/dist/render/ambientHarmonics.d.ts +1 -1
- package/dist/render/ambientHarmonics.js +1 -1
- package/dist/render/areaLights.d.ts +4 -4
- package/dist/render/areaLights.js +1 -1
- package/dist/render/atmosphere.d.ts +13 -0
- package/dist/render/atmosphere.js +9 -1
- package/dist/render/backend/api.d.ts +19 -4
- package/dist/render/backend/createRenderer.d.ts +6 -0
- package/dist/render/backend/createRenderer.js +4 -1
- package/dist/render/backend/select.js +11 -5
- package/dist/render/backend/webgl2/boneAnimations.d.ts +29 -0
- package/dist/render/backend/webgl2/boneAnimations.js +80 -0
- package/dist/render/backend/webgl2/instanced.d.ts +5 -1
- package/dist/render/backend/webgl2/instanced.js +13 -1
- package/dist/render/backend/webgl2/renderer.d.ts +180 -4
- package/dist/render/backend/webgl2/renderer.js +550 -40
- package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +5 -3
- package/dist/render/backend/webgl2/skinPaletteTexture.js +6 -4
- package/dist/render/backend/webgpu/boneAnimations.d.ts +34 -0
- package/dist/render/backend/webgpu/boneAnimations.js +76 -0
- package/dist/render/backend/webgpu/buffers.d.ts +19 -4
- package/dist/render/backend/webgpu/buffers.js +18 -11
- package/dist/render/backend/webgpu/compressedUpload.d.ts +0 -1
- package/dist/render/backend/webgpu/compressedUpload.js +53 -8
- package/dist/render/backend/webgpu/depthPass.d.ts +59 -3
- package/dist/render/backend/webgpu/depthPass.js +49 -14
- package/dist/render/backend/webgpu/device.d.ts +7 -1
- package/dist/render/backend/webgpu/device.js +31 -3
- package/dist/render/backend/webgpu/drawCommand.d.ts +18 -4
- package/dist/render/backend/webgpu/drawCommand.js +10 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +100 -42
- package/dist/render/backend/webgpu/flatPass.js +191 -43
- package/dist/render/backend/webgpu/instanced.d.ts +14 -1
- package/dist/render/backend/webgpu/instanced.js +24 -1
- package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
- package/dist/render/backend/webgpu/materialStore.js +265 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +6 -0
- package/dist/render/backend/webgpu/pipelineCache.js +7 -0
- package/dist/render/backend/webgpu/postPass.d.ts +51 -9
- package/dist/render/backend/webgpu/postPass.js +16 -2
- package/dist/render/backend/webgpu/reflectionSurfacePass.d.ts +30 -0
- package/dist/render/backend/webgpu/reflectionSurfacePass.js +100 -0
- package/dist/render/backend/webgpu/renderer.d.ts +283 -37
- package/dist/render/backend/webgpu/renderer.js +1363 -202
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +7 -3
- package/dist/render/backend/webgpu/skinPaletteRing.js +13 -7
- package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +6 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.js +7 -1
- package/dist/render/backend/webgpu/staticBundles.d.ts +125 -0
- package/dist/render/backend/webgpu/staticBundles.js +241 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +10 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +20 -2
- package/dist/render/backend/webgpu/uniformRing.d.ts +21 -0
- package/dist/render/backend/webgpu/uniformRing.js +9 -1
- package/dist/render/bloomChain.d.ts +3 -3
- package/dist/render/boneAnimation.d.ts +92 -0
- package/dist/render/boneAnimation.js +133 -0
- package/dist/render/compressedSource.d.ts +33 -13
- package/dist/render/compressedSource.js +70 -25
- package/dist/render/displayRange.d.ts +31 -0
- package/dist/render/displayRange.js +47 -0
- package/dist/render/filmicCurve.d.ts +74 -0
- package/dist/render/filmicCurve.js +203 -0
- package/dist/render/fog.d.ts +4 -1
- package/dist/render/fog.js +12 -2
- package/dist/render/frame/resources.d.ts +2 -2
- package/dist/render/frame/resources.js +6 -0
- package/dist/render/frameReflections.d.ts +40 -0
- package/dist/render/frameReflections.js +48 -0
- package/dist/render/glCompressed.js +83 -0
- package/dist/render/instances.d.ts +26 -0
- package/dist/render/lightBudget.d.ts +10 -0
- package/dist/render/lightBudget.js +10 -0
- package/dist/render/lightmap.d.ts +1 -1
- package/dist/render/mesh.d.ts +5 -0
- package/dist/render/mesh.js +6 -0
- package/dist/render/pass.d.ts +49 -0
- package/dist/render/pointLightSelection.d.ts +4 -4
- package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
- package/dist/render/reflectionSurfaceTargets.js +99 -0
- package/dist/render/renderQuality.d.ts +39 -8
- package/dist/render/renderQuality.js +4 -0
- package/dist/render/sceneTarget.d.ts +5 -0
- package/dist/render/sceneTarget.js +24 -1
- package/dist/render/screenSpaceReflection.d.ts +7 -1
- package/dist/render/screenSpaceReflection.js +5 -0
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/boneAnimation.d.ts +19 -0
- package/dist/render/shaders/boneAnimation.js +63 -0
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/depth.d.ts +7 -0
- package/dist/render/shaders/depth.js +35 -10
- package/dist/render/shaders/film.d.ts +1 -1
- package/dist/render/shaders/filmLook.js +2 -1
- package/dist/render/shaders/fire.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +2 -0
- package/dist/render/shaders/flat/index.d.ts +16 -0
- package/dist/render/shaders/flat/index.js +33 -5
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +43 -5
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/overlay.d.ts +16 -0
- package/dist/render/shaders/flat/overlay.js +117 -0
- package/dist/render/shaders/flat/pointShadow.js +3 -3
- package/dist/render/shaders/flat/preamble.js +38 -24
- package/dist/render/shaders/flat/reflectionSurface.d.ts +21 -0
- package/dist/render/shaders/flat/reflectionSurface.js +61 -0
- package/dist/render/shaders/fog.d.ts +1 -1
- package/dist/render/shaders/fog.js +9 -2
- package/dist/render/shaders/fringe.d.ts +29 -0
- package/dist/render/shaders/fringe.js +55 -0
- package/dist/render/shaders/generated/arcane.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/arcane.wgsl.js +1 -1
- 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/caustics.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/caustics.wgsl.js +1 -1
- package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
- package/dist/render/shaders/generated/depth.wgsl.js +93 -0
- package/dist/render/shaders/generated/film.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/film.wgsl.js +1 -1
- package/dist/render/shaders/generated/fire.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/fire.wgsl.js +1 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +3254 -2920
- package/dist/render/shaders/generated/flat.wgsl.js +3292 -2957
- package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/line.wgsl.js +1 -1
- package/dist/render/shaders/generated/particle.wgsl.d.ts +4 -4
- package/dist/render/shaders/generated/particle.wgsl.js +4 -4
- package/dist/render/shaders/generated/rush.wgsl.d.ts +56 -26
- package/dist/render/shaders/generated/rush.wgsl.js +56 -26
- package/dist/render/shaders/generated/scatter.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/scatter.wgsl.js +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/smoke.wgsl.js +1 -1
- package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/ssrResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +22 -2
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +22 -2
- package/dist/render/shaders/generated/water.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/water.wgsl.js +1 -1
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +2 -2
- package/dist/render/shaders/gpudriven/fog.wgsl.js +11 -3
- package/dist/render/shaders/line.d.ts +1 -1
- package/dist/render/shaders/outputTransform.d.ts +7 -0
- package/dist/render/shaders/outputTransform.js +28 -14
- package/dist/render/shaders/particle.d.ts +3 -3
- package/dist/render/shaders/rush.js +54 -11
- package/dist/render/shaders/scatter.d.ts +1 -1
- package/dist/render/shaders/smoke.d.ts +1 -1
- package/dist/render/shaders/ssrResolve.d.ts +17 -0
- package/dist/render/shaders/ssrResolve.js +51 -0
- package/dist/render/shaders/ssrTrace.js +26 -0
- package/dist/render/shaders/vertexChannel.d.ts +7 -0
- package/dist/render/shaders/vertexChannel.js +26 -0
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/ssrPass.d.ts +16 -0
- package/dist/render/ssrPass.js +106 -1
- package/dist/render/staticDraws.d.ts +47 -0
- package/dist/render/staticDraws.js +43 -0
- package/dist/render/surfaceOverlay.d.ts +132 -0
- package/dist/render/surfaceOverlay.js +85 -0
- package/dist/render/surfaceTexture.d.ts +57 -7
- package/dist/render/surfaceTexture.js +125 -17
- package/dist/render/temporalAa.d.ts +14 -0
- package/dist/render/temporalAa.js +20 -0
- package/dist/render/vertexDefaults.d.ts +17 -0
- package/dist/render/vertexDefaults.js +24 -0
- package/package.json +6 -6
- package/src/index.ts +24 -2
- package/src/render/ambientHarmonics.ts +1 -1
- package/src/render/areaLights.ts +4 -4
- package/src/render/atmosphere.ts +22 -1
- package/src/render/backend/api.ts +22 -3
- package/src/render/backend/createRenderer.ts +18 -1
- package/src/render/backend/select.ts +10 -5
- package/src/render/backend/webgl2/boneAnimations.ts +105 -0
- package/src/render/backend/webgl2/instanced.ts +20 -1
- package/src/render/backend/webgl2/renderer.ts +672 -37
- package/src/render/backend/webgl2/skinPaletteTexture.ts +6 -4
- package/src/render/backend/webgpu/boneAnimations.ts +97 -0
- package/src/render/backend/webgpu/buffers.ts +42 -16
- package/src/render/backend/webgpu/compressedUpload.ts +59 -9
- package/src/render/backend/webgpu/depthPass.ts +51 -10
- package/src/render/backend/webgpu/device.ts +42 -3
- package/src/render/backend/webgpu/drawCommand.ts +22 -4
- package/src/render/backend/webgpu/flatPass.ts +250 -40
- package/src/render/backend/webgpu/instanced.ts +32 -1
- package/src/render/backend/webgpu/materialStore.ts +276 -0
- package/src/render/backend/webgpu/pipelineCache.ts +7 -0
- package/src/render/backend/webgpu/postPass.ts +18 -0
- package/src/render/backend/webgpu/reflectionSurfacePass.ts +114 -0
- package/src/render/backend/webgpu/renderer.ts +1655 -230
- package/src/render/backend/webgpu/skinPaletteRing.ts +13 -7
- package/src/render/backend/webgpu/skinPaletteTexture.ts +7 -1
- package/src/render/backend/webgpu/staticBundles.ts +363 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
- package/src/render/backend/webgpu/uniformRing.ts +10 -1
- package/src/render/bloomChain.ts +3 -3
- package/src/render/boneAnimation.ts +223 -0
- package/src/render/compressedSource.ts +121 -29
- package/src/render/displayRange.ts +61 -0
- package/src/render/filmicCurve.ts +229 -0
- package/src/render/fog.ts +19 -3
- package/src/render/frame/resources.ts +6 -0
- package/src/render/frameReflections.ts +72 -0
- package/src/render/glCompressed.ts +83 -0
- package/src/render/instances.ts +27 -0
- package/src/render/lightBudget.ts +11 -0
- package/src/render/lightmap.ts +1 -1
- package/src/render/mesh.ts +6 -0
- package/src/render/pass.ts +53 -1
- package/src/render/pointLightSelection.ts +4 -4
- package/src/render/reflectionSurfaceTargets.ts +105 -0
- package/src/render/renderQuality.ts +44 -8
- package/src/render/sceneTarget.ts +30 -2
- package/src/render/screenSpaceReflection.ts +7 -1
- package/src/render/shaders/boneAnimation.ts +63 -0
- package/src/render/shaders/depth.ts +45 -10
- package/src/render/shaders/filmLook.ts +2 -1
- package/src/render/shaders/flat/glassTint.ts +5 -1
- package/src/render/shaders/flat/index.ts +49 -5
- package/src/render/shaders/flat/main.ts +43 -5
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/overlay.ts +117 -0
- package/src/render/shaders/flat/pointShadow.ts +3 -3
- package/src/render/shaders/flat/preamble.ts +38 -24
- package/src/render/shaders/flat/reflectionSurface.ts +61 -0
- package/src/render/shaders/fog.ts +9 -2
- package/src/render/shaders/fringe.ts +59 -0
- package/src/render/shaders/generated/arcane.wgsl.ts +1 -1
- package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
- package/src/render/shaders/generated/caustics.wgsl.ts +1 -1
- package/src/render/shaders/generated/depth.wgsl.ts +95 -0
- package/src/render/shaders/generated/film.wgsl.ts +1 -1
- package/src/render/shaders/generated/fire.wgsl.ts +1 -1
- package/src/render/shaders/generated/flat.wgsl.ts +3292 -2957
- package/src/render/shaders/generated/line.wgsl.ts +1 -1
- package/src/render/shaders/generated/particle.wgsl.ts +4 -4
- package/src/render/shaders/generated/rush.wgsl.ts +56 -26
- package/src/render/shaders/generated/scatter.wgsl.ts +1 -1
- package/src/render/shaders/generated/smoke.wgsl.ts +1 -1
- package/src/render/shaders/generated/ssrResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/ssrTrace.wgsl.ts +22 -2
- package/src/render/shaders/generated/water.wgsl.ts +1 -1
- package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
- package/src/render/shaders/outputTransform.ts +30 -14
- package/src/render/shaders/rush.ts +54 -11
- package/src/render/shaders/ssrResolve.ts +52 -0
- package/src/render/shaders/ssrTrace.ts +26 -0
- package/src/render/shaders/vertexChannel.ts +27 -0
- package/src/render/ssrPass.ts +138 -1
- package/src/render/staticDraws.ts +95 -0
- package/src/render/surfaceOverlay.ts +195 -0
- package/src/render/surfaceTexture.ts +161 -27
- package/src/render/temporalAa.ts +20 -0
- package/src/render/vertexDefaults.ts +28 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* so a merged block wearing forty facades is one draw.
|
|
10
10
|
*/
|
|
11
11
|
import type { SurfaceModel } from './surfaceModel.ts';
|
|
12
|
-
import type { CompressedTextureFormat, SurfaceSource } from './compressedSource.ts';
|
|
12
|
+
import type { CompressedTextureFormat, CompressedTextureSource, SurfaceSource } from './compressedSource.ts';
|
|
13
13
|
import type { SurfaceLayerEffect } from './surfaceEffects.ts';
|
|
14
14
|
import type { CutoutMode } from './cutoutDither.ts';
|
|
15
15
|
import type { LightmapTexels } from './lightmap.ts';
|
|
@@ -107,7 +107,7 @@ export interface SurfaceMaterial<Texture = SurfaceTexture> {
|
|
|
107
107
|
* which is every light's default too, so a scene that names no channel is lit as it always was.
|
|
108
108
|
*
|
|
109
109
|
* A point or spot light shades this surface only where its `PointLightSet.lightChannels` and this
|
|
110
|
-
* share a bit —
|
|
110
|
+
* share a bit — lighting channels. A character's own key and rim lights on channel 2,
|
|
111
111
|
* and the character's materials on 3, light the character and leave the floor around it as the
|
|
112
112
|
* stage's lights alone have it. **What it does not reach**: the sun, the sky and the probes, area
|
|
113
113
|
* lights, DriftLight's volume and the GPU-driven pipeline light every surface whatever its mask.
|
|
@@ -141,6 +141,22 @@ export interface SurfaceMaterial<Texture = SurfaceTexture> {
|
|
|
141
141
|
* which is the opposite of what the caller asked for.
|
|
142
142
|
*/
|
|
143
143
|
occlusionStrength?: number;
|
|
144
|
+
/**
|
|
145
|
+
* How much of the environment this material's draws mirror, 0 to 1: the number
|
|
146
|
+
* `setSurfaceReflectivity` sets for every draw, stated by the material for its own. Absent, its
|
|
147
|
+
* draws wear the setter's, as every material's did before this existed.
|
|
148
|
+
*
|
|
149
|
+
* **Here so a static list can carry it.** A list keeps each entry's material and none of the
|
|
150
|
+
* renderer's state between draws (`createStaticDraws`), so a stage whose batches each mirror their
|
|
151
|
+
* own share of a baked reflection says so in the material it records. What it gives up is nothing a
|
|
152
|
+
* setter could do: one called after this material is set is ignored for the material's draws.
|
|
153
|
+
*/
|
|
154
|
+
reflectivity?: number;
|
|
155
|
+
/**
|
|
156
|
+
* How bright the environment this material's draws reflect is: `setEnvironmentGain`'s number,
|
|
157
|
+
* stated by the material for its own, and absent the setter's. Held non-negative.
|
|
158
|
+
*/
|
|
159
|
+
environmentGain?: number;
|
|
144
160
|
/**
|
|
145
161
|
* Scales the emissive map, per channel. Default 1.
|
|
146
162
|
*
|
|
@@ -164,14 +180,14 @@ export interface SurfaceMaterial<Texture = SurfaceTexture> {
|
|
|
164
180
|
modelMap?: Texture | null;
|
|
165
181
|
/**
|
|
166
182
|
* Whether a lamp's and the sun's highlight on this surface is GGX's own, `π · D · Vis · F · N·L`,
|
|
167
|
-
* as
|
|
168
|
-
* peak of one. **False by default**, every surface as it was.
|
|
183
|
+
* as physically based renderers and this engine's skin and eye shade it, rather than the engine's
|
|
184
|
+
* lobe scaled to a peak of one. **False by default**, every surface as it was.
|
|
169
185
|
*
|
|
170
186
|
* The peak-normalised lobe is a look control: the specular attribute says how strong a highlight
|
|
171
187
|
* is and roughness how wide, apart. Physical, they are entangled as they are in a real surface —
|
|
172
188
|
* the peak is `1 / (4 α²)` of the light head-on, so a polished surface's highlight is many times
|
|
173
189
|
* the look's and a rough one's lower and broader — and the specular attribute is read as the
|
|
174
|
-
* reflectance at normal incidence, F0:
|
|
190
|
+
* reflectance at normal incidence, F0: `0.08 × Specular`, 0.04 at its default. Fresnel
|
|
175
191
|
* then brightens every surface toward grazing, not only a metal. A rectangle's highlight is the
|
|
176
192
|
* lobe integrated over it with the attribute as F0 already, so it is unchanged either way.
|
|
177
193
|
*
|
|
@@ -275,7 +291,16 @@ export declare class SurfaceTexture {
|
|
|
275
291
|
/** The per-layer effects table, or null for a texture given none. See `surfaceEffects.ts`. */
|
|
276
292
|
private effectsTable;
|
|
277
293
|
/** The block format a compressed texture holds, or null for one uploaded from images. */
|
|
278
|
-
private
|
|
294
|
+
private blockFormat;
|
|
295
|
+
/** How the texture is sampled, kept so blocks swapped in by `update` are sampled the same way. */
|
|
296
|
+
private readonly sampling;
|
|
297
|
+
/** Level 0's size, which `flatLayer` copies; kept as `update` changes it. */
|
|
298
|
+
private width;
|
|
299
|
+
private height;
|
|
300
|
+
/** The texture's storage format, which `flatLayer`'s copy matches so the copy converts nothing. */
|
|
301
|
+
private readonly storage;
|
|
302
|
+
/** Layer 0 as a plain 2D texture, made by `flatLayer` and dropped when the pixels change. */
|
|
303
|
+
private flat;
|
|
279
304
|
/**
|
|
280
305
|
* One image, or an array of images that must share one size (`layerSize` refuses otherwise).
|
|
281
306
|
* Uploaded unflipped either way; see the constructor body for why. Or blocks, uploaded as they are
|
|
@@ -296,7 +321,20 @@ export declare class SurfaceTexture {
|
|
|
296
321
|
* Not a hot path: it re-uploads the whole image and regenerates the chain. A caller
|
|
297
322
|
* doing this every frame at any size wants to know that it costs what it costs.
|
|
298
323
|
*/
|
|
299
|
-
update(gl: WebGL2RenderingContext, source: TexImageSource): void;
|
|
324
|
+
update(gl: WebGL2RenderingContext, source: TexImageSource | CompressedTextureSource, compressed?: readonly CompressedTextureFormat[]): void;
|
|
325
|
+
/**
|
|
326
|
+
* Blocks in place of the image, behind the same handle: **a new GL object** rather than the
|
|
327
|
+
* image's levels respecified, because a chain shorter than the image's would leave the levels
|
|
328
|
+
* past it allocated, and immutable storage could not be respecified at all. Sampled as the image
|
|
329
|
+
* was, and refused before anything changes where the context does not take the format.
|
|
330
|
+
*/
|
|
331
|
+
private swapToBlocks;
|
|
332
|
+
/**
|
|
333
|
+
* Wrap, filters and anisotropy on the bound texture. Nearest where the caller said their pixels
|
|
334
|
+
* are the subject; see `filter`. The mip chain is still blended between levels, because that is
|
|
335
|
+
* minification and this option is about magnification.
|
|
336
|
+
*/
|
|
337
|
+
private applySampling;
|
|
300
338
|
/**
|
|
301
339
|
* Attach the only layer as the bound framebuffer's colour: a scene capture's target, drawn into
|
|
302
340
|
* by `captureScene`. Engine-internal, as `bind` is.
|
|
@@ -304,5 +342,17 @@ export declare class SurfaceTexture {
|
|
|
304
342
|
attachColor(gl: WebGL2RenderingContext): void;
|
|
305
343
|
/** Bind to a unit for sampling. Engine-internal: the renderer owns unit assignment. */
|
|
306
344
|
bind(gl: WebGL2RenderingContext, unit: number): void;
|
|
345
|
+
/**
|
|
346
|
+
* Layer 0 as a plain 2D texture: what a `sampler2D` can be handed, which an array cannot. Copied
|
|
347
|
+
* the first time it is asked for, by a framebuffer blit into storage of the same format, and kept
|
|
348
|
+
* until `update` or `dispose`. Engine-internal: a surface overlay's atlas is bound where the
|
|
349
|
+
* lit stage's one 2D image slot is (`surfaceOverlay.ts`).
|
|
350
|
+
*
|
|
351
|
+
* **Null for blocks**, which no framebuffer can read; the caller says so. What it costs is a copy
|
|
352
|
+
* of level 0 in memory beside the array, and the bindings of both framebuffer targets, which are
|
|
353
|
+
* read back before the blit and put back after it — a sync query, paid once per image.
|
|
354
|
+
*/
|
|
355
|
+
flatLayer(gl: WebGL2RenderingContext): WebGLTexture | null;
|
|
356
|
+
private dropFlat;
|
|
307
357
|
dispose(gl: WebGL2RenderingContext): void;
|
|
308
358
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { layerSize, refuseArrayUpdate, sourceSize } from './textureSource.js';
|
|
2
|
-
import { compressedLayers, planBlocks, refuseBlockUpdate } from './compressedSource.js';
|
|
2
|
+
import { compressedLayers, isCompressedSource, planBlocks, refuseBlockUpdate, } from './compressedSource.js';
|
|
3
3
|
import { uploadCompressedArray } from './glCompressed.js';
|
|
4
4
|
import { SURFACE_EFFECT_TEXELS, packSurfaceEffects } from './surfaceEffects.js';
|
|
5
5
|
import { isLightmapTexels } from './lightmap.js';
|
|
@@ -25,6 +25,15 @@ export class SurfaceTexture {
|
|
|
25
25
|
effectsTable = null;
|
|
26
26
|
/** The block format a compressed texture holds, or null for one uploaded from images. */
|
|
27
27
|
blockFormat;
|
|
28
|
+
/** How the texture is sampled, kept so blocks swapped in by `update` are sampled the same way. */
|
|
29
|
+
sampling;
|
|
30
|
+
/** Level 0's size, which `flatLayer` copies; kept as `update` changes it. */
|
|
31
|
+
width = 0;
|
|
32
|
+
height = 0;
|
|
33
|
+
/** The texture's storage format, which `flatLayer`'s copy matches so the copy converts nothing. */
|
|
34
|
+
storage;
|
|
35
|
+
/** Layer 0 as a plain 2D texture, made by `flatLayer` and dropped when the pixels change. */
|
|
36
|
+
flat = null;
|
|
28
37
|
/**
|
|
29
38
|
* One image, or an array of images that must share one size (`layerSize` refuses otherwise).
|
|
30
39
|
* Uploaded unflipped either way; see the constructor body for why. Or blocks, uploaded as they are
|
|
@@ -51,6 +60,9 @@ export class SurfaceTexture {
|
|
|
51
60
|
this.layers = 1;
|
|
52
61
|
this.blockFormat = null;
|
|
53
62
|
this.mipmapped = false;
|
|
63
|
+
this.width = capture.width;
|
|
64
|
+
this.height = capture.height;
|
|
65
|
+
this.storage = capture.float ? gl.RGBA16F : gl.RGBA8;
|
|
54
66
|
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, capture.float ? gl.RGBA16F : gl.RGBA8, capture.width, capture.height, 1);
|
|
55
67
|
}
|
|
56
68
|
else if (baked !== null) {
|
|
@@ -58,6 +70,9 @@ export class SurfaceTexture {
|
|
|
58
70
|
this.layers = baked.layers.length;
|
|
59
71
|
this.blockFormat = null;
|
|
60
72
|
this.mipmapped = false;
|
|
73
|
+
this.width = baked.width;
|
|
74
|
+
this.height = baked.height;
|
|
75
|
+
this.storage = gl.RGBA8;
|
|
61
76
|
/* A typed array refuses either flag set, so both are put down here rather than assumed. */
|
|
62
77
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
63
78
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
@@ -73,6 +88,7 @@ export class SurfaceTexture {
|
|
|
73
88
|
`generateMipmap` cannot write a compressed format. */
|
|
74
89
|
this.layers = blocks.length;
|
|
75
90
|
this.blockFormat = blocks[0].format;
|
|
91
|
+
this.storage = gl.NONE;
|
|
76
92
|
this.mipmapped = (options.mipmap ?? true) && plan.levels > 1;
|
|
77
93
|
uploadCompressedArray(gl, plan.name, blocks, this.mipmapped ? plan.levels : 1);
|
|
78
94
|
}
|
|
@@ -81,25 +97,20 @@ export class SurfaceTexture {
|
|
|
81
97
|
this.layers = sources.length;
|
|
82
98
|
this.blockFormat = null;
|
|
83
99
|
this.mipmapped = options.mipmap ?? true;
|
|
100
|
+
const { width, height } = layerSize(sources);
|
|
101
|
+
this.width = width;
|
|
102
|
+
this.height = height;
|
|
103
|
+
this.storage = this.srgb ? gl.SRGB8_ALPHA8 : gl.RGBA8;
|
|
84
104
|
uploadImages(gl, sources, this.srgb);
|
|
85
105
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, nearest ? gl.NEAREST : gl.LINEAR);
|
|
93
|
-
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.mipmapped
|
|
94
|
-
? nearest
|
|
95
|
-
? gl.NEAREST_MIPMAP_LINEAR
|
|
96
|
-
: gl.LINEAR_MIPMAP_LINEAR
|
|
97
|
-
: nearest
|
|
98
|
-
? gl.NEAREST
|
|
99
|
-
: gl.LINEAR);
|
|
106
|
+
this.sampling = {
|
|
107
|
+
wrap,
|
|
108
|
+
nearest: options.filter === 'nearest',
|
|
109
|
+
anisotropy: options.anisotropy ?? DEFAULT_ANISOTROPY,
|
|
110
|
+
};
|
|
111
|
+
this.applySampling(gl);
|
|
100
112
|
if (this.mipmapped && this.blockFormat === null)
|
|
101
113
|
gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
|
|
102
|
-
applyAnisotropy(gl, options.anisotropy ?? DEFAULT_ANISOTROPY);
|
|
103
114
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
|
|
104
115
|
/* Half floats, nearest, clamped: a table read by texelFetch, whose every whole number is under
|
|
105
116
|
what a half holds exactly. */
|
|
@@ -137,12 +148,19 @@ export class SurfaceTexture {
|
|
|
137
148
|
* Not a hot path: it re-uploads the whole image and regenerates the chain. A caller
|
|
138
149
|
* doing this every frame at any size wants to know that it costs what it costs.
|
|
139
150
|
*/
|
|
140
|
-
update(gl, source) {
|
|
151
|
+
update(gl, source, compressed = []) {
|
|
141
152
|
if (this.texture === null)
|
|
142
153
|
return;
|
|
143
154
|
refuseArrayUpdate(this.layers);
|
|
155
|
+
if (isCompressedSource(source)) {
|
|
156
|
+
this.swapToBlocks(gl, source, compressed);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
144
159
|
refuseBlockUpdate(this.blockFormat);
|
|
145
160
|
const { width, height } = sourceSize(source);
|
|
161
|
+
this.width = width;
|
|
162
|
+
this.height = height;
|
|
163
|
+
this.dropFlat(gl);
|
|
146
164
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
|
|
147
165
|
/* Unflipped, matching the constructor. See it for why, and for what it cost. */
|
|
148
166
|
gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, this.srgb ? gl.SRGB8_ALPHA8 : gl.RGBA, width, height, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
@@ -150,6 +168,48 @@ export class SurfaceTexture {
|
|
|
150
168
|
gl.generateMipmap(gl.TEXTURE_2D_ARRAY);
|
|
151
169
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
|
|
152
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Blocks in place of the image, behind the same handle: **a new GL object** rather than the
|
|
173
|
+
* image's levels respecified, because a chain shorter than the image's would leave the levels
|
|
174
|
+
* past it allocated, and immutable storage could not be respecified at all. Sampled as the image
|
|
175
|
+
* was, and refused before anything changes where the context does not take the format.
|
|
176
|
+
*/
|
|
177
|
+
swapToBlocks(gl, source, compressed) {
|
|
178
|
+
const plan = planBlocks([source], this.srgb, compressed);
|
|
179
|
+
const texture = gl.createTexture();
|
|
180
|
+
if (texture === null)
|
|
181
|
+
throw new Error('SurfaceTexture: createTexture failed');
|
|
182
|
+
this.dropFlat(gl);
|
|
183
|
+
if (this.texture !== null)
|
|
184
|
+
gl.deleteTexture(this.texture);
|
|
185
|
+
this.texture = texture;
|
|
186
|
+
this.blockFormat = source.format;
|
|
187
|
+
this.width = source.width;
|
|
188
|
+
this.height = source.height;
|
|
189
|
+
gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture);
|
|
190
|
+
uploadCompressedArray(gl, plan.name, [source], this.mipmapped ? plan.levels : 1);
|
|
191
|
+
this.applySampling(gl);
|
|
192
|
+
gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Wrap, filters and anisotropy on the bound texture. Nearest where the caller said their pixels
|
|
196
|
+
* are the subject; see `filter`. The mip chain is still blended between levels, because that is
|
|
197
|
+
* minification and this option is about magnification.
|
|
198
|
+
*/
|
|
199
|
+
applySampling(gl) {
|
|
200
|
+
const { wrap, nearest, anisotropy } = this.sampling;
|
|
201
|
+
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, wrap);
|
|
202
|
+
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, wrap);
|
|
203
|
+
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, nearest ? gl.NEAREST : gl.LINEAR);
|
|
204
|
+
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, this.mipmapped
|
|
205
|
+
? nearest
|
|
206
|
+
? gl.NEAREST_MIPMAP_LINEAR
|
|
207
|
+
: gl.LINEAR_MIPMAP_LINEAR
|
|
208
|
+
: nearest
|
|
209
|
+
? gl.NEAREST
|
|
210
|
+
: gl.LINEAR);
|
|
211
|
+
applyAnisotropy(gl, anisotropy);
|
|
212
|
+
}
|
|
153
213
|
/**
|
|
154
214
|
* Attach the only layer as the bound framebuffer's colour: a scene capture's target, drawn into
|
|
155
215
|
* by `captureScene`. Engine-internal, as `bind` is.
|
|
@@ -162,9 +222,57 @@ export class SurfaceTexture {
|
|
|
162
222
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
163
223
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
|
|
164
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Layer 0 as a plain 2D texture: what a `sampler2D` can be handed, which an array cannot. Copied
|
|
227
|
+
* the first time it is asked for, by a framebuffer blit into storage of the same format, and kept
|
|
228
|
+
* until `update` or `dispose`. Engine-internal: a surface overlay's atlas is bound where the
|
|
229
|
+
* lit stage's one 2D image slot is (`surfaceOverlay.ts`).
|
|
230
|
+
*
|
|
231
|
+
* **Null for blocks**, which no framebuffer can read; the caller says so. What it costs is a copy
|
|
232
|
+
* of level 0 in memory beside the array, and the bindings of both framebuffer targets, which are
|
|
233
|
+
* read back before the blit and put back after it — a sync query, paid once per image.
|
|
234
|
+
*/
|
|
235
|
+
flatLayer(gl) {
|
|
236
|
+
if (this.texture === null || this.blockFormat !== null)
|
|
237
|
+
return null;
|
|
238
|
+
if (this.flat !== null)
|
|
239
|
+
return this.flat;
|
|
240
|
+
const flat = gl.createTexture();
|
|
241
|
+
const read = gl.createFramebuffer();
|
|
242
|
+
const draw = gl.createFramebuffer();
|
|
243
|
+
if (flat === null || read === null || draw === null)
|
|
244
|
+
return null;
|
|
245
|
+
gl.bindTexture(gl.TEXTURE_2D, flat);
|
|
246
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, this.storage, this.width, this.height);
|
|
247
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
248
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
249
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
250
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
251
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
252
|
+
const heldRead = gl.getParameter(gl.READ_FRAMEBUFFER_BINDING);
|
|
253
|
+
const heldDraw = gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING);
|
|
254
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, read);
|
|
255
|
+
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.texture, 0, 0);
|
|
256
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, draw);
|
|
257
|
+
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, flat, 0);
|
|
258
|
+
const [w, h] = [this.width, this.height];
|
|
259
|
+
gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);
|
|
260
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, heldRead);
|
|
261
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, heldDraw);
|
|
262
|
+
gl.deleteFramebuffer(read);
|
|
263
|
+
gl.deleteFramebuffer(draw);
|
|
264
|
+
this.flat = flat;
|
|
265
|
+
return flat;
|
|
266
|
+
}
|
|
267
|
+
dropFlat(gl) {
|
|
268
|
+
if (this.flat !== null)
|
|
269
|
+
gl.deleteTexture(this.flat);
|
|
270
|
+
this.flat = null;
|
|
271
|
+
}
|
|
165
272
|
dispose(gl) {
|
|
166
273
|
if (this.texture === null)
|
|
167
274
|
return;
|
|
275
|
+
this.dropFlat(gl);
|
|
168
276
|
gl.deleteTexture(this.texture);
|
|
169
277
|
this.texture = null;
|
|
170
278
|
if (this.effectsTable !== null)
|
|
@@ -248,12 +248,26 @@ export declare class TemporalHistory {
|
|
|
248
248
|
private picture;
|
|
249
249
|
private width;
|
|
250
250
|
private height;
|
|
251
|
+
/** Whether this frame of the renderer's has opened one of the sequence, and what it answered. */
|
|
252
|
+
private opened;
|
|
253
|
+
private answer;
|
|
254
|
+
/**
|
|
255
|
+
* A frame of the renderer's began: the next `openFrame` opens a frame of the sequence. Called at
|
|
256
|
+
* `beginFrame`, by both backends.
|
|
257
|
+
*/
|
|
258
|
+
nextFrame(): void;
|
|
251
259
|
/**
|
|
252
260
|
* Open a frame at this target size, and answer whether the history may be sampled.
|
|
253
261
|
*
|
|
254
262
|
* **The jitter advances whether or not it may be.** Holding the sequence still on the frames a
|
|
255
263
|
* resize or a cut discarded would sample the same position twice running, which is one sample
|
|
256
264
|
* and not two.
|
|
265
|
+
*
|
|
266
|
+
* **Once a frame, however many times it is asked.** A renderer asks where the scene's camera
|
|
267
|
+
* arrives, and a frame binds that camera again after a scene capture or anything else that bound
|
|
268
|
+
* another; each asking opened a frame of its own, so the sequence stepped twice in such a frame
|
|
269
|
+
* and the edges of the picture swam. Asked again, it gives the answer it gave. What it gives up:
|
|
270
|
+
* a size changed between two asks in one frame is seen at the next frame, not at once.
|
|
257
271
|
*/
|
|
258
272
|
openFrame(width: number, height: number): boolean;
|
|
259
273
|
/**
|
|
@@ -355,20 +355,40 @@ export class TemporalHistory {
|
|
|
355
355
|
picture = false;
|
|
356
356
|
width = 0;
|
|
357
357
|
height = 0;
|
|
358
|
+
/** Whether this frame of the renderer's has opened one of the sequence, and what it answered. */
|
|
359
|
+
opened = false;
|
|
360
|
+
answer = false;
|
|
361
|
+
/**
|
|
362
|
+
* A frame of the renderer's began: the next `openFrame` opens a frame of the sequence. Called at
|
|
363
|
+
* `beginFrame`, by both backends.
|
|
364
|
+
*/
|
|
365
|
+
nextFrame() {
|
|
366
|
+
this.opened = false;
|
|
367
|
+
}
|
|
358
368
|
/**
|
|
359
369
|
* Open a frame at this target size, and answer whether the history may be sampled.
|
|
360
370
|
*
|
|
361
371
|
* **The jitter advances whether or not it may be.** Holding the sequence still on the frames a
|
|
362
372
|
* resize or a cut discarded would sample the same position twice running, which is one sample
|
|
363
373
|
* and not two.
|
|
374
|
+
*
|
|
375
|
+
* **Once a frame, however many times it is asked.** A renderer asks where the scene's camera
|
|
376
|
+
* arrives, and a frame binds that camera again after a scene capture or anything else that bound
|
|
377
|
+
* another; each asking opened a frame of its own, so the sequence stepped twice in such a frame
|
|
378
|
+
* and the edges of the picture swam. Asked again, it gives the answer it gave. What it gives up:
|
|
379
|
+
* a size changed between two asks in one frame is seen at the next frame, not at once.
|
|
364
380
|
*/
|
|
365
381
|
openFrame(width, height) {
|
|
382
|
+
if (this.opened)
|
|
383
|
+
return this.answer;
|
|
384
|
+
this.opened = true;
|
|
366
385
|
this.frameIndex++;
|
|
367
386
|
const usable = this.picture && width === this.width && height === this.height;
|
|
368
387
|
if (!usable)
|
|
369
388
|
this.picture = false;
|
|
370
389
|
this.width = width;
|
|
371
390
|
this.height = height;
|
|
391
|
+
this.answer = usable;
|
|
372
392
|
return usable;
|
|
373
393
|
}
|
|
374
394
|
/**
|
|
@@ -38,6 +38,12 @@ export declare const ABSENT_ATTRIBUTE: Readonly<Record<string, readonly number[]
|
|
|
38
38
|
* value that produces a picture. `flat.ts` reads `0` as none, `1` as sRGB and `2` as ACES.
|
|
39
39
|
*/
|
|
40
40
|
export declare const OUTPUT_TRANSFORM_CODE: Readonly<Record<string, number>>;
|
|
41
|
+
/**
|
|
42
|
+
* The code a **forward** pass grades with: the transform's own, except `filmic`, which only the
|
|
43
|
+
* composite carries the constants for, and which a pass grading itself therefore draws as `aces`.
|
|
44
|
+
* Both backends' `gradeCode` read this, so neither can hand a forward stage a code it lacks.
|
|
45
|
+
*/
|
|
46
|
+
export declare function forwardTransformCode(transform: string): number;
|
|
41
47
|
/**
|
|
42
48
|
* How far the speed rush reaches, and how far a motion-blurred pixel may travel, both in UV.
|
|
43
49
|
*
|
|
@@ -46,3 +52,14 @@ export declare const OUTPUT_TRANSFORM_CODE: Readonly<Record<string, number>>;
|
|
|
46
52
|
*/
|
|
47
53
|
export declare const RUSH_REACH_UV = 0.012;
|
|
48
54
|
export declare const MOTION_BLUR_MAX_UV = 0.03;
|
|
55
|
+
/**
|
|
56
|
+
* A longest smear as `setCameraMotionBlur` takes it: a share of the frame, above zero and at most
|
|
57
|
+
* half, and the default where the number is not one. Shared, so both backends cap one way.
|
|
58
|
+
*/
|
|
59
|
+
export declare function clampMotionShare(share: number): number;
|
|
60
|
+
/**
|
|
61
|
+
* Said once where a draw names where it was last frame and the frame blurs by motion, but keeps no
|
|
62
|
+
* motion target to blur that draw by: each object's own motion is drawn only under a
|
|
63
|
+
* reconstruction on WebGPU, and anywhere else the camera's motion alone smears the frame.
|
|
64
|
+
*/
|
|
65
|
+
export declare const OBJECT_BLUR_UNKEPT: string;
|
|
@@ -110,7 +110,16 @@ export const OUTPUT_TRANSFORM_CODE = {
|
|
|
110
110
|
srgb: 1,
|
|
111
111
|
aces: 2,
|
|
112
112
|
shoulder: 3,
|
|
113
|
+
filmic: 4,
|
|
113
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* The code a **forward** pass grades with: the transform's own, except `filmic`, which only the
|
|
117
|
+
* composite carries the constants for, and which a pass grading itself therefore draws as `aces`.
|
|
118
|
+
* Both backends' `gradeCode` read this, so neither can hand a forward stage a code it lacks.
|
|
119
|
+
*/
|
|
120
|
+
export function forwardTransformCode(transform) {
|
|
121
|
+
return transform === 'filmic' ? 2 : (OUTPUT_TRANSFORM_CODE[transform] ?? 0);
|
|
122
|
+
}
|
|
114
123
|
/**
|
|
115
124
|
* How far the speed rush reaches, and how far a motion-blurred pixel may travel, both in UV.
|
|
116
125
|
*
|
|
@@ -119,3 +128,18 @@ export const OUTPUT_TRANSFORM_CODE = {
|
|
|
119
128
|
*/
|
|
120
129
|
export const RUSH_REACH_UV = 0.012;
|
|
121
130
|
export const MOTION_BLUR_MAX_UV = 0.03;
|
|
131
|
+
/**
|
|
132
|
+
* A longest smear as `setCameraMotionBlur` takes it: a share of the frame, above zero and at most
|
|
133
|
+
* half, and the default where the number is not one. Shared, so both backends cap one way.
|
|
134
|
+
*/
|
|
135
|
+
export function clampMotionShare(share) {
|
|
136
|
+
return Number.isFinite(share) && share > 0 ? Math.min(share, 0.5) : MOTION_BLUR_MAX_UV;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Said once where a draw names where it was last frame and the frame blurs by motion, but keeps no
|
|
140
|
+
* motion target to blur that draw by: each object's own motion is drawn only under a
|
|
141
|
+
* reconstruction on WebGPU, and anywhere else the camera's motion alone smears the frame.
|
|
142
|
+
*/
|
|
143
|
+
export const OBJECT_BLUR_UNKEPT = "[driftengine] motion blur follows each draw's own motion only under a reconstruction " +
|
|
144
|
+
"(DriftTR, WebGPU), which draws the motion target it reads; here the camera's motion alone " +
|
|
145
|
+
'blurs the frame, and a moving object is smeared only as the camera moved past it.';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftengine/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0",
|
|
4
4
|
"description": "The runtime of DriftEngine, a WebGPU game engine with a WebGL2 fallback: renderer, loop, input, cameras, scene graph and physics",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@driftengine/drft": "4.
|
|
33
|
-
"@driftengine/physics": "4.
|
|
32
|
+
"@driftengine/drft": "4.10.0",
|
|
33
|
+
"@driftengine/physics": "4.10.0",
|
|
34
34
|
"gl-matrix": "^3.4.3"
|
|
35
35
|
},
|
|
36
36
|
"author": "Drift Technologies",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"prepack": "node ../../scripts/build.mjs @driftengine/core"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@driftengine/nav": "4.
|
|
71
|
-
"@driftengine/network": "4.
|
|
72
|
-
"@driftengine/texture": "4.
|
|
70
|
+
"@driftengine/nav": "4.10.0",
|
|
71
|
+
"@driftengine/network": "4.10.0",
|
|
72
|
+
"@driftengine/texture": "4.10.0"
|
|
73
73
|
}
|
|
74
74
|
}
|
package/src/index.ts
CHANGED
|
@@ -454,6 +454,8 @@ export type { ReflectionOptions, ReflectiveSample } from './render/gi/reflection
|
|
|
454
454
|
*/
|
|
455
455
|
export { GRADE_PLACEHOLDER_SIZE, MAX_GRADE_SIZE, identityGradeLut } from './render/colourGrade.ts';
|
|
456
456
|
export type { ColourGradeLut } from './render/colourGrade.ts';
|
|
457
|
+
export { DEFAULT_FILMIC_CURVE } from './render/filmicCurve.ts';
|
|
458
|
+
export type { FilmicCurve } from './render/filmicCurve.ts';
|
|
457
459
|
/**
|
|
458
460
|
* How bloom answers past its threshold — a ramp in place of the subtraction, and a tint for each
|
|
459
461
|
* of the pyramid's `BLOOM_LEVELS` octaves — the third argument of `setBloom`.
|
|
@@ -513,6 +515,20 @@ export type {
|
|
|
513
515
|
SurfaceModel,
|
|
514
516
|
SurfaceModelKind,
|
|
515
517
|
} from './render/surfaceModel.ts';
|
|
518
|
+
/*
|
|
519
|
+
* What a draw lays over its surface beyond its material — a rim of light, a dissolve, wrinkle
|
|
520
|
+
* normals by region — set per draw with `setSurfaceOverlay`, its images regions of one atlas.
|
|
521
|
+
*/
|
|
522
|
+
/* Every opaque lit surface reflecting the frame by its own material: `screenSpaceReflections`. */
|
|
523
|
+
export { DEFAULT_FRAME_REFLECTIONS } from './render/frameReflections.ts';
|
|
524
|
+
export type { FrameReflections } from './render/frameReflections.ts';
|
|
525
|
+
export type {
|
|
526
|
+
OverlayRegion,
|
|
527
|
+
SurfaceDissolve,
|
|
528
|
+
SurfaceOverlay,
|
|
529
|
+
SurfaceRim,
|
|
530
|
+
SurfaceWrinkle,
|
|
531
|
+
} from './render/surfaceOverlay.ts';
|
|
516
532
|
/*
|
|
517
533
|
* A baked lightmap: the page a consumer decoded, which `createLightmap` uploads as a lightmapped
|
|
518
534
|
* material's `modelMap`, and the region of it a material or an instance reads.
|
|
@@ -552,6 +568,10 @@ export type {
|
|
|
552
568
|
ShadowCasterSink,
|
|
553
569
|
ShadowCasters,
|
|
554
570
|
} from './render/shadowCasters.ts';
|
|
571
|
+
/* What `createStaticDraws` hands back, so a consumer can hold one in a field it declares. */
|
|
572
|
+
export type { StaticDrawsHandle } from './render/staticDraws.ts';
|
|
573
|
+
/* A bone animation's clip as a caller hands it over, and the handle `createBoneAnimation` returns. */
|
|
574
|
+
export type { BoneAnimationClip, BoneAnimationHandle } from './render/boneAnimation.ts';
|
|
555
575
|
export type { Atmosphere, UnderwaterAtmosphere } from './render/atmosphere.ts';
|
|
556
576
|
/*
|
|
557
577
|
* Reading an image's texels back exactly, which no canvas and no `VideoFrame` will do.
|
|
@@ -644,12 +664,14 @@ export { MAX_CLUSTERED_LIGHTS } from './render/clusteredLights.ts';
|
|
|
644
664
|
export { SurfaceTexture } from './render/surfaceTexture.ts';
|
|
645
665
|
export type { SurfaceMaterial, SurfaceTextureOptions } from './render/surfaceTexture.ts';
|
|
646
666
|
/*
|
|
647
|
-
* BC
|
|
648
|
-
* ask before handing one over — whether this device takes its format
|
|
667
|
+
* Compressed textures — BC, ETC2 and EAC, ASTC: the source `createSurfaceTexture` takes as blocks,
|
|
668
|
+
* the one question to ask before handing one over — whether this device takes its format
|
|
669
|
+
* (`renderer.compressedFormats`) — and the bytes a level of it holds, for a reader checking a file.
|
|
649
670
|
*/
|
|
650
671
|
export {
|
|
651
672
|
compressedFormatName,
|
|
652
673
|
isCompressedSource,
|
|
674
|
+
levelBytes,
|
|
653
675
|
uploadsCompressed,
|
|
654
676
|
} from './render/compressedSource.ts';
|
|
655
677
|
export type {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* **Why a draw needs its own.** The engine's diffuse ambient is one answer for a whole frame — the
|
|
6
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 (
|
|
7
|
+
* lit alike. A stage with a baked volume of indirect light (a volumetric lightmap) lights a
|
|
8
8
|
* character by sampling that volume where the character stands; a consumer that samples it each
|
|
9
9
|
* frame hands the result here, around that character's draws, and the character takes the light of
|
|
10
10
|
* the spot it is in rather than the frame's average.
|
package/src/render/areaLights.ts
CHANGED
|
@@ -94,14 +94,14 @@ export interface AreaLightSource {
|
|
|
94
94
|
* others. **Read only where the rectangle is shaded through the froxel table** — the ones past
|
|
95
95
|
* `maxAreaLights` with `clusteredLights` on; the fixed four light everything they face, as they
|
|
96
96
|
* always have. Absent, it is where the rectangle's irradiance on its axis falls to a thousandth
|
|
97
|
-
* of a scene unit, and never inside the rectangle itself.
|
|
97
|
+
* of a scene unit, and never inside the rectangle itself. An attenuation radius, in metres.
|
|
98
98
|
*/
|
|
99
99
|
range?: number;
|
|
100
100
|
/**
|
|
101
101
|
* Barn doors: a flap hinged at each of the rectangle's four edges, standing this many degrees from
|
|
102
102
|
* its normal. 90, or absent, folds them flat and they hide nothing; smaller closes them, so the
|
|
103
103
|
* light narrows to the opening they leave — a rectangle at 50° throws a beam rather than filling
|
|
104
|
-
* its hemisphere.
|
|
104
|
+
* its hemisphere. 88° is the usual default, nearly flat.
|
|
105
105
|
*
|
|
106
106
|
* What a fragment sees past the doors is the part of the rectangle no door's tip hides, one axis
|
|
107
107
|
* at a time, and the rectangle then shades as that smaller rectangle, its highlight included.
|
|
@@ -111,7 +111,7 @@ export interface AreaLightSource {
|
|
|
111
111
|
* rectangle's back face has none.
|
|
112
112
|
*/
|
|
113
113
|
barnDoorAngle?: number;
|
|
114
|
-
/** The barn doors' length in metres. Absent, 0.2:
|
|
114
|
+
/** The barn doors' length in metres. Absent, 0.2: the usual default of 20 cm. */
|
|
115
115
|
barnDoorLength?: number;
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -150,7 +150,7 @@ export function createAreaLightBuffer(capacity: number = MAX_AREA_LIGHTS): AreaL
|
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
/**
|
|
153
|
+
/** The usual default barn door length, in metres. See `AreaLightSource.barnDoorLength`. */
|
|
154
154
|
export const DEFAULT_BARN_DOOR_LENGTH = 0.2;
|
|
155
155
|
|
|
156
156
|
/**
|
package/src/render/atmosphere.ts
CHANGED
|
@@ -47,6 +47,19 @@ export interface Atmosphere {
|
|
|
47
47
|
/** Linear mode only: where haze begins, and where it is total. */
|
|
48
48
|
fogNear?: number;
|
|
49
49
|
fogFar?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The medium only: how far along the view ray it begins, in metres. Absent or 0 is at the
|
|
52
|
+
* camera, as every world before it was drawn.
|
|
53
|
+
*
|
|
54
|
+
* The air nearer than this is perfectly clear, and what lies beyond is fogged by the air past
|
|
55
|
+
* this point alone — so a faint, bright haze can lie over a distant crowd while the figures a
|
|
56
|
+
* few metres from the camera stay sharp, which no density can do when the medium starts at the
|
|
57
|
+
* eye: there it veils the whole frame, lifting the shadows and draining the colour before it
|
|
58
|
+
* reaches anything far enough to want it. Unlike `linear`'s `fogNear`, nothing past it is a
|
|
59
|
+
* ramp: it is the same extinction, integrated from further out. **What it gives up** is the air
|
|
60
|
+
* between the camera and the start, which a real medium has; that is the point of it.
|
|
61
|
+
*/
|
|
62
|
+
fogStart?: number;
|
|
50
63
|
underwater: UnderwaterAtmosphere | null;
|
|
51
64
|
}
|
|
52
65
|
|
|
@@ -132,7 +145,15 @@ export function resolveAtmosphere(
|
|
|
132
145
|
out.fogHeightFalloff = atmosphere.fogHeightFalloff;
|
|
133
146
|
out.fogEyeY = cameraY;
|
|
134
147
|
out.fogMode = atmosphere.fogMode === 'linear' ? 1 : 0;
|
|
135
|
-
|
|
148
|
+
/*
|
|
149
|
+
* **One slot, two meanings, and never both**: the ramp's near distance in linear mode, and in
|
|
150
|
+
* the medium where it begins (`fogStart`), which the medium never read before — so a world that
|
|
151
|
+
* left a `fogNear` on an exponential fog starts nothing, and draws exactly as it did.
|
|
152
|
+
*/
|
|
153
|
+
out.fogNear =
|
|
154
|
+
atmosphere.fogMode === 'linear'
|
|
155
|
+
? (atmosphere.fogNear ?? 0)
|
|
156
|
+
: Math.max(0, Number.isFinite(atmosphere.fogStart) ? (atmosphere.fogStart ?? 0) : 0);
|
|
136
157
|
out.fogFar = atmosphere.fogFar ?? 1;
|
|
137
158
|
/*
|
|
138
159
|
* The air medium stands in when nothing is submerged. The shaders multiply by the factor
|