@driftengine/core 4.11.0 → 4.11.1
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 +36 -0
- package/README.md +1 -1
- package/dist/index.d.ts +2 -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 +45 -4
- package/dist/render/backend/webgl2/renderer.js +112 -19
- package/dist/render/backend/webgpu/renderer.d.ts +52 -1
- package/dist/render/backend/webgpu/renderer.js +237 -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/index.js +9 -2
- package/dist/render/shaders/flat/layered.d.ts +15 -7
- package/dist/render/shaders/flat/layered.js +114 -31
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +10 -3
- package/dist/render/shaders/flat/normalMap.d.ts +1 -1
- package/dist/render/shaders/flat/normalMap.js +11 -2
- 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 +48 -48
- package/dist/render/shaders/generated/flat.wgsl.js +71 -71
- package/dist/render/surfaceLayers.d.ts +83 -15
- package/dist/render/surfaceLayers.js +69 -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/src/index.ts +2 -0
- package/src/render/ambientOcclusionPass.ts +4 -1
- package/src/render/backend/api.ts +31 -0
- package/src/render/backend/webgl2/renderer.ts +130 -20
- package/src/render/backend/webgpu/renderer.ts +371 -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/index.ts +9 -2
- package/src/render/shaders/flat/layered.ts +114 -31
- package/src/render/shaders/flat/main.ts +10 -3
- package/src/render/shaders/flat/normalMap.ts +11 -2
- package/src/render/shaders/generated/ambientOcclusion.wgsl.ts +6 -1
- package/src/render/shaders/generated/flat.wgsl.ts +71 -71
- package/src/render/surfaceLayers.ts +138 -19
- package/src/render/surfaceTexture.ts +13 -4
- package/src/render/transmission.ts +27 -0
- package/src/ui/splash.ts +83 -14
|
@@ -106,8 +106,16 @@ 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';
|
|
112
120
|
import type { SurfaceProjection } from '../../surfaceProjection.ts';
|
|
113
121
|
import { FILM_FRAG, FILM_VERT } from '../../shaders/film.ts';
|
|
@@ -282,7 +290,7 @@ import type { BufferSize } from '../../drawingBuffer.ts';
|
|
|
282
290
|
import { Mesh, createMeshIncremental } from '../../mesh.ts';
|
|
283
291
|
import type { IncrementalMesh } from '../../mesh.ts';
|
|
284
292
|
import type { MeshData } from '../../mesh.ts';
|
|
285
|
-
import type { MeshOptions } from '../api.ts';
|
|
293
|
+
import type { MeshOptions, PrepareOptions } from '../api.ts';
|
|
286
294
|
import { SurfaceTexture } from '../../surfaceTexture.ts';
|
|
287
295
|
import { sceneCaptureTexels } from '../../sceneCapture.ts';
|
|
288
296
|
import { GlSceneCaptureTarget } from './sceneCaptureTarget.ts';
|
|
@@ -1599,6 +1607,8 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
1599
1607
|
private readonly aoProjScale = new Float32Array(2);
|
|
1600
1608
|
/** Where this frame's jitter put the occlusion, in the composite's uv. See `uAoOffset`. */
|
|
1601
1609
|
private readonly aoOffset = new Float32Array(2);
|
|
1610
|
+
/** Where occlusion fades out with distance, `uFade`: none until a caller sets one. */
|
|
1611
|
+
private readonly aoFade = new Float32Array([-1, 0]);
|
|
1602
1612
|
/**
|
|
1603
1613
|
* Whether this frame has already been resolved to the canvas.
|
|
1604
1614
|
*
|
|
@@ -1766,14 +1776,18 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
1766
1776
|
private warnedProjectionRoom = false;
|
|
1767
1777
|
/** `uWorldUv`, the current material's projection packed. See `surfaceProjection.ts`. */
|
|
1768
1778
|
private readonly projection = new Float32Array(PROJECTION_FLOATS);
|
|
1769
|
-
/**
|
|
1770
|
-
|
|
1779
|
+
/**
|
|
1780
|
+
* `uGlassTint` as the current material leaves it: its light from behind and that light's colour,
|
|
1781
|
+
* which a pane overwrites for its own draw and `unbindSeeThrough` puts back. See `transmission.ts`.
|
|
1782
|
+
*/
|
|
1783
|
+
private readonly transmission = new Float32Array([-1, -1, -1, 0]);
|
|
1771
1784
|
/** `uLayers`, the current material's layers packed. See `surfaceLayers.ts`. */
|
|
1772
1785
|
private readonly layerFloats = new Float32Array(LAYER_FLOATS);
|
|
1773
1786
|
/** Whether the lit stage has room for layers' two vectors, and which refusals were said. */
|
|
1774
1787
|
private layersRoom: boolean | null = null;
|
|
1775
1788
|
private warnedLayersRoom = false;
|
|
1776
1789
|
private warnedLayersModelMap = false;
|
|
1790
|
+
private warnedLayersTriplanar = false;
|
|
1777
1791
|
private warnedOverlayRoom = false;
|
|
1778
1792
|
private warnedOverlayBlocks = false;
|
|
1779
1793
|
/** Whether a probe is being baked, so the passes that would recurse into one can tell. */
|
|
@@ -3929,6 +3943,58 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
3929
3943
|
* `uScale`/`vScale` are repeats across the mesh's own UV range: geometry authored in
|
|
3930
3944
|
* metres is textured at whatever density the material wants without rebuilding it.
|
|
3931
3945
|
*/
|
|
3946
|
+
/**
|
|
3947
|
+
* Compile, off the frame, every program a draw of `mesh` in `material` takes that making the mesh
|
|
3948
|
+
* did not, so the first frame that draws it waits on none: the program of the material's shading
|
|
3949
|
+
* model for each vertex variant the mesh can be drawn with (its rig, with a palette; its targets,
|
|
3950
|
+
* with weights and without), a skin's halves under the screen-space blur, and the lit switches
|
|
3951
|
+
* the material turns on. `ready()` resolves once they have.
|
|
3952
|
+
*
|
|
3953
|
+
* **For `pipelineCompile: 'skip'` above all**, where a draw whose program is new is left out until
|
|
3954
|
+
* it lands: a figure brought on screen whole rather than without its face and hair for the frames
|
|
3955
|
+
* those take. Where draws wait, the programs compile here, at the call, rather than in a frame.
|
|
3956
|
+
* Two-sided and cut-out surfaces are draw state on this backend and need nothing; on WebGPU they
|
|
3957
|
+
* are pipelines of their own, prepared the same way.
|
|
3958
|
+
*
|
|
3959
|
+
* **Call it between frames**: it sets `material` to read it and leaves no material set after, as
|
|
3960
|
+
* `setMaterial(null)` does. `options` is the other backend's; blended draws share a program here.
|
|
3961
|
+
*/
|
|
3962
|
+
prepareMesh(mesh: Mesh, material: SurfaceMaterial | null, _options: PrepareOptions = {}): void {
|
|
3963
|
+
if (this.contextLost) return;
|
|
3964
|
+
this.setMaterial(material);
|
|
3965
|
+
const kind = material?.model?.kind ?? null;
|
|
3966
|
+
if (kind !== null) {
|
|
3967
|
+
const eight = mesh.isSkinnedEight;
|
|
3968
|
+
const morphs = mesh.morph !== null;
|
|
3969
|
+
const plain = mesh.isSkinned ? (eight ? 'skinned8' : 'skinned') : 'plain';
|
|
3970
|
+
const morphed = mesh.isSkinned ? (eight ? 'both8' : 'both') : 'morphed';
|
|
3971
|
+
for (const variant of morphs ? [plain, morphed] : [plain]) {
|
|
3972
|
+
this.modelProgram(variant, kind);
|
|
3973
|
+
/* A skin under the screen-space blur draws three halves, each a program of its own. */
|
|
3974
|
+
if (kind === 'skin' && this.skinScatter !== null && this.sceneTarget !== null) {
|
|
3975
|
+
for (const half of SPLIT_SKIN_HALVES) this.modelProgram(variant, kind, half);
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
this.setMaterial(null);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
/** `prepareMesh` for an instanced batch: its own programs, and its model's for its variant. */
|
|
3983
|
+
prepareInstanced(
|
|
3984
|
+
batch: InstancedBatch,
|
|
3985
|
+
material: SurfaceMaterial | null,
|
|
3986
|
+
_options: PrepareOptions = {},
|
|
3987
|
+
): void {
|
|
3988
|
+
if (this.contextLost) return;
|
|
3989
|
+
this.setMaterial(material);
|
|
3990
|
+
const animated = batch.animation !== null;
|
|
3991
|
+
this.ensureInstancedProgram();
|
|
3992
|
+
if (animated) this.ensureAnimatedProgram();
|
|
3993
|
+
const kind = material?.model?.kind ?? null;
|
|
3994
|
+
if (kind !== null) this.modelProgram(animated ? 'animated' : 'instanced', kind);
|
|
3995
|
+
this.setMaterial(null);
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3932
3998
|
/**
|
|
3933
3999
|
* Choose the joint palette the following `drawMesh` calls skin by, or null for none.
|
|
3934
4000
|
*
|
|
@@ -4323,9 +4389,9 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4323
4389
|
* and read neither — one decision for every program, as `setMaterial` says.
|
|
4324
4390
|
*/
|
|
4325
4391
|
const modelMap = material?.modelMap ?? null;
|
|
4326
|
-
/* A layered material's mask goes where a model's
|
|
4392
|
+
/* A layered material's mask, where it is a map, goes where a model's would: surfaceLayers.ts. */
|
|
4327
4393
|
const layers = this.layersOf(material);
|
|
4328
|
-
const boundMap = modelMap ?? layers
|
|
4394
|
+
const boundMap = modelMap ?? layerMaskMap(layers);
|
|
4329
4395
|
gl.activeTexture(gl.TEXTURE0 + MODEL_MAP_TEXTURE_UNIT);
|
|
4330
4396
|
gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.emptyTexture2DArray);
|
|
4331
4397
|
if (boundMap !== null) boundMap.bind(gl, MODEL_MAP_TEXTURE_UNIT);
|
|
@@ -4345,11 +4411,12 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4345
4411
|
/* The draw's overlay, which a program born mid-pass must wear too: see `setSurfaceOverlay`. */
|
|
4346
4412
|
gl.uniform4fv(u['uOverlay'] ?? null, this.overlayFloats);
|
|
4347
4413
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
4348
|
-
/* How much light from behind the surface lets through,
|
|
4349
|
-
|
|
4350
|
-
|
|
4414
|
+
/* How much light from behind the surface lets through, and its colour: transmission.ts. */
|
|
4415
|
+
resolveTransmission(material, this.transmission);
|
|
4416
|
+
this.writeTransmission(u);
|
|
4351
4417
|
/* Maps placed by the world, where the material asks and the lit stage has room: worldUv.ts. */
|
|
4352
|
-
const projection = material?.projection
|
|
4418
|
+
const projection = layeredProjection(material?.projection, layers);
|
|
4419
|
+
if (projection !== (material?.projection ?? null)) this.warnLayersTriplanar();
|
|
4353
4420
|
packSurfaceProjection(this.projectionFits(projection) ? projection : null, this.projection);
|
|
4354
4421
|
if ((this.projection[0] as number) > 0) this.askLit('WORLD_UVS');
|
|
4355
4422
|
gl.uniform4fv(u['uWorldUv'] ?? null, this.projection);
|
|
@@ -4598,14 +4665,15 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4598
4665
|
* no room for their two vectors each leave one layer, the last two said once each.
|
|
4599
4666
|
*/
|
|
4600
4667
|
private layersOf(material: SurfaceMaterial | null): SurfaceLayers<SurfaceTexture> | null {
|
|
4601
|
-
const layers = material?.layers ?? null;
|
|
4668
|
+
const layers = (material?.layers ?? null) as SurfaceLayers<SurfaceTexture> | null;
|
|
4602
4669
|
if (layers === null || layers.repeats.length === 0) return null;
|
|
4603
|
-
if ((material?.modelMap
|
|
4670
|
+
if (!layersFitBeside(layers, material?.modelMap)) {
|
|
4604
4671
|
if (!this.warnedLayersModelMap) {
|
|
4605
4672
|
this.warnedLayersModelMap = true;
|
|
4606
4673
|
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.
|
|
4674
|
+
"Renderer: a material's layers are drawn as one: its mask is a map, read where a " +
|
|
4675
|
+
"model's map goes, and this material carries a `modelMap` too. A mask in the ORM " +
|
|
4676
|
+
"array (`mask: 'orm'`) or the vertex colour (`mask: 'vertex'`) leaves the slot free.",
|
|
4609
4677
|
);
|
|
4610
4678
|
}
|
|
4611
4679
|
return null;
|
|
@@ -4615,7 +4683,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4615
4683
|
if (!this.warnedLayersRoom) {
|
|
4616
4684
|
this.warnedLayersRoom = true;
|
|
4617
4685
|
console.warn(
|
|
4618
|
-
"Renderer: a material's layers are refused on this device. They take
|
|
4686
|
+
"Renderer: a material's layers are refused on this device. They take four fragment uniform " +
|
|
4619
4687
|
'vectors the lit shader does not have; the material is drawn as its base layer. A lower ' +
|
|
4620
4688
|
'`maxLights` makes the room, or WebGPU has it.',
|
|
4621
4689
|
);
|
|
@@ -4623,6 +4691,16 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4623
4691
|
return null;
|
|
4624
4692
|
}
|
|
4625
4693
|
|
|
4694
|
+
/** Says once that a layered material's triplanar projection is laid on the horizontal plane. */
|
|
4695
|
+
private warnLayersTriplanar(): void {
|
|
4696
|
+
if (this.warnedLayersTriplanar) return;
|
|
4697
|
+
this.warnedLayersTriplanar = true;
|
|
4698
|
+
console.warn(
|
|
4699
|
+
"Renderer: a layered material's triplanar projection is laid on the horizontal plane: every " +
|
|
4700
|
+
"layer's maps on three planes would be three times the reads. See `SurfaceMaterial.layers`.",
|
|
4701
|
+
);
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4626
4704
|
/** Whether the lit shader with `feature` compiled in fits this GPU's fragment uniform vectors. */
|
|
4627
4705
|
private switchFits(feature: LitSwitch): boolean {
|
|
4628
4706
|
const asIf: Partial<Record<LitSwitch, boolean>> = { [feature]: true };
|
|
@@ -4786,7 +4864,8 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
4786
4864
|
*
|
|
4787
4865
|
* What it gives up: a fade reads as grain while it lasts, which a temporal resolve smooths and a
|
|
4788
4866
|
* plain frame does not; a blended draw that asks spends its opacity here and blends none of it;
|
|
4789
|
-
* and a lightmapped batch
|
|
4867
|
+
* and a lightmapped batch's opacities ride its page regions, so they fade in steps of a
|
|
4868
|
+
* sixty-fourth, which is the pattern's own resolution (`MeshInstances.lightmapRegions`).
|
|
4790
4869
|
*/
|
|
4791
4870
|
setDitherOpacity(on: boolean): void {
|
|
4792
4871
|
if (this.contextLost) return;
|
|
@@ -5281,15 +5360,23 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
5281
5360
|
glass.tint[0] ?? 1,
|
|
5282
5361
|
glass.tint[1] ?? 1,
|
|
5283
5362
|
glass.tint[2] ?? 1,
|
|
5284
|
-
this.
|
|
5363
|
+
this.transmission[3] as number,
|
|
5285
5364
|
);
|
|
5286
5365
|
return true;
|
|
5287
5366
|
}
|
|
5288
5367
|
|
|
5368
|
+
/** `uGlassTint` as the current material leaves it. See `transmission`. */
|
|
5369
|
+
private writeTransmission(u: Record<string, WebGLUniformLocation>): void {
|
|
5370
|
+
const t = this.transmission;
|
|
5371
|
+
this.gl.uniform4f(u['uGlassTint'] ?? null, t[0] ?? -1, t[1] ?? -1, t[2] ?? -1, t[3] ?? 0);
|
|
5372
|
+
}
|
|
5373
|
+
|
|
5289
5374
|
/** Put back what `bindSeeThrough` bound: the binding outlives its frame (the 2026-08-27 rule). */
|
|
5290
5375
|
private unbindSeeThrough(u: Record<string, WebGLUniformLocation>): void {
|
|
5291
5376
|
const { gl } = this;
|
|
5292
5377
|
gl.uniform4f(u['uSeeThrough'] ?? null, 0, 0, 0, 0);
|
|
5378
|
+
/* The material's light through, over the pane's tint: transmission.ts. */
|
|
5379
|
+
this.writeTransmission(u);
|
|
5293
5380
|
gl.activeTexture(gl.TEXTURE0 + REFRACT_SCENE_TEXTURE_UNIT);
|
|
5294
5381
|
/* The overlay's atlas, where one is held: it shares the unit. See `setSurfaceOverlay`. */
|
|
5295
5382
|
gl.bindTexture(gl.TEXTURE_2D, this.overlayTexture ?? this.emptyTexture2D);
|
|
@@ -7800,6 +7887,20 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
7800
7887
|
this.sceneTarget.setLocalExposure(strength);
|
|
7801
7888
|
}
|
|
7802
7889
|
|
|
7890
|
+
/**
|
|
7891
|
+
* Where ambient occlusion fades out with distance: whole up to `distance` metres from the eye and
|
|
7892
|
+
* gone `radius` metres past it, so the far depth buffer's steps — a sky dome kilometres off, a
|
|
7893
|
+
* mountain range — are not shaded in rings, and those pixels skip the occlusion's sampling.
|
|
7894
|
+
*
|
|
7895
|
+
* A distance that is not a finite number at or above zero is no fade, which is the default, and
|
|
7896
|
+
* `Infinity` reads as "never fades"; a radius below zero is a cut at `distance`. Set before
|
|
7897
|
+
* `endFrame` and held until changed, like `setDepthOfField`. Nothing at all when
|
|
7898
|
+
* `ambientOcclusion` is 0. See `occlusionFade.ts` for what it gives up.
|
|
7899
|
+
*/
|
|
7900
|
+
setAmbientOcclusionFade(distance: number, radius: number): void {
|
|
7901
|
+
resolveOcclusionFade(distance, radius, this.aoFade);
|
|
7902
|
+
}
|
|
7903
|
+
|
|
7803
7904
|
/**
|
|
7804
7905
|
* Where this frame's lens is focused, how deep the sharp zone is, and how much of the ceiling
|
|
7805
7906
|
* to take.
|
|
@@ -8453,6 +8554,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
8453
8554
|
radius: number;
|
|
8454
8555
|
projScale: Float32Array;
|
|
8455
8556
|
invProjection: Float32Array;
|
|
8557
|
+
fade: Float32Array;
|
|
8456
8558
|
offset: Float32Array;
|
|
8457
8559
|
}
|
|
8458
8560
|
| undefined;
|
|
@@ -8476,6 +8578,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
8476
8578
|
radius: this.quality.ambientOcclusionRadius,
|
|
8477
8579
|
projScale: this.aoProjScale,
|
|
8478
8580
|
invProjection: this.aoInvProjection as Float32Array,
|
|
8581
|
+
fade: this.aoFade,
|
|
8479
8582
|
offset: this.aoOffset,
|
|
8480
8583
|
};
|
|
8481
8584
|
}
|
|
@@ -9010,7 +9113,7 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
9010
9113
|
/* Nor a projection: maps follow the mesh's coordinates until a material asks otherwise. */
|
|
9011
9114
|
this.projection.fill(0);
|
|
9012
9115
|
/* Nor light through from behind. See `SurfaceMaterial.diffuseTransmission`. */
|
|
9013
|
-
this.
|
|
9116
|
+
resolveTransmission(null, this.transmission);
|
|
9014
9117
|
/* Nor layers: one layer until a material asks for more. */
|
|
9015
9118
|
this.layerFloats.fill(0);
|
|
9016
9119
|
this.overlayMaps = null;
|
|
@@ -9191,8 +9294,15 @@ export class WebGL2Renderer implements RendererApi {
|
|
|
9191
9294
|
`bindSeeThrough` for the four numbers in the one vector. */
|
|
9192
9295
|
gl.uniform4f(u['uSeeThrough'] ?? null, 0, 0, 0, 0);
|
|
9193
9296
|
gl.uniform4f(u['uRefractTint'] ?? null, 1, 1, 1, 1);
|
|
9194
|
-
/*
|
|
9195
|
-
|
|
9297
|
+
/* No light through from behind: no material at a pass's start. See `writeTransmission`. */
|
|
9298
|
+
const through = this.transmission;
|
|
9299
|
+
gl.uniform4f(
|
|
9300
|
+
u['uGlassTint'] ?? null,
|
|
9301
|
+
through[0] ?? -1,
|
|
9302
|
+
through[1] ?? -1,
|
|
9303
|
+
through[2] ?? -1,
|
|
9304
|
+
through[3] ?? 0,
|
|
9305
|
+
);
|
|
9196
9306
|
gl.uniform3fv(u['uDirectionalDir'] ?? null, env.directionalDir);
|
|
9197
9307
|
gl.uniform3fv(u['uDirectionalColor'] ?? null, env.directionalColor);
|
|
9198
9308
|
gl.uniform3fv(u['uAmbient'] ?? null, env.ambient);
|