@babylonjs-toolkit/next 9.11.1 → 9.12.101
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/lib/scenemanager.d.ts +144 -42
- package/lib/scenemanager.d.ts.map +1 -1
- package/lib/scenemanager.js +1337 -370
- package/package.json +14 -13
package/lib/scenemanager.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Light } from '@babylonjs/core/Lights/light';
|
|
|
9
9
|
import { Vector3, Quaternion, Vector2, Vector4, Matrix, TmpVectors } from '@babylonjs/core/Maths/math.vector';
|
|
10
10
|
import { FreeCamera } from '@babylonjs/core/Cameras/freeCamera';
|
|
11
11
|
import { Engine } from '@babylonjs/core/Engines/engine';
|
|
12
|
-
import { SphericalPolynomial, HDRCubeTexture, EXRCubeTexture, SphericalHarmonics, Constants, PostProcess, BlurPostProcess, DefaultRenderingPipeline, SSAORenderingPipeline, SSRRenderingPipeline, MotionBlurPostProcess } from '@babylonjs/core';
|
|
12
|
+
import { SphericalPolynomial, HDRCubeTexture, EXRCubeTexture, SphericalHarmonics, Constants, SerializationHelper, PostProcess, BlurPostProcess, DefaultRenderingPipeline, SSAORenderingPipeline, SSRRenderingPipeline, MotionBlurPostProcess } from '@babylonjs/core';
|
|
13
13
|
import { Material } from '@babylonjs/core/Materials/material';
|
|
14
14
|
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
|
|
15
15
|
import { CreateNavigationPluginAsync } from '@babylonjs/addons';
|
|
@@ -53,7 +53,7 @@ import { ShaderMaterial } from '@babylonjs/core/Materials/shaderMaterial';
|
|
|
53
53
|
import { MultiMaterial } from '@babylonjs/core/Materials/multiMaterial';
|
|
54
54
|
import { HemisphericLight } from '@babylonjs/core/Lights/hemisphericLight';
|
|
55
55
|
import { MaterialPluginBase } from '@babylonjs/core/Materials/materialPluginBase';
|
|
56
|
-
import { ShaderLanguage,
|
|
56
|
+
import { ShaderLanguage, RawTexture, ShadowDepthWrapper, ImageProcessingConfiguration, ColorCurves, RawTexture2DArray } from '@babylonjs/core/Materials';
|
|
57
57
|
import { SpotLight } from '@babylonjs/core/Lights/spotLight';
|
|
58
58
|
import { UniversalCamera } from '@babylonjs/core/Cameras/universalCamera';
|
|
59
59
|
import { DirectionalLight } from '@babylonjs/core/Lights/directionalLight';
|
|
@@ -98,7 +98,7 @@ import { ShadowOnlyMaterial } from '@babylonjs/materials/shadowOnly/shadowOnlyMa
|
|
|
98
98
|
import { SkyMaterial } from '@babylonjs/materials/sky/skyMaterial';
|
|
99
99
|
import { WaterMaterial } from '@babylonjs/materials/water/waterMaterial';
|
|
100
100
|
export class SceneManager {
|
|
101
|
-
static get Version() { return "9.
|
|
101
|
+
static get Version() { return "9.12.101 - R1"; }
|
|
102
102
|
static get Copyright() { return "All rights reserved (c) 2024 Mackey Kinard"; }
|
|
103
103
|
static GetEngine(scene) {
|
|
104
104
|
let result = null;
|
|
@@ -2824,9 +2824,15 @@ export class ScriptComponent {
|
|
|
2824
2824
|
return SceneManager.GetSkinnedMesh(this.transform);
|
|
2825
2825
|
}
|
|
2826
2826
|
getTransformMesh() {
|
|
2827
|
+
const atransform = this.transform;
|
|
2828
|
+
if (atransform._skinnedMesh)
|
|
2829
|
+
return atransform._skinnedMesh;
|
|
2827
2830
|
return (this._transform instanceof Mesh) ? this._transform : null;
|
|
2828
2831
|
}
|
|
2829
2832
|
getAbstractMesh() {
|
|
2833
|
+
const atransform = this.transform;
|
|
2834
|
+
if (atransform._skinnedMesh)
|
|
2835
|
+
return atransform._skinnedMesh;
|
|
2830
2836
|
return (this._transform instanceof AbstractMesh) ? this._transform : null;
|
|
2831
2837
|
}
|
|
2832
2838
|
getInstancedMesh() {
|
|
@@ -3787,6 +3793,31 @@ export var MaterialAlphaMode;
|
|
|
3787
3793
|
export class CubeTextureLoader {
|
|
3788
3794
|
}
|
|
3789
3795
|
export class CVTOOLS_unity_metadata {
|
|
3796
|
+
static SuppressReflectionProbeDiffuse(texture) {
|
|
3797
|
+
if (texture == null)
|
|
3798
|
+
return;
|
|
3799
|
+
texture.sphericalPolynomial = null;
|
|
3800
|
+
const internal = texture._texture;
|
|
3801
|
+
if (internal != null) {
|
|
3802
|
+
internal._sphericalPolynomial = null;
|
|
3803
|
+
internal._sphericalPolynomialComputed = true;
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
static ApplyGlobalReflectionProbeDiffuse(texture, scene, createPolynomialsFromFaces = false) {
|
|
3807
|
+
if (texture == null || createPolynomialsFromFaces === true)
|
|
3808
|
+
return;
|
|
3809
|
+
const sp = (scene != null) ? SceneManager.GetImageBasedLighting(scene) : null;
|
|
3810
|
+
if (sp == null) {
|
|
3811
|
+
CVTOOLS_unity_metadata.SuppressReflectionProbeDiffuse(texture);
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
texture.sphericalPolynomial = sp;
|
|
3815
|
+
const internal = texture._texture;
|
|
3816
|
+
if (internal != null) {
|
|
3817
|
+
internal._sphericalPolynomial = sp;
|
|
3818
|
+
internal._sphericalPolynomialComputed = true;
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3790
3821
|
constructor(loader) {
|
|
3791
3822
|
this.name = SceneManager.CVTOOLS_NAME;
|
|
3792
3823
|
this.enabled = false;
|
|
@@ -3972,7 +4003,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
3972
4003
|
finishComplete() {
|
|
3973
4004
|
if (this._parseScene === true) {
|
|
3974
4005
|
if (this._rootUrl != null && this._rootUrl.toLowerCase().indexOf("repo.babylontoolkit.com") >= 0) {
|
|
3975
|
-
this.
|
|
4006
|
+
this.applyRepoWatermark(this._babylonScene);
|
|
3976
4007
|
}
|
|
3977
4008
|
this.startParsing();
|
|
3978
4009
|
SceneManager.RenderLoopReady = true;
|
|
@@ -4144,6 +4175,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4144
4175
|
}
|
|
4145
4176
|
}
|
|
4146
4177
|
}
|
|
4178
|
+
const createPolynomialsFromFaces = scene.extras?.metadata?.createpolynomials ?? false;
|
|
4147
4179
|
if (this._reflectionMap != null && this._reflectionCache != null) {
|
|
4148
4180
|
let tindex = 0;
|
|
4149
4181
|
for (const key in this._reflectionMap) {
|
|
@@ -4163,6 +4195,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4163
4195
|
if (cachedCubeTexture != null) {
|
|
4164
4196
|
if (ctx.material != null && Utilities.HasOwnProperty(ctx.material, "reflectionTexture")) {
|
|
4165
4197
|
ctx.material.reflectionTexture = cachedCubeTexture;
|
|
4198
|
+
CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(cachedCubeTexture, this._babylonScene, createPolynomialsFromFaces);
|
|
4166
4199
|
}
|
|
4167
4200
|
}
|
|
4168
4201
|
else {
|
|
@@ -4175,8 +4208,8 @@ export class CVTOOLS_unity_metadata {
|
|
|
4175
4208
|
buffer: bytes,
|
|
4176
4209
|
prefiltered: true,
|
|
4177
4210
|
forcedExtension: newCubeExtension,
|
|
4178
|
-
createPolynomials:
|
|
4179
|
-
onLoad: () => { },
|
|
4211
|
+
createPolynomials: createPolynomialsFromFaces,
|
|
4212
|
+
onLoad: () => { CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(newCubeTexture, this._babylonScene, createPolynomialsFromFaces); },
|
|
4180
4213
|
onError: (msg, ex) => console.error(msg, ex),
|
|
4181
4214
|
});
|
|
4182
4215
|
newCubeTexture.name = ctx.name;
|
|
@@ -4189,6 +4222,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4189
4222
|
this._reflectionCache[ctx.mapkey] = newCubeTexture;
|
|
4190
4223
|
if (ctx.material != null && Utilities.HasOwnProperty(ctx.material, "reflectionTexture")) {
|
|
4191
4224
|
ctx.material.reflectionTexture = newCubeTexture;
|
|
4225
|
+
CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(newCubeTexture, this._babylonScene, createPolynomialsFromFaces);
|
|
4192
4226
|
}
|
|
4193
4227
|
}
|
|
4194
4228
|
}
|
|
@@ -4578,7 +4612,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4578
4612
|
if (metadata.ambientlighting != null && metadata.ambientlighting === 1) {
|
|
4579
4613
|
const ascene = babylonScene;
|
|
4580
4614
|
if (ascene._AmbientLight == null) {
|
|
4581
|
-
ascene._AmbientLight = new HemisphericLight("Ambient
|
|
4615
|
+
ascene._AmbientLight = new HemisphericLight("Ambient Light", new Vector3(0, 1, 0), babylonScene);
|
|
4582
4616
|
ascene._AmbientLight.falloffType = Light.FALLOFF_STANDARD;
|
|
4583
4617
|
switch (ambientLightmapMode) {
|
|
4584
4618
|
case 2:
|
|
@@ -4593,28 +4627,19 @@ export class CVTOOLS_unity_metadata {
|
|
|
4593
4627
|
}
|
|
4594
4628
|
}
|
|
4595
4629
|
if (ascene._AmbientLight != null) {
|
|
4596
|
-
|
|
4630
|
+
ascene._AmbientLight.diffuse = (metadata.ambientskycolor != null) ? Utilities.ParseColor3(metadata.ambientskycolor, Color3.Gray()) : Color3.Gray();
|
|
4631
|
+
ascene._AmbientLight.specular = (metadata.ambientspecularcolor != null) ? Color3.Black() : Color3.Black();
|
|
4632
|
+
ascene._AmbientLight.groundColor = (metadata.ambientgroundcolor != null) ? Utilities.ParseColor3(metadata.ambientgroundcolor, Color3.Gray()) : Color3.Gray();
|
|
4633
|
+
ascene._AmbientLight.intensity = (metadata.ambientlightintensity != null) ? metadata.ambientlightintensity : 1.0;
|
|
4634
|
+
if (SceneManager.GetImageBasedLighting(babylonScene) != null) {
|
|
4597
4635
|
ascene._AmbientLight.name = "Ambient Blacklight";
|
|
4598
4636
|
ascene._AmbientLight.diffuse = Color3.Black();
|
|
4599
4637
|
ascene._AmbientLight.specular = Color3.Black();
|
|
4600
4638
|
ascene._AmbientLight.groundColor = Color3.Black();
|
|
4601
|
-
|
|
4602
|
-
ascene._AmbientLight.intensity = metadata.ambientlightintensity;
|
|
4603
|
-
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4604
|
-
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4605
|
-
}
|
|
4606
|
-
else {
|
|
4607
|
-
if (metadata.ambientskycolor != null)
|
|
4608
|
-
ascene._AmbientLight.diffuse = Utilities.ParseColor3(metadata.ambientskycolor, Color3.Gray());
|
|
4609
|
-
if (metadata.ambientspecularcolor != null)
|
|
4610
|
-
ascene._AmbientLight.specular = Utilities.ParseColor3(metadata.ambientspecularcolor, Color3.Black());
|
|
4611
|
-
if (metadata.ambientgroundcolor != null)
|
|
4612
|
-
ascene._AmbientLight.groundColor = Utilities.ParseColor3(metadata.ambientgroundcolor, Color3.Gray());
|
|
4613
|
-
if (metadata.ambientlightintensity != null)
|
|
4614
|
-
ascene._AmbientLight.intensity = metadata.ambientlightintensity;
|
|
4615
|
-
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4616
|
-
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4639
|
+
ascene._AmbientLight.intensity = 1.0;
|
|
4617
4640
|
}
|
|
4641
|
+
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4642
|
+
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4618
4643
|
}
|
|
4619
4644
|
}
|
|
4620
4645
|
if (metadata.fogmode != null) {
|
|
@@ -4835,8 +4860,8 @@ export class CVTOOLS_unity_metadata {
|
|
|
4835
4860
|
const diffuseIbl = Scalar.Clamp(ibl, 0.0, IBL_MAX);
|
|
4836
4861
|
const specIbl = Scalar.Clamp(derivedRefl, 0.0, LEVEL_MAX);
|
|
4837
4862
|
const hasDiffuseIbl = Array.isArray(environment.sh) && environment.sh.length === 27;
|
|
4838
|
-
const
|
|
4839
|
-
if (
|
|
4863
|
+
const useUnitySH = (mode === 0 && hasDiffuseIbl === true);
|
|
4864
|
+
if (useUnitySH)
|
|
4840
4865
|
this.generateSphericalHarmonics(babylonScene, environment.sh, diffuseIbl);
|
|
4841
4866
|
if (envinfo != null && envinfo !== "") {
|
|
4842
4867
|
try {
|
|
@@ -4859,32 +4884,25 @@ export class CVTOOLS_unity_metadata {
|
|
|
4859
4884
|
});
|
|
4860
4885
|
babylonScene.environmentTexture = newCubeTexture;
|
|
4861
4886
|
babylonScene.environmentTexture.name = ("assets/" + envinfo.name);
|
|
4862
|
-
babylonScene.environmentTexture.level =
|
|
4863
|
-
if (
|
|
4864
|
-
|
|
4887
|
+
babylonScene.environmentTexture.level = useUnitySH ? (specIbl * scale) : specIbl;
|
|
4888
|
+
if (useUnitySH) {
|
|
4889
|
+
const applyUnitySH = () => {
|
|
4865
4890
|
const sp = SceneManager.GetImageBasedLighting(babylonScene);
|
|
4866
4891
|
if (sp != null) {
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4892
|
+
const envTex = babylonScene.environmentTexture;
|
|
4893
|
+
envTex.sphericalPolynomial = sp;
|
|
4894
|
+
const internal = envTex._texture;
|
|
4895
|
+
if (internal != null) {
|
|
4896
|
+
internal._sphericalPolynomial = sp;
|
|
4897
|
+
internal._sphericalPolynomialComputed = true;
|
|
4871
4898
|
}
|
|
4872
4899
|
babylonScene.markAllMaterialsAsDirty(Material.AllDirtyFlag);
|
|
4873
4900
|
}
|
|
4874
|
-
}
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
if (mode === 0) {
|
|
4880
|
-
babylonScene.environmentTexture.sphericalPolynomial = sp;
|
|
4881
|
-
}
|
|
4882
|
-
else {
|
|
4883
|
-
}
|
|
4884
|
-
babylonScene.markAllMaterialsAsDirty(Material.AllDirtyFlag);
|
|
4885
|
-
}
|
|
4886
|
-
});
|
|
4887
|
-
}
|
|
4901
|
+
};
|
|
4902
|
+
if (newCubeTexture.isReady())
|
|
4903
|
+
applyUnitySH();
|
|
4904
|
+
else
|
|
4905
|
+
newCubeTexture.onLoadObservable.addOnce(applyUnitySH);
|
|
4888
4906
|
}
|
|
4889
4907
|
}
|
|
4890
4908
|
else {
|
|
@@ -5332,7 +5350,43 @@ export class CVTOOLS_unity_metadata {
|
|
|
5332
5350
|
}
|
|
5333
5351
|
}
|
|
5334
5352
|
}
|
|
5335
|
-
|
|
5353
|
+
_parseUniformAndSamplerProperties(context, material, sourceMaterial) {
|
|
5354
|
+
const commonConstant = (material.extras != null && material.extras.metadata != null) ? material.extras.metadata : null;
|
|
5355
|
+
if (commonConstant != null) {
|
|
5356
|
+
if (Utilities.HasOwnProperty(sourceMaterial, "universalMaterial")) {
|
|
5357
|
+
const universalMaterial = sourceMaterial;
|
|
5358
|
+
if (commonConstant.customTextures) {
|
|
5359
|
+
for (const tkey in commonConstant.customTextures) {
|
|
5360
|
+
const tvalue = commonConstant.customTextures[tkey];
|
|
5361
|
+
if (tvalue != null)
|
|
5362
|
+
universalMaterial.checkSampler(tkey);
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5365
|
+
if (commonConstant.customVectors) {
|
|
5366
|
+
for (const vkey in commonConstant.customVectors) {
|
|
5367
|
+
const vvalue = commonConstant.customVectors[vkey];
|
|
5368
|
+
if (vvalue != null)
|
|
5369
|
+
universalMaterial.checkUniform(vkey, "vec4", Vector4.FromArray(vvalue));
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
if (commonConstant.customColors) {
|
|
5373
|
+
for (const ckey in commonConstant.customColors) {
|
|
5374
|
+
const cvalue = commonConstant.customColors[ckey];
|
|
5375
|
+
if (cvalue != null)
|
|
5376
|
+
universalMaterial.checkUniform(ckey, "vec4", Vector4.FromArray(cvalue));
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
if (commonConstant.customFloats) {
|
|
5380
|
+
for (const fkey in commonConstant.customFloats) {
|
|
5381
|
+
const fvalue = commonConstant.customFloats[fkey];
|
|
5382
|
+
if (fvalue != null)
|
|
5383
|
+
universalMaterial.checkUniform(fkey, "float", fvalue);
|
|
5384
|
+
}
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
applyRepoWatermark(scene) {
|
|
5336
5390
|
const canvas = scene.getEngine().getRenderingCanvas();
|
|
5337
5391
|
if (canvas == null)
|
|
5338
5392
|
return;
|
|
@@ -5362,8 +5416,9 @@ export class CVTOOLS_unity_metadata {
|
|
|
5362
5416
|
el.title = WM_TITLE;
|
|
5363
5417
|
el.style.cssText = [
|
|
5364
5418
|
"position:absolute",
|
|
5365
|
-
"bottom:
|
|
5366
|
-
"left:
|
|
5419
|
+
"bottom:6px",
|
|
5420
|
+
"left:50%",
|
|
5421
|
+
"transform:translateX(-50%)",
|
|
5367
5422
|
"color:rgba(0,204,0,0.5)",
|
|
5368
5423
|
"font:13px/1 Arial,sans-serif",
|
|
5369
5424
|
"pointer-events:auto",
|
|
@@ -5413,6 +5468,10 @@ export class CVTOOLS_unity_metadata {
|
|
|
5413
5468
|
s.visibility = "visible";
|
|
5414
5469
|
s.opacity = "";
|
|
5415
5470
|
}
|
|
5471
|
+
if (s.left !== "50%")
|
|
5472
|
+
s.left = "50%";
|
|
5473
|
+
if (s.transform !== "translateX(-50%)")
|
|
5474
|
+
s.transform = "translateX(-50%)";
|
|
5416
5475
|
}
|
|
5417
5476
|
});
|
|
5418
5477
|
scene.onDisposeObservable.addOnce(() => {
|
|
@@ -5433,42 +5492,6 @@ export class CVTOOLS_unity_metadata {
|
|
|
5433
5492
|
}
|
|
5434
5493
|
});
|
|
5435
5494
|
}
|
|
5436
|
-
_parseUniformAndSamplerProperties(context, material, sourceMaterial) {
|
|
5437
|
-
const commonConstant = (material.extras != null && material.extras.metadata != null) ? material.extras.metadata : null;
|
|
5438
|
-
if (commonConstant != null) {
|
|
5439
|
-
if (Utilities.HasOwnProperty(sourceMaterial, "universalMaterial")) {
|
|
5440
|
-
const universalMaterial = sourceMaterial;
|
|
5441
|
-
if (commonConstant.customTextures) {
|
|
5442
|
-
for (const tkey in commonConstant.customTextures) {
|
|
5443
|
-
const tvalue = commonConstant.customTextures[tkey];
|
|
5444
|
-
if (tvalue != null)
|
|
5445
|
-
universalMaterial.checkSampler(tkey);
|
|
5446
|
-
}
|
|
5447
|
-
}
|
|
5448
|
-
if (commonConstant.customVectors) {
|
|
5449
|
-
for (const vkey in commonConstant.customVectors) {
|
|
5450
|
-
const vvalue = commonConstant.customVectors[vkey];
|
|
5451
|
-
if (vvalue != null)
|
|
5452
|
-
universalMaterial.checkUniform(vkey, "vec4", Vector4.FromArray(vvalue));
|
|
5453
|
-
}
|
|
5454
|
-
}
|
|
5455
|
-
if (commonConstant.customColors) {
|
|
5456
|
-
for (const ckey in commonConstant.customColors) {
|
|
5457
|
-
const cvalue = commonConstant.customColors[ckey];
|
|
5458
|
-
if (cvalue != null)
|
|
5459
|
-
universalMaterial.checkUniform(ckey, "vec4", Vector4.FromArray(cvalue));
|
|
5460
|
-
}
|
|
5461
|
-
}
|
|
5462
|
-
if (commonConstant.customFloats) {
|
|
5463
|
-
for (const fkey in commonConstant.customFloats) {
|
|
5464
|
-
const fvalue = commonConstant.customFloats[fkey];
|
|
5465
|
-
if (fvalue != null)
|
|
5466
|
-
universalMaterial.checkUniform(fkey, "float", fvalue);
|
|
5467
|
-
}
|
|
5468
|
-
}
|
|
5469
|
-
}
|
|
5470
|
-
}
|
|
5471
|
-
}
|
|
5472
5495
|
}
|
|
5473
5496
|
CVTOOLS_unity_metadata.IBL_TINY_VALUE = 0.001;
|
|
5474
5497
|
CVTOOLS_unity_metadata.IBL_SPEC_FACTOR = 1.0;
|
|
@@ -5520,10 +5543,18 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5520
5543
|
this.shader = null;
|
|
5521
5544
|
this.plugin = null;
|
|
5522
5545
|
this._unityLightingPlugin = null;
|
|
5546
|
+
this._skinArray = false;
|
|
5547
|
+
this._skinArrayNormal = false;
|
|
5548
|
+
this._skinArrayMetalRough = false;
|
|
5549
|
+
this._skinArrayEmissive = false;
|
|
5550
|
+
this._skinLayerUniform = false;
|
|
5551
|
+
this._skinArraySwitchingPlugin = null;
|
|
5523
5552
|
this.shader = "CustomShaderMaterial";
|
|
5524
5553
|
this.addFloatUniform("tkIblDiffuseScale", 1.0);
|
|
5525
5554
|
this.addFloatUniform("tkIblSpecularScale", 1.0);
|
|
5555
|
+
this.addFloatUniform("tkSkinLayerUni", 0.0);
|
|
5526
5556
|
this._unityLightingPlugin = new UnityStyleLightingPlugin(this, this.shader);
|
|
5557
|
+
this._skinArraySwitchingPlugin = new SkinArraySwitchingPlugin(this);
|
|
5527
5558
|
}
|
|
5528
5559
|
initMaterial() {
|
|
5529
5560
|
if (this["awake"])
|
|
@@ -5557,6 +5588,108 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5557
5588
|
this.plugin?.markAllDefinesAsDirty();
|
|
5558
5589
|
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5559
5590
|
}
|
|
5591
|
+
enableSkinArray(layerUniform = false) {
|
|
5592
|
+
this._skinArray = true;
|
|
5593
|
+
this._skinLayerUniform = layerUniform;
|
|
5594
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5595
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5596
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5597
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5598
|
+
return this;
|
|
5599
|
+
}
|
|
5600
|
+
setSkinLayer(layer) {
|
|
5601
|
+
this._skinLayerUniform = true;
|
|
5602
|
+
this.setFloatValue("tkSkinLayerUni", Math.max(0, Math.floor(layer)));
|
|
5603
|
+
return this;
|
|
5604
|
+
}
|
|
5605
|
+
enableSkinArrayNormal(enabled = true) {
|
|
5606
|
+
this._skinArrayNormal = enabled;
|
|
5607
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5608
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5609
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5610
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5611
|
+
return this;
|
|
5612
|
+
}
|
|
5613
|
+
enableSkinArrayMetalRough(enabled = true) {
|
|
5614
|
+
this._skinArrayMetalRough = enabled;
|
|
5615
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5616
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5617
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5618
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5619
|
+
return this;
|
|
5620
|
+
}
|
|
5621
|
+
enableSkinArrayEmissive(enabled = true) {
|
|
5622
|
+
this._skinArrayEmissive = enabled;
|
|
5623
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5624
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5625
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5626
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5627
|
+
return this;
|
|
5628
|
+
}
|
|
5629
|
+
setSkinArrayLayerMode(uniform) {
|
|
5630
|
+
this._skinLayerUniform = uniform;
|
|
5631
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5632
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5633
|
+
return this;
|
|
5634
|
+
}
|
|
5635
|
+
addTextureArrayUniform(name, texture) {
|
|
5636
|
+
if (this._samplers.indexOf(name) === -1)
|
|
5637
|
+
this._samplers.push(name);
|
|
5638
|
+
this._textures[name] = texture;
|
|
5639
|
+
this.markTextureAsRaw(name);
|
|
5640
|
+
return this;
|
|
5641
|
+
}
|
|
5642
|
+
get skinArray() { return this._skinArray; }
|
|
5643
|
+
get skinArrayNormal() { return this._skinArrayNormal; }
|
|
5644
|
+
get skinArrayMetalRough() { return this._skinArrayMetalRough; }
|
|
5645
|
+
get skinArrayEmissive() { return this._skinArrayEmissive; }
|
|
5646
|
+
get skinArrayActive() {
|
|
5647
|
+
return this._skinArray || this._skinArrayNormal || this._skinArrayMetalRough || this._skinArrayEmissive;
|
|
5648
|
+
}
|
|
5649
|
+
get skinLayerUniform() { return this._skinLayerUniform; }
|
|
5650
|
+
clone(name, cloneTexturesOnlyOnce = true, rootUrl = "") {
|
|
5651
|
+
const scene = this.getScene();
|
|
5652
|
+
const ctor = this.constructor;
|
|
5653
|
+
const result = SerializationHelper.Clone(() => new ctor(name, scene), this, { cloneTexturesOnlyOnce });
|
|
5654
|
+
if (result == null)
|
|
5655
|
+
return result;
|
|
5656
|
+
result.id = name;
|
|
5657
|
+
result.name = name;
|
|
5658
|
+
if (this.stencil && result.stencil)
|
|
5659
|
+
this.stencil.copyTo(result.stencil);
|
|
5660
|
+
this.copyCustomStateTo(result);
|
|
5661
|
+
return result;
|
|
5662
|
+
}
|
|
5663
|
+
copyCustomStateTo(result) {
|
|
5664
|
+
result.universalMaterial = this.universalMaterial;
|
|
5665
|
+
result._defines = Object.assign({}, this._defines);
|
|
5666
|
+
result._uniforms = this._uniforms.slice();
|
|
5667
|
+
result._samplers = this._samplers.slice();
|
|
5668
|
+
result._attributes = this._attributes.slice();
|
|
5669
|
+
result._ubos = (this._ubos != null) ? this._ubos.map((u) => ({ name: u.name, size: u.size, type: u.type, arraySize: u.arraySize })) : null;
|
|
5670
|
+
result._textures = Object.assign({}, this._textures);
|
|
5671
|
+
result._noMatrixTextures = (this._noMatrixTextures != null) ? new Set(this._noMatrixTextures) : null;
|
|
5672
|
+
result._vectors4 = {};
|
|
5673
|
+
for (const n in this._vectors4)
|
|
5674
|
+
result._vectors4[n] = this._vectors4[n].clone();
|
|
5675
|
+
result._vectors3 = {};
|
|
5676
|
+
for (const n in this._vectors3)
|
|
5677
|
+
result._vectors3[n] = this._vectors3[n].clone();
|
|
5678
|
+
result._vectors2 = {};
|
|
5679
|
+
for (const n in this._vectors2)
|
|
5680
|
+
result._vectors2[n] = this._vectors2[n].clone();
|
|
5681
|
+
result._floats = Object.assign({}, this._floats);
|
|
5682
|
+
result._bools = Object.assign({}, this._bools);
|
|
5683
|
+
result._skinArray = this._skinArray;
|
|
5684
|
+
result._skinArrayNormal = this._skinArrayNormal;
|
|
5685
|
+
result._skinArrayMetalRough = this._skinArrayMetalRough;
|
|
5686
|
+
result._skinArrayEmissive = this._skinArrayEmissive;
|
|
5687
|
+
result._skinLayerUniform = this._skinLayerUniform;
|
|
5688
|
+
result.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5689
|
+
result.plugin?.markAllDefinesAsDirty();
|
|
5690
|
+
result._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5691
|
+
result._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5692
|
+
}
|
|
5560
5693
|
addTextureUniform(name, texture) {
|
|
5561
5694
|
this.checkSampler(name, texture);
|
|
5562
5695
|
this._textures[name] = texture;
|
|
@@ -5999,6 +6132,301 @@ export class UnityStyleLightingPlugin extends CustomShaderMaterialPlugin {
|
|
|
5999
6132
|
this.getCustomShaderMaterial().updateCustomBindings(uniformBuffer);
|
|
6000
6133
|
}
|
|
6001
6134
|
}
|
|
6135
|
+
export class SkinArraySwitchingPlugin extends CustomShaderMaterialPlugin {
|
|
6136
|
+
constructor(material) {
|
|
6137
|
+
super(material, "SkinArraySwitchingPlugin", 21, { TOOLKIT_SKIN_ARRAY: false, TOOLKIT_SKIN_LAYER_UNIFORM: false, TOOLKIT_SKIN_ARRAY_ALBEDO: false, TOOLKIT_SKIN_ARRAY_NORMAL: false, TOOLKIT_SKIN_ARRAY_MR: false, TOOLKIT_SKIN_ARRAY_EMISSIVE: false }, true, true, false);
|
|
6138
|
+
}
|
|
6139
|
+
isCompatible(shaderLanguage) {
|
|
6140
|
+
return (shaderLanguage === ShaderLanguage.WGSL || shaderLanguage === ShaderLanguage.GLSL);
|
|
6141
|
+
}
|
|
6142
|
+
getClassName() {
|
|
6143
|
+
return "SkinArraySwitchingPlugin";
|
|
6144
|
+
}
|
|
6145
|
+
getAttributes(attributes, scene, mesh) {
|
|
6146
|
+
const mat = this.getCustomShaderMaterial();
|
|
6147
|
+
if (!mat.skinArrayActive)
|
|
6148
|
+
return;
|
|
6149
|
+
if (mat.skinLayerUniform !== true && attributes.indexOf("tkSkinLayer") === -1)
|
|
6150
|
+
attributes.push("tkSkinLayer");
|
|
6151
|
+
}
|
|
6152
|
+
getSamplers(samplers) {
|
|
6153
|
+
const mat = this.getCustomShaderMaterial();
|
|
6154
|
+
if (!mat.skinArrayActive)
|
|
6155
|
+
return;
|
|
6156
|
+
const customSamplers = mat.getCustomSamplers();
|
|
6157
|
+
if (customSamplers != null) {
|
|
6158
|
+
for (const s of customSamplers)
|
|
6159
|
+
if (samplers.indexOf(s) === -1)
|
|
6160
|
+
samplers.push(s);
|
|
6161
|
+
}
|
|
6162
|
+
}
|
|
6163
|
+
prepareDefines(defines, scene, mesh) {
|
|
6164
|
+
const mat = this.getCustomShaderMaterial();
|
|
6165
|
+
defines.TOOLKIT_SKIN_ARRAY = !!mat.skinArrayActive;
|
|
6166
|
+
defines.TOOLKIT_SKIN_LAYER_UNIFORM = !!mat.skinLayerUniform;
|
|
6167
|
+
defines.TOOLKIT_SKIN_ARRAY_ALBEDO = !!mat.skinArray;
|
|
6168
|
+
defines.TOOLKIT_SKIN_ARRAY_NORMAL = !!mat.skinArrayNormal;
|
|
6169
|
+
defines.TOOLKIT_SKIN_ARRAY_MR = !!mat.skinArrayMetalRough;
|
|
6170
|
+
defines.TOOLKIT_SKIN_ARRAY_EMISSIVE = !!mat.skinArrayEmissive;
|
|
6171
|
+
}
|
|
6172
|
+
getCustomCode(shaderType, shaderLanguage) {
|
|
6173
|
+
const wgsl = (shaderLanguage === ShaderLanguage.WGSL);
|
|
6174
|
+
if (shaderType === "vertex") {
|
|
6175
|
+
if (wgsl) {
|
|
6176
|
+
return {
|
|
6177
|
+
CUSTOM_VERTEX_DEFINITIONS: this.getWGSLVertexDefinitions(),
|
|
6178
|
+
CUSTOM_VERTEX_MAIN_END: this.getWGSLVertexMainEnd()
|
|
6179
|
+
};
|
|
6180
|
+
}
|
|
6181
|
+
return {
|
|
6182
|
+
CUSTOM_VERTEX_DEFINITIONS: this.getGLSLVertexDefinitions(),
|
|
6183
|
+
CUSTOM_VERTEX_MAIN_END: this.getGLSLVertexMainEnd()
|
|
6184
|
+
};
|
|
6185
|
+
}
|
|
6186
|
+
if (shaderType === "fragment") {
|
|
6187
|
+
if (wgsl) {
|
|
6188
|
+
return {
|
|
6189
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getWGSLFragmentDefinitions(),
|
|
6190
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getWGSLAlbedoCode() + this.getWGSLMetalRoughSampleCode(),
|
|
6191
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getWGSLNormalCode(),
|
|
6192
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getWGSLMetalRoughApplyCode(),
|
|
6193
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getWGSLEmissiveCode()
|
|
6194
|
+
};
|
|
6195
|
+
}
|
|
6196
|
+
return {
|
|
6197
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getGLSLFragmentDefinitions(),
|
|
6198
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getGLSLAlbedoCode() + this.getGLSLMetalRoughSampleCode(),
|
|
6199
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getGLSLNormalCode(),
|
|
6200
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getGLSLMetalRoughApplyCode(),
|
|
6201
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getGLSLEmissiveCode()
|
|
6202
|
+
};
|
|
6203
|
+
}
|
|
6204
|
+
return null;
|
|
6205
|
+
}
|
|
6206
|
+
getGLSLVertexDefinitions() {
|
|
6207
|
+
return `
|
|
6208
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6209
|
+
#ifndef TOOLKIT_SKIN_V_DEFINED
|
|
6210
|
+
#define TOOLKIT_SKIN_V_DEFINED
|
|
6211
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6212
|
+
uniform float tkSkinLayerUni;
|
|
6213
|
+
#else
|
|
6214
|
+
attribute float tkSkinLayer;
|
|
6215
|
+
#endif
|
|
6216
|
+
varying float vSkinLayer;
|
|
6217
|
+
varying vec2 vSkinUV;
|
|
6218
|
+
#endif
|
|
6219
|
+
#endif
|
|
6220
|
+
`;
|
|
6221
|
+
}
|
|
6222
|
+
getGLSLVertexMainEnd() {
|
|
6223
|
+
return `
|
|
6224
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6225
|
+
#ifdef UV1
|
|
6226
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6227
|
+
vSkinLayer = tkSkinLayerUni;
|
|
6228
|
+
#else
|
|
6229
|
+
vSkinLayer = tkSkinLayer;
|
|
6230
|
+
#endif
|
|
6231
|
+
vSkinUV = uv;
|
|
6232
|
+
#else
|
|
6233
|
+
vSkinLayer = 0.0;
|
|
6234
|
+
vSkinUV = vec2(0.0);
|
|
6235
|
+
#endif
|
|
6236
|
+
#endif
|
|
6237
|
+
`;
|
|
6238
|
+
}
|
|
6239
|
+
getGLSLFragmentDefinitions() {
|
|
6240
|
+
return `
|
|
6241
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6242
|
+
#ifndef TOOLKIT_SKIN_F_DEFINED
|
|
6243
|
+
#define TOOLKIT_SKIN_F_DEFINED
|
|
6244
|
+
varying float vSkinLayer;
|
|
6245
|
+
varying vec2 vSkinUV;
|
|
6246
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6247
|
+
uniform sampler2DArray tkAlbedoArray;
|
|
6248
|
+
#endif
|
|
6249
|
+
#ifdef TOOLKIT_SKIN_ARRAY_NORMAL
|
|
6250
|
+
uniform sampler2DArray tkNormalArray;
|
|
6251
|
+
#endif
|
|
6252
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6253
|
+
uniform sampler2DArray tkMetalRoughArray;
|
|
6254
|
+
vec2 _tkMR;
|
|
6255
|
+
#endif
|
|
6256
|
+
#ifdef TOOLKIT_SKIN_ARRAY_EMISSIVE
|
|
6257
|
+
uniform sampler2DArray tkEmissiveArray;
|
|
6258
|
+
#endif
|
|
6259
|
+
#endif
|
|
6260
|
+
#endif
|
|
6261
|
+
`;
|
|
6262
|
+
}
|
|
6263
|
+
getGLSLAlbedoCode() {
|
|
6264
|
+
return `
|
|
6265
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6266
|
+
{
|
|
6267
|
+
float _tkLayer = floor(vSkinLayer + 0.5);
|
|
6268
|
+
vec4 _tkAlb = texture(tkAlbedoArray, vec3(vSkinUV, _tkLayer));
|
|
6269
|
+
#ifdef GAMMAALBEDO
|
|
6270
|
+
surfaceAlbedo = toLinearSpace(_tkAlb.rgb) * vAlbedoColor.rgb;
|
|
6271
|
+
#else
|
|
6272
|
+
surfaceAlbedo = _tkAlb.rgb * vAlbedoColor.rgb;
|
|
6273
|
+
#endif
|
|
6274
|
+
#ifdef ALPHATEST
|
|
6275
|
+
if (_tkAlb.a < alphaCutOff) discard;
|
|
6276
|
+
#endif
|
|
6277
|
+
}
|
|
6278
|
+
#endif
|
|
6279
|
+
`;
|
|
6280
|
+
}
|
|
6281
|
+
getGLSLNormalCode() {
|
|
6282
|
+
return `
|
|
6283
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
6284
|
+
{
|
|
6285
|
+
vec3 _tkNrmTexel = texture(tkNormalArray, vec3(vSkinUV, floor(vSkinLayer + 0.5))).xyz;
|
|
6286
|
+
normalW = perturbNormal(vTBN, _tkNrmTexel, vBumpInfos.y);
|
|
6287
|
+
}
|
|
6288
|
+
#endif
|
|
6289
|
+
`;
|
|
6290
|
+
}
|
|
6291
|
+
getGLSLMetalRoughSampleCode() {
|
|
6292
|
+
return `
|
|
6293
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6294
|
+
{
|
|
6295
|
+
vec4 _tkMRtexel = texture(tkMetalRoughArray, vec3(vSkinUV, floor(vSkinLayer + 0.5)));
|
|
6296
|
+
_tkMR = vec2(_tkMRtexel.b, _tkMRtexel.g);
|
|
6297
|
+
}
|
|
6298
|
+
#endif
|
|
6299
|
+
`;
|
|
6300
|
+
}
|
|
6301
|
+
getGLSLMetalRoughApplyCode() {
|
|
6302
|
+
return `
|
|
6303
|
+
#if defined(TOOLKIT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
6304
|
+
metallicRoughness.r = _tkMR.x;
|
|
6305
|
+
metallicRoughness.g = _tkMR.y;
|
|
6306
|
+
#endif
|
|
6307
|
+
`;
|
|
6308
|
+
}
|
|
6309
|
+
getGLSLEmissiveCode() {
|
|
6310
|
+
return `
|
|
6311
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_EMISSIVE)
|
|
6312
|
+
{
|
|
6313
|
+
vec3 _tkEmis = texture(tkEmissiveArray, vec3(vSkinUV, floor(vSkinLayer + 0.5))).rgb;
|
|
6314
|
+
finalEmissive = toLinearSpace(_tkEmis);
|
|
6315
|
+
}
|
|
6316
|
+
#endif
|
|
6317
|
+
`;
|
|
6318
|
+
}
|
|
6319
|
+
getWGSLVertexDefinitions() {
|
|
6320
|
+
return `
|
|
6321
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6322
|
+
#ifndef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6323
|
+
attribute tkSkinLayer: f32;
|
|
6324
|
+
#endif
|
|
6325
|
+
varying vSkinLayer: f32;
|
|
6326
|
+
varying vSkinUV: vec2<f32>;
|
|
6327
|
+
#endif
|
|
6328
|
+
`;
|
|
6329
|
+
}
|
|
6330
|
+
getWGSLVertexMainEnd() {
|
|
6331
|
+
return `
|
|
6332
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6333
|
+
#ifdef UV1
|
|
6334
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6335
|
+
vertexOutputs.vSkinLayer = uniforms.tkSkinLayerUni;
|
|
6336
|
+
#else
|
|
6337
|
+
vertexOutputs.vSkinLayer = vertexInputs.tkSkinLayer;
|
|
6338
|
+
#endif
|
|
6339
|
+
vertexOutputs.vSkinUV = vertexInputs.uv;
|
|
6340
|
+
#else
|
|
6341
|
+
vertexOutputs.vSkinLayer = 0.0;
|
|
6342
|
+
vertexOutputs.vSkinUV = vec2f(0.0);
|
|
6343
|
+
#endif
|
|
6344
|
+
#endif
|
|
6345
|
+
`;
|
|
6346
|
+
}
|
|
6347
|
+
getWGSLFragmentDefinitions() {
|
|
6348
|
+
return `
|
|
6349
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6350
|
+
varying vSkinLayer: f32;
|
|
6351
|
+
varying vSkinUV: vec2<f32>;
|
|
6352
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6353
|
+
var tkAlbedoArray: texture_2d_array<f32>;
|
|
6354
|
+
var tkAlbedoArraySampler: sampler;
|
|
6355
|
+
#endif
|
|
6356
|
+
#ifdef TOOLKIT_SKIN_ARRAY_NORMAL
|
|
6357
|
+
var tkNormalArray: texture_2d_array<f32>;
|
|
6358
|
+
var tkNormalArraySampler: sampler;
|
|
6359
|
+
#endif
|
|
6360
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6361
|
+
var tkMetalRoughArray: texture_2d_array<f32>;
|
|
6362
|
+
var tkMetalRoughArraySampler: sampler;
|
|
6363
|
+
var<private> _tkMR: vec2<f32>;
|
|
6364
|
+
#endif
|
|
6365
|
+
#ifdef TOOLKIT_SKIN_ARRAY_EMISSIVE
|
|
6366
|
+
var tkEmissiveArray: texture_2d_array<f32>;
|
|
6367
|
+
var tkEmissiveArraySampler: sampler;
|
|
6368
|
+
#endif
|
|
6369
|
+
#endif
|
|
6370
|
+
`;
|
|
6371
|
+
}
|
|
6372
|
+
getWGSLAlbedoCode() {
|
|
6373
|
+
return `
|
|
6374
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6375
|
+
{
|
|
6376
|
+
let _tkLayer = i32(fragmentInputs.vSkinLayer + 0.5);
|
|
6377
|
+
let _tkAlb = textureSample(tkAlbedoArray, tkAlbedoArraySampler, fragmentInputs.vSkinUV, _tkLayer);
|
|
6378
|
+
#ifdef GAMMAALBEDO
|
|
6379
|
+
surfaceAlbedo = toLinearSpaceVec3(_tkAlb.rgb) * vAlbedoColor.rgb;
|
|
6380
|
+
#else
|
|
6381
|
+
surfaceAlbedo = _tkAlb.rgb * vAlbedoColor.rgb;
|
|
6382
|
+
#endif
|
|
6383
|
+
#ifdef ALPHATEST
|
|
6384
|
+
if (_tkAlb.a < alphaCutOff) { discard; }
|
|
6385
|
+
#endif
|
|
6386
|
+
}
|
|
6387
|
+
#endif
|
|
6388
|
+
`;
|
|
6389
|
+
}
|
|
6390
|
+
getWGSLNormalCode() {
|
|
6391
|
+
return `
|
|
6392
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
6393
|
+
{
|
|
6394
|
+
let _tkNrmTexel = textureSample(tkNormalArray, tkNormalArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5)).rgb;
|
|
6395
|
+
let _tkNrmTBN = mat3x3<f32>(fragmentInputs.vTBN0, fragmentInputs.vTBN1, fragmentInputs.vTBN2);
|
|
6396
|
+
normalW = perturbNormal(_tkNrmTBN, _tkNrmTexel, uniforms.vBumpInfos.y);
|
|
6397
|
+
}
|
|
6398
|
+
#endif
|
|
6399
|
+
`;
|
|
6400
|
+
}
|
|
6401
|
+
getWGSLMetalRoughSampleCode() {
|
|
6402
|
+
return `
|
|
6403
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6404
|
+
{
|
|
6405
|
+
let _tkMRtexel = textureSample(tkMetalRoughArray, tkMetalRoughArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5));
|
|
6406
|
+
_tkMR = vec2<f32>(_tkMRtexel.b, _tkMRtexel.g);
|
|
6407
|
+
}
|
|
6408
|
+
#endif
|
|
6409
|
+
`;
|
|
6410
|
+
}
|
|
6411
|
+
getWGSLMetalRoughApplyCode() {
|
|
6412
|
+
return `
|
|
6413
|
+
#if defined(TOOLKIT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
6414
|
+
metallicRoughness.r = _tkMR.x;
|
|
6415
|
+
metallicRoughness.g = _tkMR.y;
|
|
6416
|
+
#endif
|
|
6417
|
+
`;
|
|
6418
|
+
}
|
|
6419
|
+
getWGSLEmissiveCode() {
|
|
6420
|
+
return `
|
|
6421
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_EMISSIVE)
|
|
6422
|
+
{
|
|
6423
|
+
let _tkEmis = textureSample(tkEmissiveArray, tkEmissiveArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5)).rgb;
|
|
6424
|
+
finalEmissive = toLinearSpaceVec3(_tkEmis);
|
|
6425
|
+
}
|
|
6426
|
+
#endif
|
|
6427
|
+
`;
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6002
6430
|
export class UniversalShaderMaterial extends CustomShaderMaterial {
|
|
6003
6431
|
constructor(name, scene) {
|
|
6004
6432
|
super(name, scene);
|
|
@@ -6525,13 +6953,12 @@ export class MetadataParser {
|
|
|
6525
6953
|
if (babylonLight != null) {
|
|
6526
6954
|
const lightRange = component.range != null ? component.range : Number.MAX_VALUE;
|
|
6527
6955
|
const lightColor = component.color != null ? Utilities.ParseColor3(component.color, Color3.White()) : Color3.White();
|
|
6528
|
-
const specularColor = component.specular != null ? Utilities.ParseColor3(component.specular, Color3.White()) : Color3.White();
|
|
6529
6956
|
const lightmapMode = component.lightmapmode != null ? component.lightmapmode : 0;
|
|
6530
6957
|
const lightmapType = component.lightmaptype != null ? component.lightmaptype : 0;
|
|
6531
6958
|
babylonLight.parent = entity;
|
|
6532
6959
|
babylonLight.range = lightRange;
|
|
6533
6960
|
babylonLight.diffuse = lightColor;
|
|
6534
|
-
babylonLight.specular =
|
|
6961
|
+
babylonLight.specular = Color3.White();
|
|
6535
6962
|
babylonLight.intensity = (component.intensity != null ? component.intensity : 1) * intensityFactor;
|
|
6536
6963
|
switch (lightmapMode) {
|
|
6537
6964
|
case 2:
|
|
@@ -11727,8 +12154,10 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11727
12154
|
constructor(name, scene) {
|
|
11728
12155
|
super(name, scene);
|
|
11729
12156
|
this.controller = null;
|
|
11730
|
-
this.
|
|
11731
|
-
this.
|
|
12157
|
+
this._vatSkinArray = false;
|
|
12158
|
+
this._vatSkinArrayNormal = false;
|
|
12159
|
+
this._vatSkinArrayMetalRough = false;
|
|
12160
|
+
this._vatSkinArrayEmissive = false;
|
|
11732
12161
|
this.shader = this.getShaderName();
|
|
11733
12162
|
this.addAttribute("g_vatAnim0");
|
|
11734
12163
|
this.addAttribute("g_vatAnim1");
|
|
@@ -11784,97 +12213,90 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11784
12213
|
cloned.alpha = this.alpha;
|
|
11785
12214
|
cloned.alphaMode = this.alphaMode;
|
|
11786
12215
|
cloned.transparencyMode = this.transparencyMode;
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
12216
|
+
if (this._vatSkinArray) {
|
|
12217
|
+
const arr = this.getTextureValue("tkAlbedoArray");
|
|
12218
|
+
if (arr != null)
|
|
12219
|
+
cloned.addTextureArrayUniform("tkAlbedoArray", arr);
|
|
12220
|
+
cloned.enableVatSkinArray();
|
|
12221
|
+
}
|
|
12222
|
+
if (this._vatSkinArrayNormal) {
|
|
12223
|
+
const narr = this.getTextureValue("tkNormalArray");
|
|
12224
|
+
if (narr != null)
|
|
12225
|
+
cloned.addTextureArrayUniform("tkNormalArray", narr);
|
|
12226
|
+
cloned.enableVatSkinArrayNormal();
|
|
12227
|
+
}
|
|
12228
|
+
if (this._vatSkinArrayMetalRough) {
|
|
12229
|
+
const mrarr = this.getTextureValue("tkMetalRoughArray");
|
|
12230
|
+
if (mrarr != null)
|
|
12231
|
+
cloned.addTextureArrayUniform("tkMetalRoughArray", mrarr);
|
|
12232
|
+
cloned.enableVatSkinArrayMetalRough();
|
|
12233
|
+
}
|
|
12234
|
+
if (this._vatSkinArrayEmissive) {
|
|
12235
|
+
const earr = this.getTextureValue("tkEmissiveArray");
|
|
12236
|
+
if (earr != null)
|
|
12237
|
+
cloned.addTextureArrayUniform("tkEmissiveArray", earr);
|
|
12238
|
+
cloned.enableVatSkinArrayEmissive();
|
|
12239
|
+
}
|
|
11790
12240
|
return cloned;
|
|
11791
12241
|
}
|
|
11792
|
-
|
|
11793
|
-
this.
|
|
11794
|
-
this.
|
|
11795
|
-
if (
|
|
11796
|
-
this.
|
|
11797
|
-
|
|
11798
|
-
}
|
|
11799
|
-
this._notifyPluginOfRuntimeSkinChange();
|
|
12242
|
+
enableVatSkinArray() {
|
|
12243
|
+
this._vatSkinArray = true;
|
|
12244
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12245
|
+
if (this.plugin)
|
|
12246
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12247
|
+
return this;
|
|
11800
12248
|
}
|
|
11801
|
-
|
|
11802
|
-
this.
|
|
11803
|
-
this.
|
|
11804
|
-
this.
|
|
12249
|
+
disableVatSkinArray() {
|
|
12250
|
+
this._vatSkinArray = false;
|
|
12251
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12252
|
+
if (this.plugin)
|
|
12253
|
+
this.plugin.markAllDefinesAsDirty();
|
|
11805
12254
|
}
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
const scene = this.getScene();
|
|
11816
|
-
const layerCount = layers.length;
|
|
11817
|
-
const bytesPerLayer = width * height * 4;
|
|
11818
|
-
const albedoData = new Uint8Array(bytesPerLayer * layerCount);
|
|
11819
|
-
const normalData = new Uint8Array(bytesPerLayer * layerCount);
|
|
11820
|
-
const resolveUrl = (rel) => {
|
|
11821
|
-
if (!rel)
|
|
11822
|
-
return "";
|
|
11823
|
-
if (rel.indexOf("://") >= 0 || rel.indexOf("blob:") === 0 || rel.indexOf("data:") === 0 || rel.indexOf("/") === 0)
|
|
11824
|
-
return rel;
|
|
11825
|
-
if (rootUrl) {
|
|
11826
|
-
const sep = rootUrl.charAt(rootUrl.length - 1) === "/" ? "" : "/";
|
|
11827
|
-
return rootUrl + sep + rel;
|
|
11828
|
-
}
|
|
11829
|
-
return rel;
|
|
11830
|
-
};
|
|
11831
|
-
const loadAndCopy = (url, dst, layerIdx, label) => {
|
|
11832
|
-
return new Promise((resolve, reject) => {
|
|
11833
|
-
const fullUrl = resolveUrl(url);
|
|
11834
|
-
const tex = new Texture(fullUrl, scene, true, true, samplingMode, () => {
|
|
11835
|
-
const size = tex.getSize();
|
|
11836
|
-
if (size.width !== width || size.height !== height) {
|
|
11837
|
-
tex.dispose();
|
|
11838
|
-
reject(new Error(`${label} '${fullUrl}' is ${size.width}x${size.height}, expected ${width}x${height}.`));
|
|
11839
|
-
return;
|
|
11840
|
-
}
|
|
11841
|
-
const pixelsPromise = tex.readPixels();
|
|
11842
|
-
const onPixels = (pixels) => {
|
|
11843
|
-
if (!pixels) {
|
|
11844
|
-
tex.dispose();
|
|
11845
|
-
reject(new Error(`${label} '${fullUrl}': readPixels returned null.`));
|
|
11846
|
-
return;
|
|
11847
|
-
}
|
|
11848
|
-
dst.set(new Uint8Array(pixels.buffer, pixels.byteOffset, pixels.byteLength), layerIdx * bytesPerLayer);
|
|
11849
|
-
tex.dispose();
|
|
11850
|
-
resolve();
|
|
11851
|
-
};
|
|
11852
|
-
if (pixelsPromise && typeof pixelsPromise.then === "function") {
|
|
11853
|
-
pixelsPromise.then(onPixels).catch((e) => { tex.dispose(); reject(e); });
|
|
11854
|
-
}
|
|
11855
|
-
else {
|
|
11856
|
-
onPixels(pixelsPromise);
|
|
11857
|
-
}
|
|
11858
|
-
}, (msg) => reject(new Error(`${label} '${fullUrl}' load failed: ${msg}`)));
|
|
11859
|
-
});
|
|
11860
|
-
};
|
|
11861
|
-
const tasks = [];
|
|
11862
|
-
for (let i = 0; i < layerCount; i++) {
|
|
11863
|
-
tasks.push(loadAndCopy(layers[i].albedo, albedoData, i, "Skin albedo"));
|
|
11864
|
-
tasks.push(loadAndCopy(layers[i].normal, normalData, i, "Skin normal"));
|
|
11865
|
-
}
|
|
11866
|
-
await Promise.all(tasks);
|
|
11867
|
-
const albedoArray = RawTexture2DArray.CreateRGBATexture(albedoData, width, height, layerCount, scene, generateMipMaps, false, samplingMode);
|
|
11868
|
-
const normalArray = RawTexture2DArray.CreateRGBATexture(normalData, width, height, layerCount, scene, generateMipMaps, false, samplingMode);
|
|
11869
|
-
normalArray.gammaSpace = false;
|
|
11870
|
-
this.setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults);
|
|
11871
|
-
}
|
|
11872
|
-
_notifyPluginOfRuntimeSkinChange() {
|
|
11873
|
-
const plug = this.plugin;
|
|
11874
|
-
if (plug && typeof plug.onRuntimeSkinArraysChanged === "function") {
|
|
11875
|
-
plug.onRuntimeSkinArraysChanged();
|
|
11876
|
-
}
|
|
12255
|
+
enableVatSkinArrayNormal() {
|
|
12256
|
+
this._vatSkinArrayNormal = true;
|
|
12257
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12258
|
+
if (this.plugin)
|
|
12259
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12260
|
+
return this;
|
|
12261
|
+
}
|
|
12262
|
+
disableVatSkinArrayNormal() {
|
|
12263
|
+
this._vatSkinArrayNormal = false;
|
|
11877
12264
|
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12265
|
+
if (this.plugin)
|
|
12266
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12267
|
+
}
|
|
12268
|
+
enableVatSkinArrayMetalRough() {
|
|
12269
|
+
this._vatSkinArrayMetalRough = true;
|
|
12270
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12271
|
+
if (this.plugin)
|
|
12272
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12273
|
+
return this;
|
|
12274
|
+
}
|
|
12275
|
+
disableVatSkinArrayMetalRough() {
|
|
12276
|
+
this._vatSkinArrayMetalRough = false;
|
|
12277
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12278
|
+
if (this.plugin)
|
|
12279
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12280
|
+
}
|
|
12281
|
+
enableVatSkinArrayEmissive() {
|
|
12282
|
+
this._vatSkinArrayEmissive = true;
|
|
12283
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12284
|
+
if (this.plugin)
|
|
12285
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12286
|
+
return this;
|
|
12287
|
+
}
|
|
12288
|
+
disableVatSkinArrayEmissive() {
|
|
12289
|
+
this._vatSkinArrayEmissive = false;
|
|
12290
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12291
|
+
if (this.plugin)
|
|
12292
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12293
|
+
}
|
|
12294
|
+
get vatSkinArray() { return this._vatSkinArray; }
|
|
12295
|
+
get vatSkinArrayNormal() { return this._vatSkinArrayNormal; }
|
|
12296
|
+
get vatSkinArrayMetalRough() { return this._vatSkinArrayMetalRough; }
|
|
12297
|
+
get vatSkinArrayEmissive() { return this._vatSkinArrayEmissive; }
|
|
12298
|
+
get vatSkinArrayActive() {
|
|
12299
|
+
return this._vatSkinArray || this._vatSkinArrayNormal || this._vatSkinArrayMetalRough || this._vatSkinArrayEmissive;
|
|
11878
12300
|
}
|
|
11879
12301
|
}
|
|
11880
12302
|
export class VertexAnimationController {
|
|
@@ -11909,15 +12331,15 @@ export class VertexAnimationController {
|
|
|
11909
12331
|
}
|
|
11910
12332
|
return result;
|
|
11911
12333
|
}
|
|
11912
|
-
static
|
|
12334
|
+
static SetAtlasCellIndex(mesh, cellIndex) {
|
|
11913
12335
|
if (!mesh)
|
|
11914
12336
|
return;
|
|
11915
|
-
mesh.
|
|
12337
|
+
mesh.atlasCellIndex = Math.max(0, Math.floor(cellIndex || 0));
|
|
11916
12338
|
}
|
|
11917
|
-
static
|
|
12339
|
+
static GetAtlasCellIndex(mesh) {
|
|
11918
12340
|
if (!mesh)
|
|
11919
12341
|
return 0;
|
|
11920
|
-
const v = mesh.
|
|
12342
|
+
const v = mesh.atlasCellIndex;
|
|
11921
12343
|
return (typeof v === "number" && isFinite(v) && v >= 0) ? Math.floor(v) : 0;
|
|
11922
12344
|
}
|
|
11923
12345
|
static DisposeAll(scene) {
|
|
@@ -12001,39 +12423,6 @@ export class VertexAnimationController {
|
|
|
12001
12423
|
}
|
|
12002
12424
|
setSpeed(speed) { this._speed = speed; }
|
|
12003
12425
|
setLoop(loop) { this._manualLoopOverride = loop; this._loop = loop; }
|
|
12004
|
-
setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults = true) {
|
|
12005
|
-
for (let i = 0; i < this._plugins.length; i++) {
|
|
12006
|
-
const plugin = this._plugins[i];
|
|
12007
|
-
const mat = plugin.getCustomShaderMaterial();
|
|
12008
|
-
if (mat)
|
|
12009
|
-
mat.setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults);
|
|
12010
|
-
}
|
|
12011
|
-
}
|
|
12012
|
-
clearRuntimeSkinArrays() {
|
|
12013
|
-
for (let i = 0; i < this._plugins.length; i++) {
|
|
12014
|
-
const plugin = this._plugins[i];
|
|
12015
|
-
const mat = plugin.getCustomShaderMaterial();
|
|
12016
|
-
if (mat)
|
|
12017
|
-
mat.clearRuntimeSkinArrays();
|
|
12018
|
-
}
|
|
12019
|
-
}
|
|
12020
|
-
async installSkinsFromUrlsAsync(layers, width, height, options) {
|
|
12021
|
-
if (this._plugins.length === 0) {
|
|
12022
|
-
throw new Error("VertexAnimationController.installSkinsFromUrlsAsync: no registered VAT materials.");
|
|
12023
|
-
}
|
|
12024
|
-
const opts = options || {};
|
|
12025
|
-
const effectiveOptions = { ...opts, rootUrl: opts.rootUrl || this.rootUrl };
|
|
12026
|
-
const nullOutDefaults = opts.nullOutDefaults !== false;
|
|
12027
|
-
const firstMat = this._plugins[0].getCustomShaderMaterial();
|
|
12028
|
-
await firstMat.installSkinsFromUrlsAsync(layers, width, height, effectiveOptions);
|
|
12029
|
-
const sharedAlbedo = firstMat.runtimeAlbedoSkins;
|
|
12030
|
-
const sharedNormal = firstMat.runtimeNormalSkins;
|
|
12031
|
-
for (let i = 1; i < this._plugins.length; i++) {
|
|
12032
|
-
const mat = this._plugins[i].getCustomShaderMaterial();
|
|
12033
|
-
if (mat)
|
|
12034
|
-
mat.setRuntimeSkinArrays(sharedAlbedo, sharedNormal, nullOutDefaults);
|
|
12035
|
-
}
|
|
12036
|
-
}
|
|
12037
12426
|
setCurrentTime(time) {
|
|
12038
12427
|
if (!this._currentClip)
|
|
12039
12428
|
return;
|
|
@@ -12243,9 +12632,9 @@ export class VertexAnimationController {
|
|
|
12243
12632
|
const s = current.settings;
|
|
12244
12633
|
anim0.set(this._time * s.vertexfps, s.vertexframes, current.fromRow, this._blendWeight);
|
|
12245
12634
|
const loopFlag = this._loopBlend ? 1.0 : 0.0;
|
|
12246
|
-
const
|
|
12247
|
-
const
|
|
12248
|
-
anim1.w =
|
|
12635
|
+
const cellRaw = imesh.atlasCellIndex;
|
|
12636
|
+
const cell = (typeof cellRaw === "number" && cellRaw >= 0) ? Math.floor(cellRaw) : 0;
|
|
12637
|
+
anim1.w = cell * 2.0 + loopFlag;
|
|
12249
12638
|
const prev = this.getPreviousRendererClip(rendererGuid);
|
|
12250
12639
|
if (prev && this._previousClip && this._blendWeight < 0.999 && this._isRendererPositionReady(prev)) {
|
|
12251
12640
|
const ps = prev.settings;
|
|
@@ -12415,17 +12804,17 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12415
12804
|
super(customMaterial, shaderName, 100, {
|
|
12416
12805
|
VERTEXANIMATIONMATERIAL: false,
|
|
12417
12806
|
VAT_NORMAL_SEPARATE: false,
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12807
|
+
VAT_SKIN_ARRAY: false,
|
|
12808
|
+
VAT_SKIN_ARRAY_ALBEDO: false,
|
|
12809
|
+
VAT_SKIN_ARRAY_NORMAL: false,
|
|
12810
|
+
VAT_SKIN_ARRAY_MR: false,
|
|
12811
|
+
VAT_SKIN_ARRAY_EMISSIVE: false
|
|
12421
12812
|
});
|
|
12422
12813
|
this.vertexAnimations = null;
|
|
12423
12814
|
this.controller = null;
|
|
12424
12815
|
this._rendererTargets = [];
|
|
12425
12816
|
this._targetRendererGuid = "";
|
|
12426
12817
|
this._placeholderTexture = null;
|
|
12427
|
-
this._placeholderAlbedoArray = null;
|
|
12428
|
-
this._placeholderNormalArray = null;
|
|
12429
12818
|
this._cc_posTex = null;
|
|
12430
12819
|
this._cc_normTex = null;
|
|
12431
12820
|
this._cc_prevPosTex = null;
|
|
@@ -12447,24 +12836,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12447
12836
|
customMaterial.setTextureValue("vatNormal", this._placeholderTexture);
|
|
12448
12837
|
customMaterial.setTextureValue("vatPrevPosition", this._placeholderTexture);
|
|
12449
12838
|
customMaterial.setTextureValue("vatPrevNormal", this._placeholderTexture);
|
|
12450
|
-
const greyArr = new Uint8Array([128, 128, 128, 255]);
|
|
12451
|
-
const flatNormalArr = new Uint8Array([128, 128, 255, 255]);
|
|
12452
|
-
this._placeholderAlbedoArray = RawTexture2DArray.CreateRGBATexture(greyArr, 1, 1, 1, scene, false, false, Texture.NEAREST_SAMPLINGMODE);
|
|
12453
|
-
this._placeholderNormalArray = RawTexture2DArray.CreateRGBATexture(flatNormalArr, 1, 1, 1, scene, false, false, Texture.NEAREST_SAMPLINGMODE);
|
|
12454
12839
|
}
|
|
12455
12840
|
dispose() {
|
|
12456
12841
|
if (this._placeholderTexture) {
|
|
12457
12842
|
this._placeholderTexture.dispose();
|
|
12458
12843
|
this._placeholderTexture = null;
|
|
12459
12844
|
}
|
|
12460
|
-
if (this._placeholderAlbedoArray) {
|
|
12461
|
-
this._placeholderAlbedoArray.dispose();
|
|
12462
|
-
this._placeholderAlbedoArray = null;
|
|
12463
|
-
}
|
|
12464
|
-
if (this._placeholderNormalArray) {
|
|
12465
|
-
this._placeholderNormalArray.dispose();
|
|
12466
|
-
this._placeholderNormalArray = null;
|
|
12467
|
-
}
|
|
12468
12845
|
super.dispose();
|
|
12469
12846
|
}
|
|
12470
12847
|
isCompatible(shaderLanguage) {
|
|
@@ -12478,28 +12855,32 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12478
12855
|
CUSTOM_VERTEX_DEFINITIONS: this.getWGSLVertexDefinitions(),
|
|
12479
12856
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getWGSLVertexPositionCode(),
|
|
12480
12857
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getWGSLVertexNormalCode(),
|
|
12481
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12858
|
+
CUSTOM_VERTEX_MAIN_END: this.getWGSLSkinLayerVaryingCode()
|
|
12482
12859
|
};
|
|
12483
12860
|
}
|
|
12484
12861
|
return {
|
|
12485
12862
|
CUSTOM_VERTEX_DEFINITIONS: this.getGLSLVertexDefinitions(),
|
|
12486
12863
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getGLSLVertexPositionCode(),
|
|
12487
12864
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getGLSLVertexNormalCode(),
|
|
12488
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12865
|
+
CUSTOM_VERTEX_MAIN_END: this.getGLSLSkinLayerVaryingCode()
|
|
12489
12866
|
};
|
|
12490
12867
|
}
|
|
12491
12868
|
if (shaderType === "fragment") {
|
|
12492
12869
|
if (wgsl) {
|
|
12493
12870
|
return {
|
|
12494
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12495
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12496
|
-
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.
|
|
12871
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getWGSLSkinFragmentDefs(),
|
|
12872
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getWGSLSkinAlbedoCode() + this.getWGSLSkinMetalRoughSampleCode(),
|
|
12873
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getWGSLSkinNormalCode(),
|
|
12874
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getWGSLSkinMetalRoughApplyCode(),
|
|
12875
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getWGSLSkinEmissiveCode()
|
|
12497
12876
|
};
|
|
12498
12877
|
}
|
|
12499
12878
|
return {
|
|
12500
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12501
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12502
|
-
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.
|
|
12879
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getGLSLSkinFragmentDefs(),
|
|
12880
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getGLSLSkinAlbedoCode() + this.getGLSLSkinMetalRoughSampleCode(),
|
|
12881
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getGLSLSkinNormalCode(),
|
|
12882
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getGLSLSkinMetalRoughApplyCode(),
|
|
12883
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getGLSLSkinEmissiveCode()
|
|
12503
12884
|
};
|
|
12504
12885
|
}
|
|
12505
12886
|
return null;
|
|
@@ -12514,13 +12895,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12514
12895
|
const customSamplers = this.getCustomShaderMaterial().getCustomSamplers();
|
|
12515
12896
|
if (customSamplers != null && customSamplers.length > 0)
|
|
12516
12897
|
samplers.push(...customSamplers);
|
|
12517
|
-
const mat = this.getCustomShaderMaterial();
|
|
12518
|
-
if (mat) {
|
|
12519
|
-
if (samplers.indexOf("runtimeAlbedoSkins") === -1)
|
|
12520
|
-
samplers.push("runtimeAlbedoSkins");
|
|
12521
|
-
if (samplers.indexOf("runtimeNormalSkins") === -1)
|
|
12522
|
-
samplers.push("runtimeNormalSkins");
|
|
12523
|
-
}
|
|
12524
12898
|
}
|
|
12525
12899
|
getAttributes(attributes, scene, mesh) {
|
|
12526
12900
|
const customAttributes = this.getCustomShaderMaterial().getCustomAttributes();
|
|
@@ -12536,15 +12910,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12536
12910
|
defines.VAT_NORMAL_SEPARATE = (mode === "separate");
|
|
12537
12911
|
const engine = scene ? scene.getEngine() : null;
|
|
12538
12912
|
defines.UV3 = !(engine && engine.isWebGPU);
|
|
12539
|
-
const
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
defines.
|
|
12543
|
-
defines.
|
|
12544
|
-
defines.
|
|
12545
|
-
}
|
|
12546
|
-
onRuntimeSkinArraysChanged() {
|
|
12547
|
-
this.markAllDefinesAsDirty();
|
|
12913
|
+
const matSkin = this.getCustomShaderMaterial();
|
|
12914
|
+
defines.VAT_SKIN_ARRAY = !!(matSkin && matSkin.vatSkinArrayActive);
|
|
12915
|
+
defines.VAT_SKIN_ARRAY_ALBEDO = !!(matSkin && matSkin.vatSkinArray);
|
|
12916
|
+
defines.VAT_SKIN_ARRAY_NORMAL = !!(matSkin && matSkin.vatSkinArrayNormal);
|
|
12917
|
+
defines.VAT_SKIN_ARRAY_MR = !!(matSkin && matSkin.vatSkinArrayMetalRough);
|
|
12918
|
+
defines.VAT_SKIN_ARRAY_EMISSIVE = !!(matSkin && matSkin.vatSkinArrayEmissive);
|
|
12548
12919
|
}
|
|
12549
12920
|
bindForSubMesh(uniformBuffer, scene, engine, subMesh) {
|
|
12550
12921
|
if (!this.getIsEnabled())
|
|
@@ -12552,16 +12923,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12552
12923
|
const renderMesh = subMesh && subMesh.getRenderingMesh ? subMesh.getRenderingMesh() : null;
|
|
12553
12924
|
this._captureRendererTarget(renderMesh || (subMesh ? subMesh.getMesh() : null));
|
|
12554
12925
|
this._pushVATUniforms(uniformBuffer, false);
|
|
12555
|
-
this._pushRuntimeSkinSamplers(uniformBuffer);
|
|
12556
|
-
}
|
|
12557
|
-
_pushRuntimeSkinSamplers(buf) {
|
|
12558
|
-
const mat = this.getCustomShaderMaterial();
|
|
12559
|
-
const albedoArr = (mat && mat.runtimeAlbedoSkins && mat.runtimeAlbedoSkins.isReady && mat.runtimeAlbedoSkins.isReady())
|
|
12560
|
-
? mat.runtimeAlbedoSkins : this._placeholderAlbedoArray;
|
|
12561
|
-
const normalArr = (mat && mat.runtimeNormalSkins && mat.runtimeNormalSkins.isReady && mat.runtimeNormalSkins.isReady())
|
|
12562
|
-
? mat.runtimeNormalSkins : this._placeholderNormalArray;
|
|
12563
|
-
buf.setTexture("runtimeAlbedoSkins", albedoArr);
|
|
12564
|
-
buf.setTexture("runtimeNormalSkins", normalArr);
|
|
12565
12926
|
}
|
|
12566
12927
|
setupAnimations(settings, controllerId, rootUrl = "", lazyLoadTextures = false) {
|
|
12567
12928
|
this.vertexAnimations = settings;
|
|
@@ -12814,7 +13175,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12814
13175
|
}
|
|
12815
13176
|
bindVATToEffect(effect) {
|
|
12816
13177
|
this._pushVATUniforms(effect, true);
|
|
12817
|
-
this._pushRuntimeSkinSamplers(effect);
|
|
12818
13178
|
}
|
|
12819
13179
|
_pushVATUniforms(buf, isEffect) {
|
|
12820
13180
|
const fb = this._placeholderTexture;
|
|
@@ -12887,13 +13247,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12887
13247
|
uniform sampler2D vatPrevPosition;
|
|
12888
13248
|
uniform sampler2D vatPrevNormal;
|
|
12889
13249
|
#endif
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
varying vec2 vRuntimeSkinUV;
|
|
13250
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13251
|
+
#ifndef TOOLKIT_VAT_SKIN_V_DEFINED
|
|
13252
|
+
#define TOOLKIT_VAT_SKIN_V_DEFINED
|
|
13253
|
+
varying float vVatSkinLayer;
|
|
13254
|
+
varying vec2 vVatSkinUV;
|
|
13255
|
+
#endif
|
|
12897
13256
|
#endif
|
|
12898
13257
|
`;
|
|
12899
13258
|
}
|
|
@@ -12907,8 +13266,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12907
13266
|
float vatPrevFrame = g_vatAnim1.x;
|
|
12908
13267
|
float vatPrevFrameCount = g_vatAnim1.y;
|
|
12909
13268
|
float vatPrevFromRow = g_vatAnim1.z;
|
|
12910
|
-
|
|
12911
|
-
float vatLoopBlend = mod(
|
|
13269
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13270
|
+
float vatLoopBlend = mod(g_vatAnim1.w, 2.0); // low bit is loop-blend, high bits carry the skin layer index
|
|
13271
|
+
#else
|
|
13272
|
+
float vatLoopBlend = g_vatAnim1.w;
|
|
13273
|
+
#endif
|
|
12912
13274
|
if (vatFrameCount > 0.5) {
|
|
12913
13275
|
// GLSL path uses the third UV channel:
|
|
12914
13276
|
// Unity uv3 -> glTF TEXCOORD_2 -> Babylon shader uv3
|
|
@@ -12976,9 +13338,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12976
13338
|
float vatNormFrame = g_vatAnim0.x;
|
|
12977
13339
|
float vatNormFrameCount = g_vatAnim0.y;
|
|
12978
13340
|
float vatNormFromRow = g_vatAnim0.z;
|
|
12979
|
-
|
|
12980
|
-
float
|
|
12981
|
-
|
|
13341
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13342
|
+
float vatNormLoopBlend = mod(g_vatAnim1.w, 2.0);
|
|
13343
|
+
#else
|
|
13344
|
+
float vatNormLoopBlend = g_vatAnim1.w;
|
|
13345
|
+
#endif
|
|
12982
13346
|
|
|
12983
13347
|
if (vatNormFrameCount > 0.5) {
|
|
12984
13348
|
// GLSL path uses the third UV channel:
|
|
@@ -13024,9 +13388,10 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13024
13388
|
var vatPrevPositionSampler: sampler;
|
|
13025
13389
|
var vatPrevNormal: texture_2d<f32>;
|
|
13026
13390
|
var vatPrevNormalSampler: sampler;
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
varying
|
|
13391
|
+
#endif
|
|
13392
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13393
|
+
varying vVatSkinLayer: f32;
|
|
13394
|
+
varying vVatSkinUV: vec2<f32>;
|
|
13030
13395
|
#endif
|
|
13031
13396
|
`;
|
|
13032
13397
|
}
|
|
@@ -13040,8 +13405,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13040
13405
|
let vatPrevFrame = vertexInputs.g_vatAnim1.x;
|
|
13041
13406
|
let vatPrevFrameCount = vertexInputs.g_vatAnim1.y;
|
|
13042
13407
|
let vatPrevFromRow = vertexInputs.g_vatAnim1.z;
|
|
13043
|
-
|
|
13044
|
-
let vatLoopBlend =
|
|
13408
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13409
|
+
let vatLoopBlend = vertexInputs.g_vatAnim1.w % 2.0; // low bit is loop-blend, high bits carry the skin layer index
|
|
13410
|
+
#else
|
|
13411
|
+
let vatLoopBlend = vertexInputs.g_vatAnim1.w;
|
|
13412
|
+
#endif
|
|
13045
13413
|
if (vatFrameCount > 0.5) {
|
|
13046
13414
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13047
13415
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13110,8 +13478,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13110
13478
|
let vatNormFrame = vertexInputs.g_vatAnim0.x;
|
|
13111
13479
|
let vatNormFrameCount = vertexInputs.g_vatAnim0.y;
|
|
13112
13480
|
let vatNormFromRow = vertexInputs.g_vatAnim0.z;
|
|
13113
|
-
|
|
13114
|
-
let vatNormLoopBlend =
|
|
13481
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13482
|
+
let vatNormLoopBlend = vertexInputs.g_vatAnim1.w % 2.0;
|
|
13483
|
+
#else
|
|
13484
|
+
let vatNormLoopBlend = vertexInputs.g_vatAnim1.w;
|
|
13485
|
+
#endif
|
|
13115
13486
|
if (vatNormFrameCount > 0.5) {
|
|
13116
13487
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13117
13488
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13148,130 +13519,187 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13148
13519
|
#endif
|
|
13149
13520
|
`;
|
|
13150
13521
|
}
|
|
13151
|
-
|
|
13522
|
+
getGLSLSkinLayerVaryingCode() {
|
|
13152
13523
|
return `
|
|
13153
|
-
#ifdef
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
#endif
|
|
13162
|
-
}
|
|
13524
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13525
|
+
#ifdef UV1
|
|
13526
|
+
vVatSkinLayer = floor(g_vatAnim1.w * 0.5 + 0.0001);
|
|
13527
|
+
vVatSkinUV = uv;
|
|
13528
|
+
#else
|
|
13529
|
+
vVatSkinLayer = 0.0;
|
|
13530
|
+
vVatSkinUV = vec2(0.0);
|
|
13531
|
+
#endif
|
|
13163
13532
|
#endif
|
|
13164
13533
|
`;
|
|
13165
13534
|
}
|
|
13166
|
-
|
|
13535
|
+
getGLSLSkinFragmentDefs() {
|
|
13167
13536
|
return `
|
|
13168
|
-
#ifdef
|
|
13537
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13538
|
+
varying float vVatSkinLayer;
|
|
13539
|
+
varying vec2 vVatSkinUV;
|
|
13540
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13541
|
+
uniform sampler2DArray tkAlbedoArray;
|
|
13542
|
+
#endif
|
|
13543
|
+
#ifdef VAT_SKIN_ARRAY_NORMAL
|
|
13544
|
+
uniform sampler2DArray tkNormalArray;
|
|
13545
|
+
#endif
|
|
13546
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13547
|
+
uniform sampler2DArray tkMetalRoughArray;
|
|
13548
|
+
vec2 _tkMR;
|
|
13549
|
+
#endif
|
|
13550
|
+
#ifdef VAT_SKIN_ARRAY_EMISSIVE
|
|
13551
|
+
uniform sampler2DArray tkEmissiveArray;
|
|
13552
|
+
#endif
|
|
13553
|
+
#endif
|
|
13554
|
+
`;
|
|
13555
|
+
}
|
|
13556
|
+
getGLSLSkinAlbedoCode() {
|
|
13557
|
+
return `
|
|
13558
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13169
13559
|
{
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
#ifdef
|
|
13173
|
-
|
|
13560
|
+
vec4 _vatSkinAlbedo = texture(tkAlbedoArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5)));
|
|
13561
|
+
// Match Babylon's native albedo: sRGB -> linear when the albedo is gamma-space.
|
|
13562
|
+
#ifdef GAMMAALBEDO
|
|
13563
|
+
surfaceAlbedo = toLinearSpace(_vatSkinAlbedo.rgb) * vAlbedoColor.rgb;
|
|
13174
13564
|
#else
|
|
13175
|
-
|
|
13565
|
+
surfaceAlbedo = _vatSkinAlbedo.rgb * vAlbedoColor.rgb;
|
|
13566
|
+
#endif
|
|
13567
|
+
#ifdef ALPHATEST
|
|
13568
|
+
if (_vatSkinAlbedo.a < alphaCutOff) discard;
|
|
13176
13569
|
#endif
|
|
13177
13570
|
}
|
|
13178
13571
|
#endif
|
|
13179
13572
|
`;
|
|
13180
13573
|
}
|
|
13181
|
-
|
|
13574
|
+
getGLSLSkinNormalCode() {
|
|
13182
13575
|
return `
|
|
13183
|
-
#
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
uniform highp sampler2DArray runtimeNormalSkins;
|
|
13576
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
13577
|
+
{
|
|
13578
|
+
vec3 _vatNrmTexel = texture(tkNormalArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5))).xyz;
|
|
13579
|
+
normalW = perturbNormal(vTBN, _vatNrmTexel, vBumpInfos.y);
|
|
13580
|
+
}
|
|
13189
13581
|
#endif
|
|
13190
13582
|
`;
|
|
13191
13583
|
}
|
|
13192
|
-
|
|
13584
|
+
getGLSLSkinMetalRoughSampleCode() {
|
|
13193
13585
|
return `
|
|
13194
|
-
#ifdef
|
|
13586
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13195
13587
|
{
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
surfaceAlbedo = _rsAlbedo.rgb * vAlbedoColor.rgb;
|
|
13199
|
-
#ifdef ALPHATEST
|
|
13200
|
-
if (_rsAlbedo.a < alphaCutOff) discard;
|
|
13201
|
-
#endif
|
|
13588
|
+
vec4 _vatMRtexel = texture(tkMetalRoughArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5)));
|
|
13589
|
+
_tkMR = vec2(_vatMRtexel.b, _vatMRtexel.g);
|
|
13202
13590
|
}
|
|
13203
13591
|
#endif
|
|
13204
13592
|
`;
|
|
13205
13593
|
}
|
|
13206
|
-
|
|
13594
|
+
getGLSLSkinMetalRoughApplyCode() {
|
|
13595
|
+
return `
|
|
13596
|
+
#if defined(VAT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
13597
|
+
metallicRoughness.r = _tkMR.x;
|
|
13598
|
+
metallicRoughness.g = _tkMR.y;
|
|
13599
|
+
#endif
|
|
13600
|
+
`;
|
|
13601
|
+
}
|
|
13602
|
+
getGLSLSkinEmissiveCode() {
|
|
13207
13603
|
return `
|
|
13208
|
-
#
|
|
13604
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_EMISSIVE)
|
|
13209
13605
|
{
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
vec3 _rsNormalTS = _rsNormalSample * 2.0 - 1.0;
|
|
13213
|
-
vec3 _rsP = vPositionW;
|
|
13214
|
-
vec3 _rsN = normalize(vNormalW);
|
|
13215
|
-
vec3 _rsDp1 = dFdx(_rsP);
|
|
13216
|
-
vec3 _rsDp2 = dFdy(_rsP);
|
|
13217
|
-
vec2 _rsDuv1 = dFdx(vRuntimeSkinUV);
|
|
13218
|
-
vec2 _rsDuv2 = dFdy(vRuntimeSkinUV);
|
|
13219
|
-
vec3 _rsDp2perp = cross(_rsDp2, _rsN);
|
|
13220
|
-
vec3 _rsDp1perp = cross(_rsN, _rsDp1);
|
|
13221
|
-
vec3 _rsT = _rsDp2perp * _rsDuv1.x + _rsDp1perp * _rsDuv2.x;
|
|
13222
|
-
vec3 _rsB = _rsDp2perp * _rsDuv1.y + _rsDp1perp * _rsDuv2.y;
|
|
13223
|
-
float _rsInvMax = inversesqrt(max(dot(_rsT, _rsT), dot(_rsB, _rsB)));
|
|
13224
|
-
mat3 _rsTBN = mat3(_rsT * _rsInvMax, _rsB * _rsInvMax, _rsN);
|
|
13225
|
-
normalW = normalize(_rsTBN * _rsNormalTS);
|
|
13606
|
+
vec3 _vatEmis = texture(tkEmissiveArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5))).rgb;
|
|
13607
|
+
finalEmissive = toLinearSpace(_vatEmis);
|
|
13226
13608
|
}
|
|
13227
13609
|
#endif
|
|
13228
13610
|
`;
|
|
13229
13611
|
}
|
|
13230
|
-
|
|
13612
|
+
getWGSLSkinLayerVaryingCode() {
|
|
13231
13613
|
return `
|
|
13232
|
-
|
|
13233
|
-
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13614
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13615
|
+
#ifdef UV1
|
|
13616
|
+
vertexOutputs.vVatSkinLayer = floor(vertexInputs.g_vatAnim1.w * 0.5 + 0.0001);
|
|
13617
|
+
vertexOutputs.vVatSkinUV = vertexInputs.uv;
|
|
13618
|
+
#else
|
|
13619
|
+
vertexOutputs.vVatSkinLayer = 0.0;
|
|
13620
|
+
vertexOutputs.vVatSkinUV = vec2f(0.0);
|
|
13621
|
+
#endif
|
|
13622
|
+
#endif
|
|
13238
13623
|
`;
|
|
13239
13624
|
}
|
|
13240
|
-
|
|
13625
|
+
getWGSLSkinFragmentDefs() {
|
|
13241
13626
|
return `
|
|
13242
|
-
#ifdef
|
|
13627
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13628
|
+
varying vVatSkinLayer: f32;
|
|
13629
|
+
varying vVatSkinUV: vec2<f32>;
|
|
13630
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13631
|
+
var tkAlbedoArray: texture_2d_array<f32>;
|
|
13632
|
+
var tkAlbedoArraySampler: sampler;
|
|
13633
|
+
#endif
|
|
13634
|
+
#ifdef VAT_SKIN_ARRAY_NORMAL
|
|
13635
|
+
var tkNormalArray: texture_2d_array<f32>;
|
|
13636
|
+
var tkNormalArraySampler: sampler;
|
|
13637
|
+
#endif
|
|
13638
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13639
|
+
var tkMetalRoughArray: texture_2d_array<f32>;
|
|
13640
|
+
var tkMetalRoughArraySampler: sampler;
|
|
13641
|
+
var<private> _tkMR: vec2<f32>;
|
|
13642
|
+
#endif
|
|
13643
|
+
#ifdef VAT_SKIN_ARRAY_EMISSIVE
|
|
13644
|
+
var tkEmissiveArray: texture_2d_array<f32>;
|
|
13645
|
+
var tkEmissiveArraySampler: sampler;
|
|
13646
|
+
#endif
|
|
13647
|
+
#endif
|
|
13648
|
+
`;
|
|
13649
|
+
}
|
|
13650
|
+
getWGSLSkinAlbedoCode() {
|
|
13651
|
+
return `
|
|
13652
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13243
13653
|
{
|
|
13244
|
-
let
|
|
13245
|
-
|
|
13246
|
-
|
|
13654
|
+
let _vatSkinAlbedo = textureSample(tkAlbedoArray, tkAlbedoArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5));
|
|
13655
|
+
// Match Babylon's native albedo: sRGB -> linear when the albedo is gamma-space.
|
|
13656
|
+
#ifdef GAMMAALBEDO
|
|
13657
|
+
surfaceAlbedo = toLinearSpaceVec3(_vatSkinAlbedo.rgb) * vAlbedoColor.rgb;
|
|
13658
|
+
#else
|
|
13659
|
+
surfaceAlbedo = _vatSkinAlbedo.rgb * vAlbedoColor.rgb;
|
|
13660
|
+
#endif
|
|
13247
13661
|
#ifdef ALPHATEST
|
|
13248
|
-
if (
|
|
13662
|
+
if (_vatSkinAlbedo.a < alphaCutOff) { discard; }
|
|
13249
13663
|
#endif
|
|
13250
13664
|
}
|
|
13251
13665
|
#endif
|
|
13252
13666
|
`;
|
|
13253
13667
|
}
|
|
13254
|
-
|
|
13668
|
+
getWGSLSkinNormalCode() {
|
|
13669
|
+
return `
|
|
13670
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
13671
|
+
{
|
|
13672
|
+
let _vatNrmTexel = textureSample(tkNormalArray, tkNormalArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5)).rgb;
|
|
13673
|
+
let _vatNrmTBN = mat3x3<f32>(fragmentInputs.vTBN0, fragmentInputs.vTBN1, fragmentInputs.vTBN2);
|
|
13674
|
+
normalW = perturbNormal(_vatNrmTBN, _vatNrmTexel, uniforms.vBumpInfos.y);
|
|
13675
|
+
}
|
|
13676
|
+
#endif
|
|
13677
|
+
`;
|
|
13678
|
+
}
|
|
13679
|
+
getWGSLSkinMetalRoughSampleCode() {
|
|
13255
13680
|
return `
|
|
13256
|
-
#ifdef
|
|
13681
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13257
13682
|
{
|
|
13258
|
-
let
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13683
|
+
let _vatMRtexel = textureSample(tkMetalRoughArray, tkMetalRoughArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5));
|
|
13684
|
+
_tkMR = vec2<f32>(_vatMRtexel.b, _vatMRtexel.g);
|
|
13685
|
+
}
|
|
13686
|
+
#endif
|
|
13687
|
+
`;
|
|
13688
|
+
}
|
|
13689
|
+
getWGSLSkinMetalRoughApplyCode() {
|
|
13690
|
+
return `
|
|
13691
|
+
#if defined(VAT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
13692
|
+
metallicRoughness.r = _tkMR.x;
|
|
13693
|
+
metallicRoughness.g = _tkMR.y;
|
|
13694
|
+
#endif
|
|
13695
|
+
`;
|
|
13696
|
+
}
|
|
13697
|
+
getWGSLSkinEmissiveCode() {
|
|
13698
|
+
return `
|
|
13699
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_EMISSIVE)
|
|
13700
|
+
{
|
|
13701
|
+
let _vatEmis = textureSample(tkEmissiveArray, tkEmissiveArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5)).rgb;
|
|
13702
|
+
finalEmissive = toLinearSpaceVec3(_vatEmis);
|
|
13275
13703
|
}
|
|
13276
13704
|
#endif
|
|
13277
13705
|
`;
|
|
@@ -27671,6 +28099,138 @@ ShurikenParticles.UNITY_TO_BABYLON_LIFETIME_RATIO = 0.65;
|
|
|
27671
28099
|
ShurikenParticles.UNITY_TO_BABYLON_DEATH_FADE_ALPHA = 0.2;
|
|
27672
28100
|
ShurikenParticles.EMITTER_POSITION_OFFSET = new Vector3(0, 0, 0);
|
|
27673
28101
|
ShurikenParticles.EMITTER_ROTATION_OFFSET = new Vector3(90, 0, 0);
|
|
28102
|
+
export class SkinTextureArray {
|
|
28103
|
+
static Build(scene, urls, options = {}) {
|
|
28104
|
+
const requested = (urls || []).filter((u) => u != null && String(u).length > 0);
|
|
28105
|
+
if (requested.length === 0)
|
|
28106
|
+
return Promise.resolve(null);
|
|
28107
|
+
const maxLayers = SkinTextureArray._maxArrayLayers(scene.getEngine());
|
|
28108
|
+
let list = requested;
|
|
28109
|
+
if (requested.length > maxLayers) {
|
|
28110
|
+
console.warn("SkinTextureArray: " + requested.length + " slices exceeds GPU maxTextureArrayLayers ("
|
|
28111
|
+
+ maxLayers + ") — clamping to " + maxLayers + ". Skin indices >= " + maxLayers + " will be unavailable.");
|
|
28112
|
+
list = requested.slice(0, maxLayers);
|
|
28113
|
+
}
|
|
28114
|
+
const optKey = "m" + (options.mipmaps === false ? 0 : 1)
|
|
28115
|
+
+ "|y" + (options.invertY === true ? 1 : 0)
|
|
28116
|
+
+ "|s" + (options.samplingMode != null ? options.samplingMode : "d");
|
|
28117
|
+
const key = list.join("|") + "||" + optKey;
|
|
28118
|
+
if (SkinTextureArray._cache[key] != null)
|
|
28119
|
+
return SkinTextureArray._cache[key];
|
|
28120
|
+
const built = SkinTextureArray._loadImages(list).then((images) => {
|
|
28121
|
+
if (images == null || images.length === 0)
|
|
28122
|
+
return null;
|
|
28123
|
+
const w = images[0].width, h = images[0].height, depth = images.length;
|
|
28124
|
+
const canvas = document.createElement("canvas");
|
|
28125
|
+
canvas.width = w;
|
|
28126
|
+
canvas.height = h;
|
|
28127
|
+
const ctx = canvas.getContext("2d");
|
|
28128
|
+
const data = new Uint8Array(w * h * 4 * depth);
|
|
28129
|
+
const flipY = (options.invertY != null) ? options.invertY : false;
|
|
28130
|
+
for (let i = 0; i < depth; i++) {
|
|
28131
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
28132
|
+
ctx.clearRect(0, 0, w, h);
|
|
28133
|
+
if (flipY)
|
|
28134
|
+
ctx.setTransform(1, 0, 0, -1, 0, h);
|
|
28135
|
+
ctx.drawImage(images[i], 0, 0, w, h);
|
|
28136
|
+
const id = ctx.getImageData(0, 0, w, h).data;
|
|
28137
|
+
data.set(id, i * w * h * 4);
|
|
28138
|
+
}
|
|
28139
|
+
const engine = scene.getEngine();
|
|
28140
|
+
const isWebGPU = (engine != null && engine.isWebGPU === true);
|
|
28141
|
+
const genMips = (options.mipmaps !== false);
|
|
28142
|
+
const mipCount = genMips ? (Math.floor(Math.log2(Math.max(w, h))) + 1) : 1;
|
|
28143
|
+
const samplingMode = (options.samplingMode != null) ? options.samplingMode
|
|
28144
|
+
: (genMips ? Texture.TRILINEAR_SAMPLINGMODE : Texture.BILINEAR_SAMPLINGMODE);
|
|
28145
|
+
const arr = new RawTexture2DArray(data, w, h, depth, Constants.TEXTUREFORMAT_RGBA, scene, genMips, false, samplingMode, Constants.TEXTURETYPE_UNSIGNED_BYTE, 0, mipCount);
|
|
28146
|
+
if (genMips && isWebGPU && mipCount > 1)
|
|
28147
|
+
SkinTextureArray._uploadMipChain(scene, arr, data, w, h, depth);
|
|
28148
|
+
arr.wrapU = Texture.CLAMP_ADDRESSMODE;
|
|
28149
|
+
arr.wrapV = Texture.CLAMP_ADDRESSMODE;
|
|
28150
|
+
arr.anisotropicFilteringLevel = (options.aniso != null) ? options.aniso : 8;
|
|
28151
|
+
return arr;
|
|
28152
|
+
}).catch((e) => { console.warn("SkinTextureArray: build failed", e); delete SkinTextureArray._cache[key]; return null; });
|
|
28153
|
+
SkinTextureArray._cache[key] = built;
|
|
28154
|
+
return built;
|
|
28155
|
+
}
|
|
28156
|
+
static _uploadMipChain(scene, arr, base, w, h, depth) {
|
|
28157
|
+
const engine = scene.getEngine();
|
|
28158
|
+
const itex = arr.getInternalTexture();
|
|
28159
|
+
if (itex == null || typeof engine.updateRawTexture2DArray !== "function")
|
|
28160
|
+
return;
|
|
28161
|
+
const count = Math.floor(Math.log2(Math.max(w, h))) + 1;
|
|
28162
|
+
try {
|
|
28163
|
+
let prev = base, pw = w, ph = h;
|
|
28164
|
+
for (let m = 1; m < count; m++) {
|
|
28165
|
+
const nw = Math.max(1, pw >> 1), nh = Math.max(1, ph >> 1);
|
|
28166
|
+
const mip = SkinTextureArray._downsampleLayers(prev, pw, ph, depth, nw, nh);
|
|
28167
|
+
engine.updateRawTexture2DArray(itex, mip, Constants.TEXTUREFORMAT_RGBA, false, null, Constants.TEXTURETYPE_UNSIGNED_BYTE, m);
|
|
28168
|
+
prev = mip;
|
|
28169
|
+
pw = nw;
|
|
28170
|
+
ph = nh;
|
|
28171
|
+
}
|
|
28172
|
+
}
|
|
28173
|
+
catch (e) {
|
|
28174
|
+
console.warn("SkinTextureArray: mip-chain upload failed, using base level only", e);
|
|
28175
|
+
}
|
|
28176
|
+
}
|
|
28177
|
+
static _downsampleLayers(src, sw, sh, depth, dw, dh) {
|
|
28178
|
+
const out = new Uint8Array(dw * dh * 4 * depth);
|
|
28179
|
+
for (let L = 0; L < depth; L++) {
|
|
28180
|
+
const so = L * sw * sh * 4, doo = L * dw * dh * 4;
|
|
28181
|
+
for (let y = 0; y < dh; y++) {
|
|
28182
|
+
for (let x = 0; x < dw; x++) {
|
|
28183
|
+
const sx = x * 2, sy = y * 2;
|
|
28184
|
+
const sx1 = Math.min(sx + 1, sw - 1), sy1 = Math.min(sy + 1, sh - 1);
|
|
28185
|
+
for (let c = 0; c < 4; c++) {
|
|
28186
|
+
const a = src[so + (sy * sw + sx) * 4 + c], b = src[so + (sy * sw + sx1) * 4 + c], e = src[so + (sy1 * sw + sx) * 4 + c], d = src[so + (sy1 * sw + sx1) * 4 + c];
|
|
28187
|
+
out[doo + (y * dw + x) * 4 + c] = (a + b + e + d) >> 2;
|
|
28188
|
+
}
|
|
28189
|
+
}
|
|
28190
|
+
}
|
|
28191
|
+
}
|
|
28192
|
+
return out;
|
|
28193
|
+
}
|
|
28194
|
+
static _maxArrayLayers(engine) {
|
|
28195
|
+
try {
|
|
28196
|
+
const dev = (engine != null) ? (engine._device || (typeof engine.getDevice === "function" ? engine.getDevice() : null)) : null;
|
|
28197
|
+
if (dev != null && dev.limits != null && typeof dev.limits.maxTextureArrayLayers === "number" && dev.limits.maxTextureArrayLayers > 0) {
|
|
28198
|
+
return dev.limits.maxTextureArrayLayers;
|
|
28199
|
+
}
|
|
28200
|
+
const gl = (engine != null) ? engine._gl : null;
|
|
28201
|
+
if (gl != null && typeof gl.getParameter === "function") {
|
|
28202
|
+
const MAX_ARRAY_TEXTURE_LAYERS = 0x88FF;
|
|
28203
|
+
const v = gl.getParameter(MAX_ARRAY_TEXTURE_LAYERS);
|
|
28204
|
+
if (typeof v === "number" && v > 0)
|
|
28205
|
+
return v;
|
|
28206
|
+
}
|
|
28207
|
+
}
|
|
28208
|
+
catch (e) { }
|
|
28209
|
+
return 256;
|
|
28210
|
+
}
|
|
28211
|
+
static _loadImages(urls) {
|
|
28212
|
+
return Promise.all(urls.map((u) => new Promise((resolve, reject) => {
|
|
28213
|
+
const img = document.createElement("img");
|
|
28214
|
+
img.crossOrigin = "anonymous";
|
|
28215
|
+
img.onload = () => resolve(img);
|
|
28216
|
+
img.onerror = () => reject(new Error("SkinTextureArray: failed to load " + u));
|
|
28217
|
+
img.src = u;
|
|
28218
|
+
})));
|
|
28219
|
+
}
|
|
28220
|
+
static Clear() {
|
|
28221
|
+
const entries = [];
|
|
28222
|
+
for (const k in SkinTextureArray._cache) {
|
|
28223
|
+
if (SkinTextureArray._cache[k] != null)
|
|
28224
|
+
entries.push(SkinTextureArray._cache[k]);
|
|
28225
|
+
}
|
|
28226
|
+
SkinTextureArray._cache = {};
|
|
28227
|
+
for (const p of entries) {
|
|
28228
|
+
p.then((arr) => { if (arr != null)
|
|
28229
|
+
arr.dispose(); }).catch(() => { });
|
|
28230
|
+
}
|
|
28231
|
+
}
|
|
28232
|
+
}
|
|
28233
|
+
SkinTextureArray._cache = {};
|
|
27674
28234
|
export class MeshNormalProxy {
|
|
27675
28235
|
constructor() {
|
|
27676
28236
|
this.blendWithPhysicsNormal = 0.0;
|
|
@@ -29245,6 +29805,410 @@ TerrainBuilder.detailChunkMaxTotalChunks = 256;
|
|
|
29245
29805
|
TerrainBuilder.meshDetailChunkMode = 1;
|
|
29246
29806
|
TerrainBuilder.meshDetailChunkTargetInstances = 20000;
|
|
29247
29807
|
TerrainBuilder.meshDetailChunkWorldSize = 64;
|
|
29808
|
+
export class TextureAtlasSkin extends ScriptComponent {
|
|
29809
|
+
constructor(transform, scene, properties = {}, alias = "TextureAtlasSkin") {
|
|
29810
|
+
super(transform, scene, properties, alias);
|
|
29811
|
+
this.abtractMesh = null;
|
|
29812
|
+
this.textureData = null;
|
|
29813
|
+
this.defaultIndex = 0;
|
|
29814
|
+
this.skinnedParts = [];
|
|
29815
|
+
this.albedoSlices = null;
|
|
29816
|
+
this.normalSlices = null;
|
|
29817
|
+
this.metallicSlices = null;
|
|
29818
|
+
this.occlusionSlices = null;
|
|
29819
|
+
this.emissiveSlices = null;
|
|
29820
|
+
this._applied = false;
|
|
29821
|
+
this._manifest = null;
|
|
29822
|
+
this._currentIndex = 0;
|
|
29823
|
+
this._targets = [];
|
|
29824
|
+
this._clonedMultiMaterial = null;
|
|
29825
|
+
}
|
|
29826
|
+
awake() {
|
|
29827
|
+
this.abtractMesh = this.getAbstractMesh();
|
|
29828
|
+
this.albedoSlices = this.getProperty("albedoSlices", null);
|
|
29829
|
+
this.normalSlices = this.getProperty("normalSlices", null);
|
|
29830
|
+
this.metallicSlices = this.getProperty("metallicSlices", null);
|
|
29831
|
+
this.occlusionSlices = this.getProperty("occlusionSlices", null);
|
|
29832
|
+
this.emissiveSlices = this.getProperty("emissiveSlices", null);
|
|
29833
|
+
window["__" + this.transform.name] = this;
|
|
29834
|
+
}
|
|
29835
|
+
start() {
|
|
29836
|
+
this.applySkins();
|
|
29837
|
+
}
|
|
29838
|
+
applySkins() {
|
|
29839
|
+
if (this._applied)
|
|
29840
|
+
return;
|
|
29841
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
29842
|
+
if (mesh == null) {
|
|
29843
|
+
console.warn("TextureAtlasSkin: no abstract mesh on " + this.transform.name);
|
|
29844
|
+
return;
|
|
29845
|
+
}
|
|
29846
|
+
let manifest = this.parseManifest();
|
|
29847
|
+
if (manifest == null) {
|
|
29848
|
+
const sliceCount = this.maxChannelSliceCount();
|
|
29849
|
+
if (sliceCount > 0) {
|
|
29850
|
+
const skins = [];
|
|
29851
|
+
for (let i = 0; i < sliceCount; i++)
|
|
29852
|
+
skins.push({ index: i, name: "skin_" + i });
|
|
29853
|
+
manifest = { skinArray: true, count: sliceCount, skins: skins };
|
|
29854
|
+
}
|
|
29855
|
+
else {
|
|
29856
|
+
console.warn("TextureAtlasSkin: no textureData manifest and no channel slices on " + this.transform.name);
|
|
29857
|
+
return;
|
|
29858
|
+
}
|
|
29859
|
+
}
|
|
29860
|
+
this._manifest = manifest;
|
|
29861
|
+
this._currentIndex = this.clampIndex(this.toInt(this.defaultIndex, 0), "defaultIndex");
|
|
29862
|
+
const isInstanced = this.isInstancedSetup(mesh);
|
|
29863
|
+
const slots = this.getMeshSlots(mesh);
|
|
29864
|
+
const parts = this.skinnedParts || [];
|
|
29865
|
+
if (parts.length === 0) {
|
|
29866
|
+
console.warn("TextureAtlasSkin: no skinnedParts on " + this.transform.name);
|
|
29867
|
+
return;
|
|
29868
|
+
}
|
|
29869
|
+
for (const part of parts) {
|
|
29870
|
+
const targetMat = this.resolvePartMaterial(part);
|
|
29871
|
+
const slot = this.matchSlot(slots, targetMat, part);
|
|
29872
|
+
if (slot == null || !(slot.material instanceof CustomShaderMaterial)) {
|
|
29873
|
+
console.warn("TextureAtlasSkin: skinned part not found / not a CustomShaderMaterial on " + this.transform.name, part);
|
|
29874
|
+
continue;
|
|
29875
|
+
}
|
|
29876
|
+
let material = slot.material;
|
|
29877
|
+
const isVat = (material instanceof VertexAnimationMaterial);
|
|
29878
|
+
const kind = isVat ? "vat" : (isInstanced ? "instanced" : "regular");
|
|
29879
|
+
if (kind === "regular") {
|
|
29880
|
+
material = this.cloneForRegular(mesh, slot, material);
|
|
29881
|
+
}
|
|
29882
|
+
this.configureMaterial(material, manifest, kind);
|
|
29883
|
+
this._targets.push({ material: material, kind: kind });
|
|
29884
|
+
console.warn(">>> TextureAtlasSkin: " + this.transform.name + " — part '" + material.name + "' → " + this.describeKind(kind) + " setup");
|
|
29885
|
+
}
|
|
29886
|
+
this.applyIndexToTargets(mesh, this._currentIndex);
|
|
29887
|
+
this._applied = true;
|
|
29888
|
+
}
|
|
29889
|
+
setSkinIndex(index) {
|
|
29890
|
+
const requested = this.toInt(index, 0);
|
|
29891
|
+
this._currentIndex = this.clampIndex(requested, "skin index");
|
|
29892
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
29893
|
+
this.applyIndexToTargets(mesh, this._currentIndex);
|
|
29894
|
+
return this._currentIndex;
|
|
29895
|
+
}
|
|
29896
|
+
clampIndex(index, label) {
|
|
29897
|
+
const count = this.skinCount();
|
|
29898
|
+
const max = Math.max(0, count - 1);
|
|
29899
|
+
const clamped = (index < 0) ? 0 : (index > max ? max : index);
|
|
29900
|
+
if (clamped !== index) {
|
|
29901
|
+
console.warn("TextureAtlasSkin: " + label + " " + index + " out of range [0, " + max + "] on " + this.transform.name + " — clamped to " + clamped);
|
|
29902
|
+
}
|
|
29903
|
+
return clamped;
|
|
29904
|
+
}
|
|
29905
|
+
skinCount() {
|
|
29906
|
+
const m = this._manifest;
|
|
29907
|
+
if (m == null)
|
|
29908
|
+
return this.maxChannelSliceCount();
|
|
29909
|
+
const skins = m.skins || [];
|
|
29910
|
+
if (skins.length > 0)
|
|
29911
|
+
return skins.length;
|
|
29912
|
+
const c = this.toInt(m.count, 0);
|
|
29913
|
+
if (c > 0)
|
|
29914
|
+
return c;
|
|
29915
|
+
return this.maxChannelSliceCount();
|
|
29916
|
+
}
|
|
29917
|
+
maxChannelSliceCount() {
|
|
29918
|
+
const lens = [this.albedoSlices, this.normalSlices, this.metallicSlices, this.occlusionSlices, this.emissiveSlices]
|
|
29919
|
+
.map((s) => (s != null) ? s.length : 0);
|
|
29920
|
+
return Math.max(0, lens[0], lens[1], lens[2], lens[3], lens[4]);
|
|
29921
|
+
}
|
|
29922
|
+
getSkinIndex() {
|
|
29923
|
+
return this._currentIndex;
|
|
29924
|
+
}
|
|
29925
|
+
configureMaterial(material, manifest, kind) {
|
|
29926
|
+
const shared = (kind !== "regular");
|
|
29927
|
+
if (shared && this.isConfigured(material))
|
|
29928
|
+
return;
|
|
29929
|
+
if (shared)
|
|
29930
|
+
this.markConfigured(material);
|
|
29931
|
+
if (kind === "instanced")
|
|
29932
|
+
this.ensureSkinLayerBuffer(this.abtractMesh || this.getAbstractMesh());
|
|
29933
|
+
const albedoUrls = this.albedoChannelUrls(manifest);
|
|
29934
|
+
const normalUrls = this.normalChannelUrls(manifest);
|
|
29935
|
+
const mrUrls = this.metalRoughChannelUrls(manifest);
|
|
29936
|
+
const emissiveUrls = this.emissiveChannelUrls(manifest);
|
|
29937
|
+
const has = (u) => (u != null && u.length > 0);
|
|
29938
|
+
if (!has(albedoUrls) && !has(normalUrls) && !has(mrUrls) && !has(emissiveUrls)) {
|
|
29939
|
+
console.warn("TextureAtlasSkin: no channel slices to build a skin array on " + this.transform.name);
|
|
29940
|
+
return;
|
|
29941
|
+
}
|
|
29942
|
+
if (kind !== "vat")
|
|
29943
|
+
material.setSkinArrayLayerMode(kind === "regular");
|
|
29944
|
+
const build = (urls, mipped) => has(urls) ? SkinTextureArray.Build(this.scene, urls, mipped ? {} : { mipmaps: false }) : Promise.resolve(null);
|
|
29945
|
+
Promise.all([build(albedoUrls, true), build(normalUrls, false), build(mrUrls, true), build(emissiveUrls, true)])
|
|
29946
|
+
.then(([albTex, nrmTex, mrTex, emisTex]) => {
|
|
29947
|
+
const vmat = (kind === "vat") ? material : null;
|
|
29948
|
+
if (albTex != null) {
|
|
29949
|
+
material.addTextureArrayUniform("tkAlbedoArray", albTex);
|
|
29950
|
+
if (vmat != null)
|
|
29951
|
+
vmat.enableVatSkinArray();
|
|
29952
|
+
else
|
|
29953
|
+
material.enableSkinArray(kind === "regular");
|
|
29954
|
+
}
|
|
29955
|
+
if (nrmTex != null) {
|
|
29956
|
+
material.addTextureArrayUniform("tkNormalArray", nrmTex);
|
|
29957
|
+
if (vmat != null)
|
|
29958
|
+
vmat.enableVatSkinArrayNormal();
|
|
29959
|
+
else
|
|
29960
|
+
material.enableSkinArrayNormal();
|
|
29961
|
+
}
|
|
29962
|
+
if (mrTex != null) {
|
|
29963
|
+
material.addTextureArrayUniform("tkMetalRoughArray", mrTex);
|
|
29964
|
+
if (vmat != null)
|
|
29965
|
+
vmat.enableVatSkinArrayMetalRough();
|
|
29966
|
+
else
|
|
29967
|
+
material.enableSkinArrayMetalRough();
|
|
29968
|
+
}
|
|
29969
|
+
if (emisTex != null) {
|
|
29970
|
+
material.addTextureArrayUniform("tkEmissiveArray", emisTex);
|
|
29971
|
+
if (vmat != null)
|
|
29972
|
+
vmat.enableVatSkinArrayEmissive();
|
|
29973
|
+
else
|
|
29974
|
+
material.enableSkinArrayEmissive();
|
|
29975
|
+
}
|
|
29976
|
+
if (albTex == null && nrmTex == null && mrTex == null && emisTex == null) {
|
|
29977
|
+
console.warn("TextureAtlasSkin: all channel arrays failed to build on " + this.transform.name);
|
|
29978
|
+
return;
|
|
29979
|
+
}
|
|
29980
|
+
this.applyLayerToMaterial(material, kind, this._currentIndex);
|
|
29981
|
+
});
|
|
29982
|
+
}
|
|
29983
|
+
albedoChannelUrls(manifest) {
|
|
29984
|
+
const fromSlices = this.sliceUrls(this.albedoSlices);
|
|
29985
|
+
if (fromSlices != null)
|
|
29986
|
+
return fromSlices;
|
|
29987
|
+
const layers = (manifest != null) ? manifest.albedoLayers : null;
|
|
29988
|
+
if (Array.isArray(layers)) {
|
|
29989
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
29990
|
+
return (out.length > 0) ? out : null;
|
|
29991
|
+
}
|
|
29992
|
+
return null;
|
|
29993
|
+
}
|
|
29994
|
+
normalChannelUrls(manifest) {
|
|
29995
|
+
const fromSlices = this.sliceUrls(this.normalSlices);
|
|
29996
|
+
if (fromSlices != null)
|
|
29997
|
+
return fromSlices;
|
|
29998
|
+
const layers = (manifest != null) ? manifest.normalLayers : null;
|
|
29999
|
+
if (Array.isArray(layers)) {
|
|
30000
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30001
|
+
return (out.length > 0) ? out : null;
|
|
30002
|
+
}
|
|
30003
|
+
return null;
|
|
30004
|
+
}
|
|
30005
|
+
metalRoughChannelUrls(manifest) {
|
|
30006
|
+
const fromSlices = this.sliceUrls(this.metallicSlices);
|
|
30007
|
+
if (fromSlices != null)
|
|
30008
|
+
return fromSlices;
|
|
30009
|
+
const layers = (manifest != null) ? manifest.metalRoughLayers : null;
|
|
30010
|
+
if (Array.isArray(layers)) {
|
|
30011
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30012
|
+
return (out.length > 0) ? out : null;
|
|
30013
|
+
}
|
|
30014
|
+
return null;
|
|
30015
|
+
}
|
|
30016
|
+
emissiveChannelUrls(manifest) {
|
|
30017
|
+
const fromSlices = this.sliceUrls(this.emissiveSlices);
|
|
30018
|
+
if (fromSlices != null)
|
|
30019
|
+
return fromSlices;
|
|
30020
|
+
const layers = (manifest != null) ? manifest.emissiveLayers : null;
|
|
30021
|
+
if (Array.isArray(layers)) {
|
|
30022
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30023
|
+
return (out.length > 0) ? out : null;
|
|
30024
|
+
}
|
|
30025
|
+
return null;
|
|
30026
|
+
}
|
|
30027
|
+
sliceUrls(slices) {
|
|
30028
|
+
if (slices == null || slices.length === 0)
|
|
30029
|
+
return null;
|
|
30030
|
+
const root = SceneManager.GetRootUrl(this.scene) || "";
|
|
30031
|
+
const urls = [];
|
|
30032
|
+
for (const s of slices) {
|
|
30033
|
+
if (s == null)
|
|
30034
|
+
continue;
|
|
30035
|
+
const anyS = s;
|
|
30036
|
+
let u = null;
|
|
30037
|
+
if (anyS.url != null && String(anyS.url).length > 0)
|
|
30038
|
+
u = String(anyS.url);
|
|
30039
|
+
else if (anyS.filename != null && String(anyS.filename).length > 0)
|
|
30040
|
+
u = root + String(anyS.filename);
|
|
30041
|
+
if (u != null && u.length > 0)
|
|
30042
|
+
urls.push(u);
|
|
30043
|
+
}
|
|
30044
|
+
return (urls.length > 0) ? urls : null;
|
|
30045
|
+
}
|
|
30046
|
+
resolveLayerUrl(filename) {
|
|
30047
|
+
if (filename == null)
|
|
30048
|
+
return "";
|
|
30049
|
+
const f = String(filename);
|
|
30050
|
+
if (/^(https?:|blob:|data:|\/)/i.test(f))
|
|
30051
|
+
return f;
|
|
30052
|
+
const root = SceneManager.GetRootUrl(this.scene) || "";
|
|
30053
|
+
return root + f;
|
|
30054
|
+
}
|
|
30055
|
+
applyIndexToTargets(mesh, index) {
|
|
30056
|
+
if (mesh == null)
|
|
30057
|
+
return;
|
|
30058
|
+
for (const t of this._targets) {
|
|
30059
|
+
this.applyLayerToMaterial(t.material, t.kind, index);
|
|
30060
|
+
}
|
|
30061
|
+
}
|
|
30062
|
+
applyLayerToMaterial(material, kind, index) {
|
|
30063
|
+
if (kind === "vat") {
|
|
30064
|
+
VertexAnimationController.SetAtlasCellIndex(this.abtractMesh || this.getAbstractMesh(), index);
|
|
30065
|
+
}
|
|
30066
|
+
else if (kind === "instanced") {
|
|
30067
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
30068
|
+
this.ensureSkinLayerBuffer(mesh);
|
|
30069
|
+
mesh.instancedBuffers.tkSkinLayer = index;
|
|
30070
|
+
}
|
|
30071
|
+
else {
|
|
30072
|
+
material.setSkinLayer(index);
|
|
30073
|
+
}
|
|
30074
|
+
}
|
|
30075
|
+
isInstancedSetup(mesh) {
|
|
30076
|
+
if (mesh instanceof InstancedMesh)
|
|
30077
|
+
return true;
|
|
30078
|
+
const src = (mesh instanceof Mesh) ? mesh : null;
|
|
30079
|
+
return (src != null && src.instances != null && src.instances.length > 0);
|
|
30080
|
+
}
|
|
30081
|
+
ensureSkinLayerBuffer(mesh) {
|
|
30082
|
+
const inst = mesh;
|
|
30083
|
+
const src = (inst != null && inst.sourceMesh != null) ? inst.sourceMesh : mesh;
|
|
30084
|
+
const target = (src != null) ? src : mesh;
|
|
30085
|
+
if (target != null && typeof target.registerInstancedBuffer === "function") {
|
|
30086
|
+
const ib = target.instancedBuffers;
|
|
30087
|
+
if (ib == null || ib.tkSkinLayer === undefined) {
|
|
30088
|
+
target.registerInstancedBuffer("tkSkinLayer", 1);
|
|
30089
|
+
target.instancedBuffers = target.instancedBuffers || {};
|
|
30090
|
+
target.instancedBuffers.tkSkinLayer = 0;
|
|
30091
|
+
}
|
|
30092
|
+
}
|
|
30093
|
+
mesh.instancedBuffers = mesh.instancedBuffers || {};
|
|
30094
|
+
}
|
|
30095
|
+
getMeshSlots(mesh) {
|
|
30096
|
+
const slots = [];
|
|
30097
|
+
const mat = mesh.material;
|
|
30098
|
+
if (mat instanceof MultiMaterial) {
|
|
30099
|
+
const subs = mat.subMaterials;
|
|
30100
|
+
for (let i = 0; i < subs.length; i++) {
|
|
30101
|
+
if (subs[i] != null)
|
|
30102
|
+
slots.push({ material: subs[i], mm: mat, index: i });
|
|
30103
|
+
}
|
|
30104
|
+
}
|
|
30105
|
+
else if (mat != null) {
|
|
30106
|
+
slots.push({ material: mat, mm: null, index: -1 });
|
|
30107
|
+
}
|
|
30108
|
+
return slots;
|
|
30109
|
+
}
|
|
30110
|
+
matchSlot(slots, targetMat, part) {
|
|
30111
|
+
if (targetMat != null) {
|
|
30112
|
+
for (const s of slots)
|
|
30113
|
+
if (s.material === targetMat)
|
|
30114
|
+
return s;
|
|
30115
|
+
}
|
|
30116
|
+
const name = this.partName(part) || (targetMat != null ? targetMat.name : null);
|
|
30117
|
+
if (name != null && name.length > 0) {
|
|
30118
|
+
for (const s of slots)
|
|
30119
|
+
if (s.material.name === name)
|
|
30120
|
+
return s;
|
|
30121
|
+
for (const s of slots)
|
|
30122
|
+
if (s.material.name.indexOf(name) !== -1)
|
|
30123
|
+
return s;
|
|
30124
|
+
}
|
|
30125
|
+
if (slots.length === 1)
|
|
30126
|
+
return slots[0];
|
|
30127
|
+
return null;
|
|
30128
|
+
}
|
|
30129
|
+
resolvePartMaterial(part) {
|
|
30130
|
+
if (part == null)
|
|
30131
|
+
return null;
|
|
30132
|
+
if (part instanceof Material)
|
|
30133
|
+
return part;
|
|
30134
|
+
if (part.skinPart != null)
|
|
30135
|
+
return this.resolvePartMaterial(part.skinPart);
|
|
30136
|
+
const name = this.partName(part);
|
|
30137
|
+
if (name == null)
|
|
30138
|
+
return null;
|
|
30139
|
+
let mat = this.scene.getMaterialByName(name);
|
|
30140
|
+
if (mat == null && SceneManager.GetMaterialWithName != null)
|
|
30141
|
+
mat = SceneManager.GetMaterialWithName(this.scene, name);
|
|
30142
|
+
return mat;
|
|
30143
|
+
}
|
|
30144
|
+
partName(part) {
|
|
30145
|
+
if (part == null)
|
|
30146
|
+
return null;
|
|
30147
|
+
if (typeof part === "string")
|
|
30148
|
+
return part;
|
|
30149
|
+
if (part instanceof Material)
|
|
30150
|
+
return part.name;
|
|
30151
|
+
if (part.skinPart != null)
|
|
30152
|
+
return this.partName(part.skinPart);
|
|
30153
|
+
if (part.name != null)
|
|
30154
|
+
return part.name;
|
|
30155
|
+
if (part.material != null)
|
|
30156
|
+
return this.partName(part.material);
|
|
30157
|
+
return null;
|
|
30158
|
+
}
|
|
30159
|
+
cloneForRegular(mesh, slot, material) {
|
|
30160
|
+
const tag = "_skin_" + (this.transform != null ? this.transform.name : "skin");
|
|
30161
|
+
const cloned = material.clone(material.name + tag);
|
|
30162
|
+
if (!(cloned instanceof CustomShaderMaterial)) {
|
|
30163
|
+
console.warn("TextureAtlasSkin: clone did not preserve CustomShaderMaterial — using original (skin may be shared)", cloned);
|
|
30164
|
+
return material;
|
|
30165
|
+
}
|
|
30166
|
+
if (slot.mm != null) {
|
|
30167
|
+
if (this._clonedMultiMaterial == null) {
|
|
30168
|
+
this._clonedMultiMaterial = slot.mm.clone(slot.mm.name + tag);
|
|
30169
|
+
mesh.material = this._clonedMultiMaterial;
|
|
30170
|
+
}
|
|
30171
|
+
this._clonedMultiMaterial.subMaterials[slot.index] = cloned;
|
|
30172
|
+
}
|
|
30173
|
+
else {
|
|
30174
|
+
mesh.material = cloned;
|
|
30175
|
+
}
|
|
30176
|
+
return cloned;
|
|
30177
|
+
}
|
|
30178
|
+
parseManifest() {
|
|
30179
|
+
let data = this.textureData;
|
|
30180
|
+
if (data == null)
|
|
30181
|
+
return null;
|
|
30182
|
+
if (typeof data === "string") {
|
|
30183
|
+
try {
|
|
30184
|
+
data = JSON.parse(data);
|
|
30185
|
+
}
|
|
30186
|
+
catch (e) {
|
|
30187
|
+
console.warn("TextureAtlasSkin: bad textureData JSON", e);
|
|
30188
|
+
return null;
|
|
30189
|
+
}
|
|
30190
|
+
}
|
|
30191
|
+
return (data != null && data.skins != null) ? data : null;
|
|
30192
|
+
}
|
|
30193
|
+
toInt(v, def) {
|
|
30194
|
+
const n = (typeof v === "number") ? v : parseInt(v, 10);
|
|
30195
|
+
return isNaN(n) ? def : Math.floor(n);
|
|
30196
|
+
}
|
|
30197
|
+
isConfigured(material) {
|
|
30198
|
+
return !!(material && material.metadata && material.metadata.atlasSkinConfigured === true);
|
|
30199
|
+
}
|
|
30200
|
+
markConfigured(material) {
|
|
30201
|
+
material.metadata = material.metadata || {};
|
|
30202
|
+
material.metadata.atlasSkinConfigured = true;
|
|
30203
|
+
}
|
|
30204
|
+
describeKind(kind) {
|
|
30205
|
+
if (kind === "vat")
|
|
30206
|
+
return "VAT Mesh (packed cell index)";
|
|
30207
|
+
if (kind === "instanced")
|
|
30208
|
+
return "Instanced Mesh (per-instance UV buffer)";
|
|
30209
|
+
return "Babylon Mesh (cloned material uniform)";
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
29248
30212
|
export class UserInterface extends ScriptComponent {
|
|
29249
30213
|
constructor(transform, scene, properties = {}, alias = "UserInterface") {
|
|
29250
30214
|
super(transform, scene, properties, alias);
|
|
@@ -30766,6 +31730,7 @@ SceneManager.RegisterClass("CustomShaderMaterial", CustomShaderMaterial);
|
|
|
30766
31730
|
SceneManager.RegisterClass("UniversalShaderMaterial", UniversalShaderMaterial);
|
|
30767
31731
|
SceneManager.RegisterClass("UnityStyleLightingPlugin", UnityStyleLightingPlugin);
|
|
30768
31732
|
SceneManager.RegisterClass("CustomShaderMaterialPlugin", CustomShaderMaterialPlugin);
|
|
31733
|
+
SceneManager.RegisterClass("SkinArraySwitchingPlugin", SkinArraySwitchingPlugin);
|
|
30769
31734
|
SceneManager.RegisterClass("StandardShaderMaterial", StandardShaderMaterial);
|
|
30770
31735
|
SceneManager.RegisterClass("StandardShaderMaterialPlugin", StandardShaderMaterialPlugin);
|
|
30771
31736
|
SceneManager.RegisterClass("UniversalTerrainMaterial", UniversalTerrainMaterial);
|
|
@@ -41398,7 +42363,9 @@ SceneManager.RegisterClass("NavigationAgent", NavigationAgent);
|
|
|
41398
42363
|
SceneManager.RegisterClass("PostProcessor", PostProcessor);
|
|
41399
42364
|
SceneManager.RegisterClass("RigidbodyPhysics", RigidbodyPhysics);
|
|
41400
42365
|
SceneManager.RegisterClass("ShurikenParticles", ShurikenParticles);
|
|
42366
|
+
SceneManager.RegisterClass("SkinTextureArray", SkinTextureArray);
|
|
41401
42367
|
SceneManager.RegisterClass("TerrainBuilder", TerrainBuilder);
|
|
42368
|
+
SceneManager.RegisterClass("TextureAtlasSkin", TextureAtlasSkin);
|
|
41402
42369
|
SceneManager.RegisterClass("UnitySlider", UnitySlider);
|
|
41403
42370
|
SceneManager.RegisterClass("UnityScrollBar", UnityScrollBar);
|
|
41404
42371
|
SceneManager.RegisterClass("UnityDropdownMenu", UnityDropdownMenu);
|