@driftengine/core 4.11.0 → 4.12.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 +72 -0
- package/README.md +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/render/ambientOcclusionPass.d.ts +3 -2
- package/dist/render/ambientOcclusionPass.js +4 -2
- package/dist/render/backend/api.d.ts +21 -1
- package/dist/render/backend/webgl2/renderer.d.ts +61 -5
- package/dist/render/backend/webgl2/renderer.js +153 -21
- package/dist/render/backend/webgpu/renderer.d.ts +54 -1
- package/dist/render/backend/webgpu/renderer.js +246 -89
- package/dist/render/instances.d.ts +13 -1
- package/dist/render/instances.js +10 -0
- package/dist/render/occlusionFade.d.ts +21 -0
- package/dist/render/occlusionFade.js +27 -0
- package/dist/render/sceneTarget.d.ts +2 -0
- package/dist/render/sceneTarget.js +1 -1
- package/dist/render/shaders/ambientOcclusion.js +12 -1
- package/dist/render/shaders/flat/areaLight.d.ts +1 -1
- package/dist/render/shaders/flat/areaLight.js +1 -1
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +1 -0
- package/dist/render/shaders/flat/index.d.ts +5 -0
- package/dist/render/shaders/flat/index.js +10 -3
- package/dist/render/shaders/flat/layerLooks.d.ts +16 -0
- package/dist/render/shaders/flat/layerLooks.js +116 -0
- package/dist/render/shaders/flat/layered.d.ts +19 -9
- package/dist/render/shaders/flat/layered.js +169 -37
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +17 -5
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/normalMap.d.ts +1 -1
- package/dist/render/shaders/flat/normalMap.js +11 -2
- package/dist/render/shaders/flat/preamble.js +6 -0
- package/dist/render/shaders/generated/ambientOcclusion.wgsl.d.ts +6 -1
- package/dist/render/shaders/generated/ambientOcclusion.wgsl.js +6 -1
- package/dist/render/shaders/generated/flat.wgsl.d.ts +176 -48
- package/dist/render/shaders/generated/flat.wgsl.js +215 -87
- package/dist/render/surfaceLayerLooks.d.ts +80 -0
- package/dist/render/surfaceLayerLooks.js +83 -0
- package/dist/render/surfaceLayers.d.ts +128 -19
- package/dist/render/surfaceLayers.js +73 -13
- package/dist/render/surfaceTexture.d.ts +13 -4
- package/dist/render/transmission.d.ts +21 -0
- package/dist/render/transmission.js +21 -0
- package/dist/ui/splash.d.ts +42 -2
- package/dist/ui/splash.js +78 -13
- package/package.json +6 -6
- package/scripts/browser.d.mts +5 -0
- package/scripts/browser.mjs +68 -14
- package/scripts/look.d.mts +81 -0
- package/scripts/look.mjs +380 -0
- package/src/index.ts +4 -0
- package/src/render/ambientOcclusionPass.ts +4 -1
- package/src/render/backend/api.ts +31 -0
- package/src/render/backend/webgl2/renderer.ts +170 -22
- package/src/render/backend/webgpu/renderer.ts +379 -139
- package/src/render/instances.ts +18 -1
- package/src/render/occlusionFade.ts +29 -0
- package/src/render/sceneTarget.ts +3 -0
- package/src/render/shaders/ambientOcclusion.ts +12 -1
- package/src/render/shaders/flat/areaLight.ts +1 -1
- package/src/render/shaders/flat/glassTint.ts +3 -1
- package/src/render/shaders/flat/index.ts +15 -3
- package/src/render/shaders/flat/layerLooks.ts +116 -0
- package/src/render/shaders/flat/layered.ts +170 -37
- package/src/render/shaders/flat/main.ts +17 -5
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/normalMap.ts +11 -2
- package/src/render/shaders/flat/preamble.ts +6 -0
- package/src/render/shaders/generated/ambientOcclusion.wgsl.ts +6 -1
- package/src/render/shaders/generated/flat.wgsl.ts +215 -87
- package/src/render/surfaceLayerLooks.ts +155 -0
- package/src/render/surfaceLayers.ts +187 -23
- package/src/render/surfaceTexture.ts +13 -4
- package/src/render/transmission.ts +27 -0
- package/src/ui/splash.ts +83 -14
|
@@ -106,9 +106,18 @@ import {
|
|
|
106
106
|
type SurfaceOverlay,
|
|
107
107
|
} from '../../surfaceOverlay.ts';
|
|
108
108
|
import { PROJECTION_FLOATS, packSurfaceProjection, projects } from '../../surfaceProjection.ts';
|
|
109
|
+
import { resolveTransmission } from '../../transmission.ts';
|
|
110
|
+
import { resolveOcclusionFade } from '../../occlusionFade.ts';
|
|
109
111
|
import { orthographicDepthSpan } from '../../lightMatrix.ts';
|
|
110
|
-
import {
|
|
112
|
+
import {
|
|
113
|
+
LAYER_FLOATS,
|
|
114
|
+
layerMaskMap,
|
|
115
|
+
layeredProjection,
|
|
116
|
+
layersFitBeside,
|
|
117
|
+
packSurfaceLayers,
|
|
118
|
+
} from '../../surfaceLayers.ts';
|
|
111
119
|
import type { SurfaceLayers } from '../../surfaceLayers.ts';
|
|
120
|
+
import { LOOK_FLOATS, asksLayerLooks, packLayerLooks } from '../../surfaceLayerLooks.ts';
|
|
112
121
|
import type { SurfaceProjection } from '../../surfaceProjection.ts';
|
|
113
122
|
import { FILM_FRAG, FILM_VERT } from '../../shaders/film.ts';
|
|
114
123
|
import { SceneTarget } from '../../sceneTarget.ts';
|
|
@@ -282,7 +291,7 @@ import type { BufferSize } from '../../drawingBuffer.ts';
|
|
|
282
291
|
import { Mesh, createMeshIncremental } from '../../mesh.ts';
|
|
283
292
|
import type { IncrementalMesh } from '../../mesh.ts';
|
|
284
293
|
import type { MeshData } from '../../mesh.ts';
|
|
285
|
-
import type { MeshOptions } from '../api.ts';
|
|
294
|
+
import type { MeshOptions, PrepareOptions } from '../api.ts';
|
|
286
295
|
import { SurfaceTexture } from '../../surfaceTexture.ts';
|
|
287
296
|
import { sceneCaptureTexels } from '../../sceneCapture.ts';
|
|
288
297
|
import { GlSceneCaptureTarget } from './sceneCaptureTarget.ts';
|
|
@@ -1599,6 +1608,8 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
1599
1608
|
private readonly aoProjScale = new Float32Array(2);
|
|
1600
1609
|
/** Where this frame's jitter put the occlusion, in the composite's uv. See `uAoOffset`. */
|
|
1601
1610
|
private readonly aoOffset = new Float32Array(2);
|
|
1611
|
+
/** Where occlusion fades out with distance, `uFade`: none until a caller sets one. */
|
|
1612
|
+
private readonly aoFade = new Float32Array([-1, 0]);
|
|
1602
1613
|
/**
|
|
1603
1614
|
* Whether this frame has already been resolved to the canvas.
|
|
1604
1615
|
*
|
|
@@ -1766,14 +1777,23 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
1766
1777
|
private warnedProjectionRoom = false;
|
|
1767
1778
|
/** `uWorldUv`, the current material's projection packed. See `surfaceProjection.ts`. */
|
|
1768
1779
|
private readonly projection = new Float32Array(PROJECTION_FLOATS);
|
|
1769
|
-
/**
|
|
1770
|
-
|
|
1780
|
+
/**
|
|
1781
|
+
* `uGlassTint` as the current material leaves it: its light from behind and that light's colour,
|
|
1782
|
+
* which a pane overwrites for its own draw and `unbindSeeThrough` puts back. See `transmission.ts`.
|
|
1783
|
+
*/
|
|
1784
|
+
private readonly transmission = new Float32Array([-1, -1, -1, 0]);
|
|
1771
1785
|
/** `uLayers`, the current material's layers packed. See `surfaceLayers.ts`. */
|
|
1772
1786
|
private readonly layerFloats = new Float32Array(LAYER_FLOATS);
|
|
1787
|
+
/** `uLayerLooks`, the current material's layer picks and looks packed. See `surfaceLayerLooks.ts`. */
|
|
1788
|
+
private readonly lookFloats = new Float32Array(LOOK_FLOATS);
|
|
1773
1789
|
/** Whether the lit stage has room for layers' two vectors, and which refusals were said. */
|
|
1774
1790
|
private layersRoom: boolean | null = null;
|
|
1775
1791
|
private warnedLayersRoom = false;
|
|
1792
|
+
/** Whether it has room for the layers' looks beside them, and whether the refusal was said. */
|
|
1793
|
+
private looksRoom: boolean | null = null;
|
|
1794
|
+
private warnedLooksRoom = false;
|
|
1776
1795
|
private warnedLayersModelMap = false;
|
|
1796
|
+
private warnedLayersTriplanar = false;
|
|
1777
1797
|
private warnedOverlayRoom = false;
|
|
1778
1798
|
private warnedOverlayBlocks = false;
|
|
1779
1799
|
/** Whether a probe is being baked, so the passes that would recurse into one can tell. */
|
|
@@ -3929,6 +3949,58 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
3929
3949
|
* `uScale`/`vScale` are repeats across the mesh's own UV range: geometry authored in
|
|
3930
3950
|
* metres is textured at whatever density the material wants without rebuilding it.
|
|
3931
3951
|
*/
|
|
3952
|
+
/**
|
|
3953
|
+
* Compile, off the frame, every program a draw of `mesh` in `material` takes that making the mesh
|
|
3954
|
+
* did not, so the first frame that draws it waits on none: the program of the material's shading
|
|
3955
|
+
* model for each vertex variant the mesh can be drawn with (its rig, with a palette; its targets,
|
|
3956
|
+
* with weights and without), a skin's halves under the screen-space blur, and the lit switches
|
|
3957
|
+
* the material turns on. `ready()` resolves once they have.
|
|
3958
|
+
*
|
|
3959
|
+
* **For `pipelineCompile: 'skip'` above all**, where a draw whose program is new is left out until
|
|
3960
|
+
* it lands: a figure brought on screen whole rather than without its face and hair for the frames
|
|
3961
|
+
* those take. Where draws wait, the programs compile here, at the call, rather than in a frame.
|
|
3962
|
+
* Two-sided and cut-out surfaces are draw state on this backend and need nothing; on WebGPU they
|
|
3963
|
+
* are pipelines of their own, prepared the same way.
|
|
3964
|
+
*
|
|
3965
|
+
* **Call it between frames**: it sets `material` to read it and leaves no material set after, as
|
|
3966
|
+
* `setMaterial(null)` does. `options` is the other backend's; blended draws share a program here.
|
|
3967
|
+
*/
|
|
3968
|
+
prepareMesh(mesh: Mesh, material: SurfaceMaterial | null, _options: PrepareOptions = {}): void {
|
|
3969
|
+
if (this.contextLost) return;
|
|
3970
|
+
this.setMaterial(material);
|
|
3971
|
+
const kind = material?.model?.kind ?? null;
|
|
3972
|
+
if (kind !== null) {
|
|
3973
|
+
const eight = mesh.isSkinnedEight;
|
|
3974
|
+
const morphs = mesh.morph !== null;
|
|
3975
|
+
const plain = mesh.isSkinned ? (eight ? 'skinned8' : 'skinned') : 'plain';
|
|
3976
|
+
const morphed = mesh.isSkinned ? (eight ? 'both8' : 'both') : 'morphed';
|
|
3977
|
+
for (const variant of morphs ? [plain, morphed] : [plain]) {
|
|
3978
|
+
this.modelProgram(variant, kind);
|
|
3979
|
+
/* A skin under the screen-space blur draws three halves, each a program of its own. */
|
|
3980
|
+
if (kind === 'skin' && this.skinScatter !== null && this.sceneTarget !== null) {
|
|
3981
|
+
for (const half of SPLIT_SKIN_HALVES) this.modelProgram(variant, kind, half);
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
this.setMaterial(null);
|
|
3986
|
+
}
|
|
3987
|
+
|
|
3988
|
+
/** `prepareMesh` for an instanced batch: its own programs, and its model's for its variant. */
|
|
3989
|
+
prepareInstanced(
|
|
3990
|
+
batch: InstancedBatch,
|
|
3991
|
+
material: SurfaceMaterial | null,
|
|
3992
|
+
_options: PrepareOptions = {},
|
|
3993
|
+
): void {
|
|
3994
|
+
if (this.contextLost) return;
|
|
3995
|
+
this.setMaterial(material);
|
|
3996
|
+
const animated = batch.animation !== null;
|
|
3997
|
+
this.ensureInstancedProgram();
|
|
3998
|
+
if (animated) this.ensureAnimatedProgram();
|
|
3999
|
+
const kind = material?.model?.kind ?? null;
|
|
4000
|
+
if (kind !== null) this.modelProgram(animated ? 'animated' : 'instanced', kind);
|
|
4001
|
+
this.setMaterial(null);
|
|
4002
|
+
}
|
|
4003
|
+
|
|
3932
4004
|
/**
|
|
3933
4005
|
* Choose the joint palette the following `drawMesh` calls skin by, or null for none.
|
|
3934
4006
|
*
|
|
@@ -4323,15 +4395,18 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4323
4395
|
* and read neither — one decision for every program, as `setMaterial` says.
|
|
4324
4396
|
*/
|
|
4325
4397
|
const modelMap = material?.modelMap ?? null;
|
|
4326
|
-
/* A layered material's mask goes where a model's
|
|
4398
|
+
/* A layered material's mask, where it is a map, goes where a model's would: surfaceLayers.ts. */
|
|
4327
4399
|
const layers = this.layersOf(material);
|
|
4328
|
-
const boundMap = modelMap ?? layers
|
|
4400
|
+
const boundMap = modelMap ?? layerMaskMap(layers);
|
|
4329
4401
|
gl.activeTexture(gl.TEXTURE0 + MODEL_MAP_TEXTURE_UNIT);
|
|
4330
4402
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.emptyTexture2DArray);
|
|
4331
4403
|
if (boundMap !== null) boundMap.bind(gl, MODEL_MAP_TEXTURE_UNIT);
|
|
4332
4404
|
packSurfaceLayers(layers, this.layerFloats);
|
|
4333
4405
|
if (layers !== null) this.askLit('LAYERED');
|
|
4334
4406
|
gl.uniform4fv(u['uLayers'] ?? null, this.layerFloats);
|
|
4407
|
+
packLayerLooks(layers, this.lookFloats);
|
|
4408
|
+
if (this.looksFit(layers)) this.askLit('LAYER_LOOKS');
|
|
4409
|
+
gl.uniform4fv(u['uLayerLooks'] ?? null, this.lookFloats);
|
|
4335
4410
|
gl.uniform1i(u['uModelMap'] ?? null, MODEL_MAP_TEXTURE_UNIT);
|
|
4336
4411
|
packModel(
|
|
4337
4412
|
material?.model ?? null,
|
|
@@ -4345,11 +4420,12 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4345
4420
|
/* The draw's overlay, which a program born mid-pass must wear too: see `setSurfaceOverlay`. */
|
|
4346
4421
|
gl.uniform4fv(u['uOverlay'] ?? null, this.overlayFloats);
|
|
4347
4422
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
4348
|
-
/* How much light from behind the surface lets through,
|
|
4349
|
-
|
|
4350
|
-
|
|
4423
|
+
/* How much light from behind the surface lets through, and its colour: transmission.ts. */
|
|
4424
|
+
resolveTransmission(material, this.transmission);
|
|
4425
|
+
this.writeTransmission(u);
|
|
4351
4426
|
/* Maps placed by the world, where the material asks and the lit stage has room: worldUv.ts. */
|
|
4352
|
-
const projection = material?.projection
|
|
4427
|
+
const projection = layeredProjection(material?.projection, layers);
|
|
4428
|
+
if (projection !== (material?.projection ?? null)) this.warnLayersTriplanar();
|
|
4353
4429
|
packSurfaceProjection(this.projectionFits(projection) ? projection : null, this.projection);
|
|
4354
4430
|
if ((this.projection[0] as number) > 0) this.askLit('WORLD_UVS');
|
|
4355
4431
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
@@ -4598,14 +4674,15 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4598
4674
|
* no room for their two vectors each leave one layer, the last two said once each.
|
|
4599
4675
|
*/
|
|
4600
4676
|
private layersOf(material: SurfaceMaterial | null): SurfaceLayers<SurfaceTexture> | null {
|
|
4601
|
-
const layers = material?.layers ?? null;
|
|
4677
|
+
const layers = (material?.layers ?? null) as SurfaceLayers<SurfaceTexture> | null;
|
|
4602
4678
|
if (layers === null || layers.repeats.length === 0) return null;
|
|
4603
|
-
if ((material?.modelMap
|
|
4679
|
+
if (!layersFitBeside(layers, material?.modelMap)) {
|
|
4604
4680
|
if (!this.warnedLayersModelMap) {
|
|
4605
4681
|
this.warnedLayersModelMap = true;
|
|
4606
4682
|
console.warn(
|
|
4607
|
-
"Renderer: a material's layers are drawn as one: its mask is read where a
|
|
4608
|
-
'goes, and this material carries a `modelMap` too.
|
|
4683
|
+
"Renderer: a material's layers are drawn as one: its mask is a map, read where a " +
|
|
4684
|
+
"model's map goes, and this material carries a `modelMap` too. A mask in the ORM " +
|
|
4685
|
+
"array (`mask: 'orm'`) or the vertex colour (`mask: 'vertex'`) leaves the slot free.",
|
|
4609
4686
|
);
|
|
4610
4687
|
}
|
|
4611
4688
|
return null;
|
|
@@ -4615,7 +4692,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4615
4692
|
if (!this.warnedLayersRoom) {
|
|
4616
4693
|
this.warnedLayersRoom = true;
|
|
4617
4694
|
console.warn(
|
|
4618
|
-
"Renderer: a material's layers are refused on this device. They take
|
|
4695
|
+
"Renderer: a material's layers are refused on this device. They take four fragment uniform " +
|
|
4619
4696
|
'vectors the lit shader does not have; the material is drawn as its base layer. A lower ' +
|
|
4620
4697
|
'`maxLights` makes the room, or WebGPU has it.',
|
|
4621
4698
|
);
|
|
@@ -4623,9 +4700,45 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4623
4700
|
return null;
|
|
4624
4701
|
}
|
|
4625
4702
|
|
|
4626
|
-
/**
|
|
4627
|
-
|
|
4703
|
+
/**
|
|
4704
|
+
* Whether a layered material's picks and looks are drawn: asked for, and room for their fifteen
|
|
4705
|
+
* vectors beside the layers' four. Refused, the layers are drawn reading layer `i` of their arrays
|
|
4706
|
+
* as they are, said once — which on a material sharing its arrays reads the wrong textures, so
|
|
4707
|
+
* the sentence names the way out.
|
|
4708
|
+
*/
|
|
4709
|
+
private looksFit(layers: SurfaceLayers<SurfaceTexture> | null): boolean {
|
|
4710
|
+
if (!asksLayerLooks(layers)) return false;
|
|
4711
|
+
this.looksRoom ??= this.switchFits('LAYER_LOOKS', 'LAYERED');
|
|
4712
|
+
if (this.looksRoom) return true;
|
|
4713
|
+
if (!this.warnedLooksRoom) {
|
|
4714
|
+
this.warnedLooksRoom = true;
|
|
4715
|
+
console.warn(
|
|
4716
|
+
"Renderer: a layered material's picks and looks are refused on this device. They take " +
|
|
4717
|
+
'fifteen fragment uniform vectors the lit shader does not have, so its layers read layer ' +
|
|
4718
|
+
'i of its arrays, untinted, at one repeat each. A lower `maxLights` makes the room, or ' +
|
|
4719
|
+
'WebGPU has it.',
|
|
4720
|
+
);
|
|
4721
|
+
}
|
|
4722
|
+
return false;
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
/** Says once that a layered material's triplanar projection is laid on the horizontal plane. */
|
|
4726
|
+
private warnLayersTriplanar(): void {
|
|
4727
|
+
if (this.warnedLayersTriplanar) return;
|
|
4728
|
+
this.warnedLayersTriplanar = true;
|
|
4729
|
+
console.warn(
|
|
4730
|
+
"Renderer: a layered material's triplanar projection is laid on the horizontal plane: every " +
|
|
4731
|
+
"layer's maps on three planes would be three times the reads. See `SurfaceMaterial.layers`.",
|
|
4732
|
+
);
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
/**
|
|
4736
|
+
* Whether the lit shader with `feature` compiled in, and `beside` with it where a switch means
|
|
4737
|
+
* nothing alone, fits this GPU's fragment uniform vectors.
|
|
4738
|
+
*/
|
|
4739
|
+
private switchFits(feature: LitSwitch, beside?: LitSwitch): boolean {
|
|
4628
4740
|
const asIf: Partial<Record<LitSwitch, boolean>> = { [feature]: true };
|
|
4741
|
+
if (beside !== undefined) asIf[beside] = true;
|
|
4629
4742
|
return (
|
|
4630
4743
|
countUniformVectors(this.flatFragAt(this.lightBudget, asIf)) <= this.fragmentVectorLimit()
|
|
4631
4744
|
);
|
|
@@ -4786,7 +4899,8 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4786
4899
|
*
|
|
4787
4900
|
* What it gives up: a fade reads as grain while it lasts, which a temporal resolve smooths and a
|
|
4788
4901
|
* plain frame does not; a blended draw that asks spends its opacity here and blends none of it;
|
|
4789
|
-
* and a lightmapped batch
|
|
4902
|
+
* and a lightmapped batch's opacities ride its page regions, so they fade in steps of a
|
|
4903
|
+
* sixty-fourth, which is the pattern's own resolution (`MeshInstances.lightmapRegions`).
|
|
4790
4904
|
*/
|
|
4791
4905
|
setDitherOpacity(on: boolean): void {
|
|
4792
4906
|
if (this.contextLost) return;
|
|
@@ -5281,15 +5395,23 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
5281
5395
|
glass.tint[0] ?? 1,
|
|
5282
5396
|
glass.tint[1] ?? 1,
|
|
5283
5397
|
glass.tint[2] ?? 1,
|
|
5284
|
-
this.
|
|
5398
|
+
this.transmission[3] as number,
|
|
5285
5399
|
);
|
|
5286
5400
|
return true;
|
|
5287
5401
|
}
|
|
5288
5402
|
|
|
5403
|
+
/** `uGlassTint` as the current material leaves it. See `transmission`. */
|
|
5404
|
+
private writeTransmission(u: Record<string, WebGLUniformLocation>): void {
|
|
5405
|
+
const t = this.transmission;
|
|
5406
|
+
this.gl.uniform4f(u['uGlassTint'] ?? null, t[0] ?? -1, t[1] ?? -1, t[2] ?? -1, t[3] ?? 0);
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5289
5409
|
/** Put back what `bindSeeThrough` bound: the binding outlives its frame (the 2026-08-27 rule). */
|
|
5290
5410
|
private unbindSeeThrough(u: Record<string, WebGLUniformLocation>): void {
|
|
5291
5411
|
const { gl } = this;
|
|
5292
5412
|
gl.uniform4f(u['uSeeThrough'] ?? null, 0, 0, 0, 0);
|
|
5413
|
+
/* The material's light through, over the pane's tint: transmission.ts. */
|
|
5414
|
+
this.writeTransmission(u);
|
|
5293
5415
|
gl.activeTexture(gl.TEXTURE0 + REFRACT_SCENE_TEXTURE_UNIT);
|
|
5294
5416
|
/* The overlay's atlas, where one is held: it shares the unit. See `setSurfaceOverlay`. */
|
|
5295
5417
|
gl.bindTexture(gl.TEXTURE_2D, this.overlayTexture ?? this.emptyTexture2D);
|
|
@@ -6873,6 +6995,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
6873
6995
|
worldUvs: asIf.WORLD_UVS ?? this.litOn.WORLD_UVS,
|
|
6874
6996
|
movingSun: asIf.MOVING_SUN ?? this.litOn.MOVING_SUN,
|
|
6875
6997
|
layered: asIf.LAYERED ?? this.litOn.LAYERED,
|
|
6998
|
+
layerLooks: asIf.LAYER_LOOKS ?? this.litOn.LAYER_LOOKS,
|
|
6876
6999
|
maxLights: budget.maxLights,
|
|
6877
7000
|
maxAreaLights: budget.maxAreaLights,
|
|
6878
7001
|
});
|
|
@@ -7800,6 +7923,20 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
7800
7923
|
this.sceneTarget.setLocalExposure(strength);
|
|
7801
7924
|
}
|
|
7802
7925
|
|
|
7926
|
+
/**
|
|
7927
|
+
* Where ambient occlusion fades out with distance: whole up to `distance` metres from the eye and
|
|
7928
|
+
* gone `radius` metres past it, so the far depth buffer's steps — a sky dome kilometres off, a
|
|
7929
|
+
* mountain range — are not shaded in rings, and those pixels skip the occlusion's sampling.
|
|
7930
|
+
*
|
|
7931
|
+
* A distance that is not a finite number at or above zero is no fade, which is the default, and
|
|
7932
|
+
* `Infinity` reads as "never fades"; a radius below zero is a cut at `distance`. Set before
|
|
7933
|
+
* `endFrame` and held until changed, like `setDepthOfField`. Nothing at all when
|
|
7934
|
+
* `ambientOcclusion` is 0. See `occlusionFade.ts` for what it gives up.
|
|
7935
|
+
*/
|
|
7936
|
+
setAmbientOcclusionFade(distance: number, radius: number): void {
|
|
7937
|
+
resolveOcclusionFade(distance, radius, this.aoFade);
|
|
7938
|
+
}
|
|
7939
|
+
|
|
7803
7940
|
/**
|
|
7804
7941
|
* Where this frame's lens is focused, how deep the sharp zone is, and how much of the ceiling
|
|
7805
7942
|
* to take.
|
|
@@ -8453,6 +8590,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
8453
8590
|
radius: number;
|
|
8454
8591
|
projScale: Float32Array;
|
|
8455
8592
|
invProjection: Float32Array;
|
|
8593
|
+
fade: Float32Array;
|
|
8456
8594
|
offset: Float32Array;
|
|
8457
8595
|
}
|
|
8458
8596
|
| undefined;
|
|
@@ -8476,6 +8614,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
8476
8614
|
radius: this.quality.ambientOcclusionRadius,
|
|
8477
8615
|
projScale: this.aoProjScale,
|
|
8478
8616
|
invProjection: this.aoInvProjection as Float32Array,
|
|
8617
|
+
fade: this.aoFade,
|
|
8479
8618
|
offset: this.aoOffset,
|
|
8480
8619
|
};
|
|
8481
8620
|
}
|
|
@@ -9010,9 +9149,10 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
9010
9149
|
/* Nor a projection: maps follow the mesh's coordinates until a material asks otherwise. */
|
|
9011
9150
|
this.projection.fill(0);
|
|
9012
9151
|
/* Nor light through from behind. See `SurfaceMaterial.diffuseTransmission`. */
|
|
9013
|
-
this.
|
|
9152
|
+
resolveTransmission(null, this.transmission);
|
|
9014
9153
|
/* Nor layers: one layer until a material asks for more. */
|
|
9015
9154
|
this.layerFloats.fill(0);
|
|
9155
|
+
this.lookFloats.fill(0);
|
|
9016
9156
|
this.overlayMaps = null;
|
|
9017
9157
|
this.overlayTexture = null;
|
|
9018
9158
|
/* Nor an ambient of its own: the frame's, until a draw asks. See `setAmbientSH`. */
|
|
@@ -9187,12 +9327,20 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
9187
9327
|
gl.uniform4fv(u['uOverlay'] ?? null, this.overlayFloats);
|
|
9188
9328
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
9189
9329
|
gl.uniform4fv(u['uLayers'] ?? null, this.layerFloats);
|
|
9330
|
+
gl.uniform4fv(u['uLayerLooks'] ?? null, this.lookFloats);
|
|
9190
9331
|
/* Neither refracting nor glass, which is every draw that does not say otherwise. See
|
|
9191
9332
|
`bindSeeThrough` for the four numbers in the one vector. */
|
|
9192
9333
|
gl.uniform4f(u['uSeeThrough'] ?? null, 0, 0, 0, 0);
|
|
9193
9334
|
gl.uniform4f(u['uRefractTint'] ?? null, 1, 1, 1, 1);
|
|
9194
|
-
/*
|
|
9195
|
-
|
|
9335
|
+
/* No light through from behind: no material at a pass's start. See `writeTransmission`. */
|
|
9336
|
+
const through = this.transmission;
|
|
9337
|
+
gl.uniform4f(
|
|
9338
|
+
u['uGlassTint'] ?? null,
|
|
9339
|
+
through[0] ?? -1,
|
|
9340
|
+
through[1] ?? -1,
|
|
9341
|
+
through[2] ?? -1,
|
|
9342
|
+
through[3] ?? 0,
|
|
9343
|
+
);
|
|
9196
9344
|
gl.uniform3fv(u['uDirectionalDir'] ?? null, env.directionalDir);
|
|
9197
9345
|
gl.uniform3fv(u['uDirectionalColor'] ?? null, env.directionalColor);
|
|
9198
9346
|
gl.uniform3fv(u['uAmbient'] ?? null, env.ambient);
|