@driftengine/core 4.8.6 → 4.9.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 +132 -0
- package/README.md +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +8 -1
- package/dist/render/anisotropicLobe.d.ts +10 -0
- package/dist/render/anisotropicLobe.js +19 -0
- package/dist/render/areaLights.d.ts +35 -0
- package/dist/render/areaLights.js +35 -0
- package/dist/render/atmosphere.d.ts +13 -0
- package/dist/render/atmosphere.js +9 -1
- package/dist/render/backend/api.d.ts +41 -3
- package/dist/render/backend/createRenderer.d.ts +6 -0
- package/dist/render/backend/createRenderer.js +4 -1
- package/dist/render/backend/webgl2/renderer.d.ts +140 -16
- package/dist/render/backend/webgl2/renderer.js +436 -44
- package/dist/render/backend/webgl2/sceneCaptureTarget.d.ts +29 -0
- package/dist/render/backend/webgl2/sceneCaptureTarget.js +96 -0
- package/dist/render/backend/webgpu/device.d.ts +7 -1
- package/dist/render/backend/webgpu/device.js +31 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +16 -1
- package/dist/render/backend/webgpu/flatPass.js +58 -26
- package/dist/render/backend/webgpu/particlePass.js +2 -1
- 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 +166 -3
- package/dist/render/backend/webgpu/renderer.js +738 -83
- 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/surfaceTexturePass.d.ts +4 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.js +34 -8
- package/dist/render/backend/webgpu/waterPass.d.ts +1 -1
- package/dist/render/clusteredLights.d.ts +23 -5
- package/dist/render/clusteredLights.js +35 -8
- package/dist/render/displayRange.d.ts +31 -0
- package/dist/render/displayRange.js +47 -0
- 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/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/gi/bounceLights.d.ts +3 -2
- package/dist/render/gi/bounceLights.js +8 -3
- package/dist/render/instanceCull.js +5 -0
- package/dist/render/instances.d.ts +19 -5
- package/dist/render/instances.js +9 -3
- package/dist/render/lightBudget.d.ts +12 -1
- package/dist/render/lightBudget.js +23 -3
- package/dist/render/lightmap.d.ts +23 -9
- package/dist/render/lightmap.js +40 -18
- package/dist/render/particlePool.d.ts +21 -0
- package/dist/render/particlePool.js +7 -0
- package/dist/render/pass.d.ts +49 -0
- package/dist/render/pointLightSelection.d.ts +13 -0
- package/dist/render/pointLightSelection.js +3 -1
- package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
- package/dist/render/reflectionSurfaceTargets.js +99 -0
- package/dist/render/renderQuality.d.ts +47 -15
- package/dist/render/renderQuality.js +4 -0
- 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 +24 -1
- package/dist/render/screenSpaceReflection.d.ts +32 -1
- package/dist/render/screenSpaceReflection.js +14 -0
- package/dist/render/shaders/arcane.d.ts +1 -1
- package/dist/render/shaders/bolt.d.ts +1 -1
- package/dist/render/shaders/bolt.js +7 -1
- package/dist/render/shaders/caustics.d.ts +1 -1
- package/dist/render/shaders/depth.js +11 -0
- 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/anisotropic.d.ts +1 -1
- package/dist/render/shaders/flat/anisotropic.js +37 -3
- package/dist/render/shaders/flat/areaLight.d.ts +1 -1
- package/dist/render/shaders/flat/areaLight.js +46 -0
- package/dist/render/shaders/flat/glassTint.d.ts +3 -2
- package/dist/render/shaders/flat/glassTint.js +5 -1
- package/dist/render/shaders/flat/index.d.ts +15 -0
- package/dist/render/shaders/flat/index.js +22 -2
- 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 +85 -22
- package/dist/render/shaders/flat/models.d.ts +5 -2
- package/dist/render/shaders/flat/models.js +100 -16
- 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 +1 -1
- package/dist/render/shaders/flat/preamble.js +10 -3
- 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 +4 -4
- package/dist/render/shaders/generated/depth.wgsl.js +4 -4
- 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 +192 -16
- package/dist/render/shaders/generated/flat.wgsl.js +230 -54
- 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 +32 -7
- package/dist/render/shaders/generated/ssrTrace.wgsl.js +32 -7
- 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/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/particle.d.ts +3 -3
- 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/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 +46 -1
- package/dist/render/shaders/water.d.ts +1 -1
- package/dist/render/shaders/water.js +12 -3
- package/dist/render/skinScatter.d.ts +3 -1
- package/dist/render/skinScatter.js +3 -1
- package/dist/render/ssrPass.d.ts +16 -0
- package/dist/render/ssrPass.js +107 -1
- package/dist/render/surfaceModel.d.ts +29 -8
- package/dist/render/surfaceModel.js +33 -9
- package/dist/render/surfaceOverlay.d.ts +132 -0
- package/dist/render/surfaceOverlay.js +85 -0
- package/dist/render/surfaceTexture.d.ts +44 -1
- package/dist/render/surfaceTexture.js +96 -5
- 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 +22 -2
- package/src/render/anisotropicLobe.ts +29 -0
- package/src/render/areaLights.ts +58 -0
- package/src/render/atmosphere.ts +22 -1
- package/src/render/backend/api.ts +58 -2
- package/src/render/backend/createRenderer.ts +18 -1
- package/src/render/backend/webgl2/renderer.ts +548 -50
- package/src/render/backend/webgl2/sceneCaptureTarget.ts +130 -0
- package/src/render/backend/webgpu/device.ts +42 -3
- package/src/render/backend/webgpu/flatPass.ts +63 -26
- package/src/render/backend/webgpu/particlePass.ts +2 -1
- 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 +927 -100
- package/src/render/backend/webgpu/sceneCaptureTarget.ts +63 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +44 -14
- package/src/render/clusteredLights.ts +41 -8
- package/src/render/displayRange.ts +61 -0
- package/src/render/driftLight/bake.ts +3 -1
- package/src/render/driftLight/falloff.ts +13 -2
- 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/gi/bounceLights.ts +12 -3
- package/src/render/instanceCull.ts +4 -0
- package/src/render/instances.ts +26 -6
- package/src/render/lightBudget.ts +40 -2
- package/src/render/lightmap.ts +64 -23
- package/src/render/particlePool.ts +23 -0
- package/src/render/pass.ts +53 -1
- package/src/render/pointLightSelection.ts +20 -1
- package/src/render/reflectionSurfaceTargets.ts +105 -0
- package/src/render/renderQuality.ts +52 -15
- 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 +30 -2
- package/src/render/screenSpaceReflection.ts +38 -1
- package/src/render/shaders/bolt.ts +7 -1
- package/src/render/shaders/depth.ts +11 -0
- package/src/render/shaders/filmLook.ts +2 -1
- package/src/render/shaders/flat/anisotropic.ts +37 -3
- package/src/render/shaders/flat/areaLight.ts +46 -0
- package/src/render/shaders/flat/glassTint.ts +13 -2
- package/src/render/shaders/flat/index.ts +37 -2
- package/src/render/shaders/flat/lobes.ts +50 -43
- package/src/render/shaders/flat/main.ts +85 -22
- package/src/render/shaders/flat/models.ts +100 -16
- package/src/render/shaders/flat/overlay.ts +117 -0
- package/src/render/shaders/flat/pointShadow.ts +1 -1
- package/src/render/shaders/flat/preamble.ts +10 -3
- 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 +4 -4
- 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 +230 -54
- 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 +32 -7
- package/src/render/shaders/generated/water.wgsl.ts +23 -16
- package/src/render/shaders/gi/probeBake.wgsl.ts +9 -5
- package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
- package/src/render/shaders/recon/motion.wgsl.ts +13 -2
- package/src/render/shaders/rush.ts +54 -11
- package/src/render/shaders/ssrResolve.ts +52 -0
- package/src/render/shaders/ssrTrace.ts +46 -1
- package/src/render/shaders/water.ts +12 -3
- package/src/render/skinScatter.ts +3 -1
- package/src/render/ssrPass.ts +139 -1
- package/src/render/surfaceModel.ts +47 -10
- package/src/render/surfaceOverlay.ts +195 -0
- package/src/render/surfaceTexture.ts +136 -9
- package/src/render/temporalAa.ts +20 -0
- package/src/render/vertexDefaults.ts +28 -0
|
@@ -23,6 +23,8 @@ import type { SurfaceLayerEffect } from './surfaceEffects.ts';
|
|
|
23
23
|
import type { CutoutMode } from './cutoutDither.ts';
|
|
24
24
|
import { isLightmapTexels } from './lightmap.ts';
|
|
25
25
|
import type { LightmapTexels } from './lightmap.ts';
|
|
26
|
+
import { isSceneCaptureTexels } from './sceneCapture.ts';
|
|
27
|
+
import type { SceneCaptureTexels } from './sceneCapture.ts';
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* How a texture behaves past its edges and between its texels.
|
|
@@ -172,6 +174,24 @@ export interface SurfaceMaterial<Texture = SurfaceTexture> {
|
|
|
172
174
|
* that is not a colour.
|
|
173
175
|
*/
|
|
174
176
|
modelMap?: Texture | null;
|
|
177
|
+
/**
|
|
178
|
+
* Whether a lamp's and the sun's highlight on this surface is GGX's own, `π · D · Vis · F · N·L`,
|
|
179
|
+
* as Unreal and this engine's skin and eye shade it, rather than the engine's lobe scaled to a
|
|
180
|
+
* peak of one. **False by default**, every surface as it was.
|
|
181
|
+
*
|
|
182
|
+
* The peak-normalised lobe is a look control: the specular attribute says how strong a highlight
|
|
183
|
+
* is and roughness how wide, apart. Physical, they are entangled as they are in a real surface —
|
|
184
|
+
* the peak is `1 / (4 α²)` of the light head-on, so a polished surface's highlight is many times
|
|
185
|
+
* the look's and a rough one's lower and broader — and the specular attribute is read as the
|
|
186
|
+
* reflectance at normal incidence, F0: Unreal's `0.08 × Specular`, 0.04 at its default. Fresnel
|
|
187
|
+
* then brightens every surface toward grazing, not only a metal. A rectangle's highlight is the
|
|
188
|
+
* lobe integrated over it with the attribute as F0 already, so it is unchanged either way.
|
|
189
|
+
*
|
|
190
|
+
* On the standard, lightmap and anisotropic models. Skin and the eye are physical already; hair
|
|
191
|
+
* keeps its own three lobes. **What it gives up**: the look's independence of strength and width,
|
|
192
|
+
* and an 8-bit frame clips the brighter peak without `hdrScene`.
|
|
193
|
+
*/
|
|
194
|
+
physicalSpecular?: boolean;
|
|
175
195
|
}
|
|
176
196
|
|
|
177
197
|
export interface SurfaceTextureOptions {
|
|
@@ -273,6 +293,13 @@ export class SurfaceTexture {
|
|
|
273
293
|
private effectsTable: WebGLTexture | null = null;
|
|
274
294
|
/** The block format a compressed texture holds, or null for one uploaded from images. */
|
|
275
295
|
private readonly blockFormat: BlockFormat | null;
|
|
296
|
+
/** Level 0's size, which `flatLayer` copies; kept as `update` changes it. */
|
|
297
|
+
private width = 0;
|
|
298
|
+
private height = 0;
|
|
299
|
+
/** The texture's storage format, which `flatLayer`'s copy matches so the copy converts nothing. */
|
|
300
|
+
private readonly storage: number;
|
|
301
|
+
/** Layer 0 as a plain 2D texture, made by `flatLayer` and dropped when the pixels change. */
|
|
302
|
+
private flat: WebGLTexture | null = null;
|
|
276
303
|
|
|
277
304
|
/**
|
|
278
305
|
* One image, or an array of images that must share one size (`layerSize` refuses otherwise).
|
|
@@ -281,14 +308,16 @@ export class SurfaceTexture {
|
|
|
281
308
|
*/
|
|
282
309
|
constructor(
|
|
283
310
|
gl: WebGL2RenderingContext,
|
|
284
|
-
source: SurfaceSource | readonly SurfaceSource[] | LightmapTexels,
|
|
311
|
+
source: SurfaceSource | readonly SurfaceSource[] | LightmapTexels | SceneCaptureTexels,
|
|
285
312
|
options: SurfaceTextureOptions = {},
|
|
286
313
|
compressed: readonly CompressedTextureFormat[] = [],
|
|
287
314
|
) {
|
|
288
|
-
/* A
|
|
315
|
+
/* A scene capture's target: one empty layer the renderer draws into. See `sceneCapture.ts`. */
|
|
316
|
+
const capture = isSceneCaptureTexels(source) ? source : null;
|
|
317
|
+
/* A lightmap's page: two layers of bytes, uploaded as they are. See `lightmap.ts`. */
|
|
289
318
|
const baked = isLightmapTexels(source) ? source : null;
|
|
290
319
|
const listed = (
|
|
291
|
-
baked !== null ? [] : Array.isArray(source) ? source : [source]
|
|
320
|
+
baked !== null || capture !== null ? [] : Array.isArray(source) ? source : [source]
|
|
292
321
|
) as readonly SurfaceSource[];
|
|
293
322
|
const blocks = compressedLayers(listed);
|
|
294
323
|
this.srgb = (options.colorSpace ?? 'linear') === 'srgb';
|
|
@@ -300,31 +329,68 @@ export class SurfaceTexture {
|
|
|
300
329
|
const wrap = (options.wrap ?? 'repeat') === 'repeat' ? gl.REPEAT : gl.CLAMP_TO_EDGE;
|
|
301
330
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, texture);
|
|
302
331
|
|
|
303
|
-
if (
|
|
332
|
+
if (capture !== null) {
|
|
333
|
+
/* Immutable storage, one level: a framebuffer attachment, and radiance read linear. */
|
|
334
|
+
this.layers = 1;
|
|
335
|
+
this.blockFormat = null;
|
|
336
|
+
this.mipmapped = false;
|
|
337
|
+
this.width = capture.width;
|
|
338
|
+
this.height = capture.height;
|
|
339
|
+
this.storage = capture.float ? gl.RGBA16F : gl.RGBA8;
|
|
340
|
+
gl.texStorage3D(
|
|
341
|
+
gl.TEXTURE_2D_ARRAY,
|
|
342
|
+
1,
|
|
343
|
+
capture.float ? gl.RGBA16F : gl.RGBA8,
|
|
344
|
+
capture.width,
|
|
345
|
+
capture.height,
|
|
346
|
+
1,
|
|
347
|
+
);
|
|
348
|
+
} else if (baked !== null) {
|
|
304
349
|
/* No chain: a page is read at its own resolution, and a level of it would blend regions. */
|
|
305
|
-
this.layers = baked.layers;
|
|
350
|
+
this.layers = baked.layers.length;
|
|
306
351
|
this.blockFormat = null;
|
|
307
352
|
this.mipmapped = false;
|
|
353
|
+
this.width = baked.width;
|
|
354
|
+
this.height = baked.height;
|
|
355
|
+
this.storage = gl.RGBA8;
|
|
308
356
|
/* A typed array refuses either flag set, so both are put down here rather than assumed. */
|
|
309
357
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
310
358
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
359
|
+
/* Bytes, and read by `texelFetch` alone: the shader decodes and filters. See `lightmap.ts`. */
|
|
311
360
|
gl.texImage3D(
|
|
312
361
|
gl.TEXTURE_2D_ARRAY,
|
|
313
362
|
0,
|
|
314
|
-
gl.
|
|
363
|
+
gl.RGBA8,
|
|
315
364
|
baked.width,
|
|
316
365
|
baked.height,
|
|
317
|
-
|
|
366
|
+
this.layers,
|
|
318
367
|
0,
|
|
319
368
|
gl.RGBA,
|
|
320
|
-
gl.
|
|
321
|
-
|
|
369
|
+
gl.UNSIGNED_BYTE,
|
|
370
|
+
null,
|
|
322
371
|
);
|
|
372
|
+
/* A layer at a time, so a page's arrays are uploaded where they lie rather than joined. */
|
|
373
|
+
for (let layer = 0; layer < this.layers; layer++) {
|
|
374
|
+
gl.texSubImage3D(
|
|
375
|
+
gl.TEXTURE_2D_ARRAY,
|
|
376
|
+
0,
|
|
377
|
+
0,
|
|
378
|
+
0,
|
|
379
|
+
layer,
|
|
380
|
+
baked.width,
|
|
381
|
+
baked.height,
|
|
382
|
+
1,
|
|
383
|
+
gl.RGBA,
|
|
384
|
+
gl.UNSIGNED_BYTE,
|
|
385
|
+
baked.layers[layer] as Uint8Array,
|
|
386
|
+
);
|
|
387
|
+
}
|
|
323
388
|
} else if (blocks !== null && plan !== null) {
|
|
324
389
|
/* The stored chain, or level 0 alone where no chain was asked for. Nothing is generated:
|
|
325
390
|
`generateMipmap` cannot write a compressed format. */
|
|
326
391
|
this.layers = blocks.length;
|
|
327
392
|
this.blockFormat = (blocks[0] as CompressedTextureSource).format;
|
|
393
|
+
this.storage = gl.NONE;
|
|
328
394
|
this.mipmapped = (options.mipmap ?? true) && plan.levels > 1;
|
|
329
395
|
uploadCompressedArray(gl, plan.name, blocks, this.mipmapped ? plan.levels : 1);
|
|
330
396
|
} else {
|
|
@@ -332,6 +398,10 @@ export class SurfaceTexture {
|
|
|
332
398
|
this.layers = sources.length;
|
|
333
399
|
this.blockFormat = null;
|
|
334
400
|
this.mipmapped = options.mipmap ?? true;
|
|
401
|
+
const { width, height } = layerSize(sources);
|
|
402
|
+
this.width = width;
|
|
403
|
+
this.height = height;
|
|
404
|
+
this.storage = this.srgb ? gl.SRGB8_ALPHA8 : gl.RGBA8;
|
|
335
405
|
uploadImages(gl, sources, this.srgb);
|
|
336
406
|
}
|
|
337
407
|
gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, wrap);
|
|
@@ -410,6 +480,9 @@ export class SurfaceTexture {
|
|
|
410
480
|
refuseArrayUpdate(this.layers);
|
|
411
481
|
refuseBlockUpdate(this.blockFormat);
|
|
412
482
|
const { width, height } = sourceSize(source);
|
|
483
|
+
this.width = width;
|
|
484
|
+
this.height = height;
|
|
485
|
+
this.dropFlat(gl);
|
|
413
486
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
|
|
414
487
|
/* Unflipped, matching the constructor. See it for why, and for what it cost. */
|
|
415
488
|
gl.texImage3D(
|
|
@@ -428,14 +501,68 @@ export class SurfaceTexture {
|
|
|
428
501
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
|
|
429
502
|
}
|
|
430
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Attach the only layer as the bound framebuffer's colour: a scene capture's target, drawn into
|
|
506
|
+
* by `captureScene`. Engine-internal, as `bind` is.
|
|
507
|
+
*/
|
|
508
|
+
attachColor(gl: WebGL2RenderingContext): void {
|
|
509
|
+
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.texture, 0, 0);
|
|
510
|
+
}
|
|
511
|
+
|
|
431
512
|
/** Bind to a unit for sampling. Engine-internal: the renderer owns unit assignment. */
|
|
432
513
|
bind(gl: WebGL2RenderingContext, unit: number): void {
|
|
433
514
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
434
515
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture);
|
|
435
516
|
}
|
|
436
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Layer 0 as a plain 2D texture: what a `sampler2D` can be handed, which an array cannot. Copied
|
|
520
|
+
* the first time it is asked for, by a framebuffer blit into storage of the same format, and kept
|
|
521
|
+
* until `update` or `dispose`. Engine-internal: a surface overlay's atlas is bound where the
|
|
522
|
+
* lit stage's one 2D image slot is (`surfaceOverlay.ts`).
|
|
523
|
+
*
|
|
524
|
+
* **Null for blocks**, which no framebuffer can read; the caller says so. What it costs is a copy
|
|
525
|
+
* of level 0 in memory beside the array, and the bindings of both framebuffer targets, which are
|
|
526
|
+
* read back before the blit and put back after it — a sync query, paid once per image.
|
|
527
|
+
*/
|
|
528
|
+
flatLayer(gl: WebGL2RenderingContext): WebGLTexture | null {
|
|
529
|
+
if (this.texture === null || this.blockFormat !== null) return null;
|
|
530
|
+
if (this.flat !== null) return this.flat;
|
|
531
|
+
const flat = gl.createTexture();
|
|
532
|
+
const read = gl.createFramebuffer();
|
|
533
|
+
const draw = gl.createFramebuffer();
|
|
534
|
+
if (flat === null || read === null || draw === null) return null;
|
|
535
|
+
gl.bindTexture(gl.TEXTURE_2D, flat);
|
|
536
|
+
gl.texStorage2D(gl.TEXTURE_2D, 1, this.storage, this.width, this.height);
|
|
537
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
538
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
539
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
540
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
541
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
542
|
+
const heldRead = gl.getParameter(gl.READ_FRAMEBUFFER_BINDING) as WebGLFramebuffer | null;
|
|
543
|
+
const heldDraw = gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING) as WebGLFramebuffer | null;
|
|
544
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, read);
|
|
545
|
+
gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, this.texture, 0, 0);
|
|
546
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, draw);
|
|
547
|
+
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, flat, 0);
|
|
548
|
+
const [w, h] = [this.width, this.height];
|
|
549
|
+
gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);
|
|
550
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, heldRead);
|
|
551
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, heldDraw);
|
|
552
|
+
gl.deleteFramebuffer(read);
|
|
553
|
+
gl.deleteFramebuffer(draw);
|
|
554
|
+
this.flat = flat;
|
|
555
|
+
return flat;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private dropFlat(gl: WebGL2RenderingContext): void {
|
|
559
|
+
if (this.flat !== null) gl.deleteTexture(this.flat);
|
|
560
|
+
this.flat = null;
|
|
561
|
+
}
|
|
562
|
+
|
|
437
563
|
dispose(gl: WebGL2RenderingContext): void {
|
|
438
564
|
if (this.texture === null) return;
|
|
565
|
+
this.dropFlat(gl);
|
|
439
566
|
gl.deleteTexture(this.texture);
|
|
440
567
|
this.texture = null;
|
|
441
568
|
if (this.effectsTable !== null) gl.deleteTexture(this.effectsTable);
|
package/src/render/temporalAa.ts
CHANGED
|
@@ -451,6 +451,17 @@ export class TemporalHistory {
|
|
|
451
451
|
private picture = false;
|
|
452
452
|
private width = 0;
|
|
453
453
|
private height = 0;
|
|
454
|
+
/** Whether this frame of the renderer's has opened one of the sequence, and what it answered. */
|
|
455
|
+
private opened = false;
|
|
456
|
+
private answer = false;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* A frame of the renderer's began: the next `openFrame` opens a frame of the sequence. Called at
|
|
460
|
+
* `beginFrame`, by both backends.
|
|
461
|
+
*/
|
|
462
|
+
nextFrame(): void {
|
|
463
|
+
this.opened = false;
|
|
464
|
+
}
|
|
454
465
|
|
|
455
466
|
/**
|
|
456
467
|
* Open a frame at this target size, and answer whether the history may be sampled.
|
|
@@ -458,13 +469,22 @@ export class TemporalHistory {
|
|
|
458
469
|
* **The jitter advances whether or not it may be.** Holding the sequence still on the frames a
|
|
459
470
|
* resize or a cut discarded would sample the same position twice running, which is one sample
|
|
460
471
|
* and not two.
|
|
472
|
+
*
|
|
473
|
+
* **Once a frame, however many times it is asked.** A renderer asks where the scene's camera
|
|
474
|
+
* arrives, and a frame binds that camera again after a scene capture or anything else that bound
|
|
475
|
+
* another; each asking opened a frame of its own, so the sequence stepped twice in such a frame
|
|
476
|
+
* and the edges of the picture swam. Asked again, it gives the answer it gave. What it gives up:
|
|
477
|
+
* a size changed between two asks in one frame is seen at the next frame, not at once.
|
|
461
478
|
*/
|
|
462
479
|
openFrame(width: number, height: number): boolean {
|
|
480
|
+
if (this.opened) return this.answer;
|
|
481
|
+
this.opened = true;
|
|
463
482
|
this.frameIndex++;
|
|
464
483
|
const usable = this.picture && width === this.width && height === this.height;
|
|
465
484
|
if (!usable) this.picture = false;
|
|
466
485
|
this.width = width;
|
|
467
486
|
this.height = height;
|
|
487
|
+
this.answer = usable;
|
|
468
488
|
return usable;
|
|
469
489
|
}
|
|
470
490
|
|
|
@@ -113,8 +113,18 @@ export const OUTPUT_TRANSFORM_CODE: Readonly<Record<string, number>> = {
|
|
|
113
113
|
srgb: 1,
|
|
114
114
|
aces: 2,
|
|
115
115
|
shoulder: 3,
|
|
116
|
+
filmic: 4,
|
|
116
117
|
};
|
|
117
118
|
|
|
119
|
+
/**
|
|
120
|
+
* The code a **forward** pass grades with: the transform's own, except `filmic`, which only the
|
|
121
|
+
* composite carries the constants for, and which a pass grading itself therefore draws as `aces`.
|
|
122
|
+
* Both backends' `gradeCode` read this, so neither can hand a forward stage a code it lacks.
|
|
123
|
+
*/
|
|
124
|
+
export function forwardTransformCode(transform: string): number {
|
|
125
|
+
return transform === 'filmic' ? 2 : (OUTPUT_TRANSFORM_CODE[transform] ?? 0);
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
/**
|
|
119
129
|
* How far the speed rush reaches, and how far a motion-blurred pixel may travel, both in UV.
|
|
120
130
|
*
|
|
@@ -123,3 +133,21 @@ export const OUTPUT_TRANSFORM_CODE: Readonly<Record<string, number>> = {
|
|
|
123
133
|
*/
|
|
124
134
|
export const RUSH_REACH_UV = 0.012;
|
|
125
135
|
export const MOTION_BLUR_MAX_UV = 0.03;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A longest smear as `setCameraMotionBlur` takes it: a share of the frame, above zero and at most
|
|
139
|
+
* half, and the default where the number is not one. Shared, so both backends cap one way.
|
|
140
|
+
*/
|
|
141
|
+
export function clampMotionShare(share: number): number {
|
|
142
|
+
return Number.isFinite(share) && share > 0 ? Math.min(share, 0.5) : MOTION_BLUR_MAX_UV;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Said once where a draw names where it was last frame and the frame blurs by motion, but keeps no
|
|
147
|
+
* motion target to blur that draw by: each object's own motion is drawn only under a
|
|
148
|
+
* reconstruction on WebGPU, and anywhere else the camera's motion alone smears the frame.
|
|
149
|
+
*/
|
|
150
|
+
export const OBJECT_BLUR_UNKEPT =
|
|
151
|
+
"[driftengine] motion blur follows each draw's own motion only under a reconstruction " +
|
|
152
|
+
"(DriftTR, WebGPU), which draws the motion target it reads; here the camera's motion alone " +
|
|
153
|
+
'blurs the frame, and a moving object is smeared only as the camera moved past it.';
|