@babylonjs-toolkit/next 9.12.1 → 9.12.1011
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 +142 -40
- package/lib/scenemanager.d.ts.map +1 -1
- package/lib/scenemanager.js +1269 -310
- package/package.json +2 -1
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.12.
|
|
101
|
+
static get Version() { return "9.12.1011 - 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() {
|
|
@@ -3797,6 +3803,21 @@ export class CVTOOLS_unity_metadata {
|
|
|
3797
3803
|
internal._sphericalPolynomialComputed = true;
|
|
3798
3804
|
}
|
|
3799
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
|
+
}
|
|
3800
3821
|
constructor(loader) {
|
|
3801
3822
|
this.name = SceneManager.CVTOOLS_NAME;
|
|
3802
3823
|
this.enabled = false;
|
|
@@ -4154,6 +4175,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4154
4175
|
}
|
|
4155
4176
|
}
|
|
4156
4177
|
}
|
|
4178
|
+
const createPolynomialsFromFaces = scene.extras?.metadata?.createpolynomials ?? false;
|
|
4157
4179
|
if (this._reflectionMap != null && this._reflectionCache != null) {
|
|
4158
4180
|
let tindex = 0;
|
|
4159
4181
|
for (const key in this._reflectionMap) {
|
|
@@ -4173,7 +4195,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4173
4195
|
if (cachedCubeTexture != null) {
|
|
4174
4196
|
if (ctx.material != null && Utilities.HasOwnProperty(ctx.material, "reflectionTexture")) {
|
|
4175
4197
|
ctx.material.reflectionTexture = cachedCubeTexture;
|
|
4176
|
-
CVTOOLS_unity_metadata.
|
|
4198
|
+
CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(cachedCubeTexture, this._babylonScene, createPolynomialsFromFaces);
|
|
4177
4199
|
}
|
|
4178
4200
|
}
|
|
4179
4201
|
else {
|
|
@@ -4186,8 +4208,8 @@ export class CVTOOLS_unity_metadata {
|
|
|
4186
4208
|
buffer: bytes,
|
|
4187
4209
|
prefiltered: true,
|
|
4188
4210
|
forcedExtension: newCubeExtension,
|
|
4189
|
-
createPolynomials:
|
|
4190
|
-
onLoad: () => { CVTOOLS_unity_metadata.
|
|
4211
|
+
createPolynomials: createPolynomialsFromFaces,
|
|
4212
|
+
onLoad: () => { CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(newCubeTexture, this._babylonScene, createPolynomialsFromFaces); },
|
|
4191
4213
|
onError: (msg, ex) => console.error(msg, ex),
|
|
4192
4214
|
});
|
|
4193
4215
|
newCubeTexture.name = ctx.name;
|
|
@@ -4200,7 +4222,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4200
4222
|
this._reflectionCache[ctx.mapkey] = newCubeTexture;
|
|
4201
4223
|
if (ctx.material != null && Utilities.HasOwnProperty(ctx.material, "reflectionTexture")) {
|
|
4202
4224
|
ctx.material.reflectionTexture = newCubeTexture;
|
|
4203
|
-
CVTOOLS_unity_metadata.
|
|
4225
|
+
CVTOOLS_unity_metadata.ApplyGlobalReflectionProbeDiffuse(newCubeTexture, this._babylonScene, createPolynomialsFromFaces);
|
|
4204
4226
|
}
|
|
4205
4227
|
}
|
|
4206
4228
|
}
|
|
@@ -4605,28 +4627,19 @@ export class CVTOOLS_unity_metadata {
|
|
|
4605
4627
|
}
|
|
4606
4628
|
}
|
|
4607
4629
|
if (ascene._AmbientLight != null) {
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
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) {
|
|
4635
|
+
ascene._AmbientLight.name = "Ambient Blacklight";
|
|
4636
|
+
ascene._AmbientLight.diffuse = Color3.Black();
|
|
4611
4637
|
ascene._AmbientLight.specular = Color3.Black();
|
|
4612
|
-
ascene._AmbientLight.groundColor =
|
|
4613
|
-
|
|
4614
|
-
ascene._AmbientLight.intensity = metadata.ambientlightintensity;
|
|
4615
|
-
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4616
|
-
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4617
|
-
}
|
|
4618
|
-
else {
|
|
4619
|
-
if (metadata.ambientskycolor != null)
|
|
4620
|
-
ascene._AmbientLight.diffuse = Utilities.ParseColor3(metadata.ambientskycolor, Color3.Gray());
|
|
4621
|
-
if (metadata.ambientspecularcolor != null)
|
|
4622
|
-
ascene._AmbientLight.specular = Color3.Black();
|
|
4623
|
-
if (metadata.ambientgroundcolor != null)
|
|
4624
|
-
ascene._AmbientLight.groundColor = Utilities.ParseColor3(metadata.ambientgroundcolor, Color3.Gray());
|
|
4625
|
-
if (metadata.ambientlightintensity != null)
|
|
4626
|
-
ascene._AmbientLight.intensity = (metadata.ambientlightintensity * 0.5);
|
|
4627
|
-
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4628
|
-
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4638
|
+
ascene._AmbientLight.groundColor = Color3.Black();
|
|
4639
|
+
ascene._AmbientLight.intensity = 1.0;
|
|
4629
4640
|
}
|
|
4641
|
+
ascene._AmbientLight.intensity *= SceneManager.AmbientLightIntensity;
|
|
4642
|
+
ascene._AmbientLight.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
|
|
4630
4643
|
}
|
|
4631
4644
|
}
|
|
4632
4645
|
if (metadata.fogmode != null) {
|
|
@@ -4844,7 +4857,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
4844
4857
|
const IBL_MAX = 10.0;
|
|
4845
4858
|
const LEVEL_MAX = 1000.0;
|
|
4846
4859
|
const derivedRefl = (refl != null) ? refl : (ibl * lvl);
|
|
4847
|
-
const diffuseIbl =
|
|
4860
|
+
const diffuseIbl = Scalar.Clamp(ibl, 0.0, IBL_MAX);
|
|
4848
4861
|
const specIbl = Scalar.Clamp(derivedRefl, 0.0, LEVEL_MAX);
|
|
4849
4862
|
const hasDiffuseIbl = Array.isArray(environment.sh) && environment.sh.length === 27;
|
|
4850
4863
|
const useUnitySH = (mode === 0 && hasDiffuseIbl === true);
|
|
@@ -5483,6 +5496,7 @@ export class CVTOOLS_unity_metadata {
|
|
|
5483
5496
|
CVTOOLS_unity_metadata.IBL_TINY_VALUE = 0.001;
|
|
5484
5497
|
CVTOOLS_unity_metadata.IBL_SPEC_FACTOR = 1.0;
|
|
5485
5498
|
CVTOOLS_unity_metadata.IBL_PROBE_FACTOR = 1.0;
|
|
5499
|
+
CVTOOLS_unity_metadata._boxProjectionShaderPatched = false;
|
|
5486
5500
|
CVTOOLS_unity_metadata.ScriptBundleCache = {};
|
|
5487
5501
|
export class CVTOOLS_babylon_mesh {
|
|
5488
5502
|
constructor(loader) {
|
|
@@ -5530,10 +5544,18 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5530
5544
|
this.shader = null;
|
|
5531
5545
|
this.plugin = null;
|
|
5532
5546
|
this._unityLightingPlugin = null;
|
|
5547
|
+
this._skinArray = false;
|
|
5548
|
+
this._skinArrayNormal = false;
|
|
5549
|
+
this._skinArrayMetalRough = false;
|
|
5550
|
+
this._skinArrayEmissive = false;
|
|
5551
|
+
this._skinLayerUniform = false;
|
|
5552
|
+
this._skinArraySwitchingPlugin = null;
|
|
5533
5553
|
this.shader = "CustomShaderMaterial";
|
|
5534
5554
|
this.addFloatUniform("tkIblDiffuseScale", 1.0);
|
|
5535
5555
|
this.addFloatUniform("tkIblSpecularScale", 1.0);
|
|
5556
|
+
this.addFloatUniform("tkSkinLayerUni", 0.0);
|
|
5536
5557
|
this._unityLightingPlugin = new UnityStyleLightingPlugin(this, this.shader);
|
|
5558
|
+
this._skinArraySwitchingPlugin = new SkinArraySwitchingPlugin(this);
|
|
5537
5559
|
}
|
|
5538
5560
|
initMaterial() {
|
|
5539
5561
|
if (this["awake"])
|
|
@@ -5567,6 +5589,108 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5567
5589
|
this.plugin?.markAllDefinesAsDirty();
|
|
5568
5590
|
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5569
5591
|
}
|
|
5592
|
+
enableSkinArray(layerUniform = false) {
|
|
5593
|
+
this._skinArray = true;
|
|
5594
|
+
this._skinLayerUniform = layerUniform;
|
|
5595
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5596
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5597
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5598
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5599
|
+
return this;
|
|
5600
|
+
}
|
|
5601
|
+
setSkinLayer(layer) {
|
|
5602
|
+
this._skinLayerUniform = true;
|
|
5603
|
+
this.setFloatValue("tkSkinLayerUni", Math.max(0, Math.floor(layer)));
|
|
5604
|
+
return this;
|
|
5605
|
+
}
|
|
5606
|
+
enableSkinArrayNormal(enabled = true) {
|
|
5607
|
+
this._skinArrayNormal = enabled;
|
|
5608
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5609
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5610
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5611
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5612
|
+
return this;
|
|
5613
|
+
}
|
|
5614
|
+
enableSkinArrayMetalRough(enabled = true) {
|
|
5615
|
+
this._skinArrayMetalRough = enabled;
|
|
5616
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5617
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5618
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5619
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5620
|
+
return this;
|
|
5621
|
+
}
|
|
5622
|
+
enableSkinArrayEmissive(enabled = true) {
|
|
5623
|
+
this._skinArrayEmissive = enabled;
|
|
5624
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5625
|
+
this.plugin?.markAllDefinesAsDirty();
|
|
5626
|
+
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5627
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5628
|
+
return this;
|
|
5629
|
+
}
|
|
5630
|
+
setSkinArrayLayerMode(uniform) {
|
|
5631
|
+
this._skinLayerUniform = uniform;
|
|
5632
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5633
|
+
this._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5634
|
+
return this;
|
|
5635
|
+
}
|
|
5636
|
+
addTextureArrayUniform(name, texture) {
|
|
5637
|
+
if (this._samplers.indexOf(name) === -1)
|
|
5638
|
+
this._samplers.push(name);
|
|
5639
|
+
this._textures[name] = texture;
|
|
5640
|
+
this.markTextureAsRaw(name);
|
|
5641
|
+
return this;
|
|
5642
|
+
}
|
|
5643
|
+
get skinArray() { return this._skinArray; }
|
|
5644
|
+
get skinArrayNormal() { return this._skinArrayNormal; }
|
|
5645
|
+
get skinArrayMetalRough() { return this._skinArrayMetalRough; }
|
|
5646
|
+
get skinArrayEmissive() { return this._skinArrayEmissive; }
|
|
5647
|
+
get skinArrayActive() {
|
|
5648
|
+
return this._skinArray || this._skinArrayNormal || this._skinArrayMetalRough || this._skinArrayEmissive;
|
|
5649
|
+
}
|
|
5650
|
+
get skinLayerUniform() { return this._skinLayerUniform; }
|
|
5651
|
+
clone(name, cloneTexturesOnlyOnce = true, rootUrl = "") {
|
|
5652
|
+
const scene = this.getScene();
|
|
5653
|
+
const ctor = this.constructor;
|
|
5654
|
+
const result = SerializationHelper.Clone(() => new ctor(name, scene), this, { cloneTexturesOnlyOnce });
|
|
5655
|
+
if (result == null)
|
|
5656
|
+
return result;
|
|
5657
|
+
result.id = name;
|
|
5658
|
+
result.name = name;
|
|
5659
|
+
if (this.stencil && result.stencil)
|
|
5660
|
+
this.stencil.copyTo(result.stencil);
|
|
5661
|
+
this.copyCustomStateTo(result);
|
|
5662
|
+
return result;
|
|
5663
|
+
}
|
|
5664
|
+
copyCustomStateTo(result) {
|
|
5665
|
+
result.universalMaterial = this.universalMaterial;
|
|
5666
|
+
result._defines = Object.assign({}, this._defines);
|
|
5667
|
+
result._uniforms = this._uniforms.slice();
|
|
5668
|
+
result._samplers = this._samplers.slice();
|
|
5669
|
+
result._attributes = this._attributes.slice();
|
|
5670
|
+
result._ubos = (this._ubos != null) ? this._ubos.map((u) => ({ name: u.name, size: u.size, type: u.type, arraySize: u.arraySize })) : null;
|
|
5671
|
+
result._textures = Object.assign({}, this._textures);
|
|
5672
|
+
result._noMatrixTextures = (this._noMatrixTextures != null) ? new Set(this._noMatrixTextures) : null;
|
|
5673
|
+
result._vectors4 = {};
|
|
5674
|
+
for (const n in this._vectors4)
|
|
5675
|
+
result._vectors4[n] = this._vectors4[n].clone();
|
|
5676
|
+
result._vectors3 = {};
|
|
5677
|
+
for (const n in this._vectors3)
|
|
5678
|
+
result._vectors3[n] = this._vectors3[n].clone();
|
|
5679
|
+
result._vectors2 = {};
|
|
5680
|
+
for (const n in this._vectors2)
|
|
5681
|
+
result._vectors2[n] = this._vectors2[n].clone();
|
|
5682
|
+
result._floats = Object.assign({}, this._floats);
|
|
5683
|
+
result._bools = Object.assign({}, this._bools);
|
|
5684
|
+
result._skinArray = this._skinArray;
|
|
5685
|
+
result._skinArrayNormal = this._skinArrayNormal;
|
|
5686
|
+
result._skinArrayMetalRough = this._skinArrayMetalRough;
|
|
5687
|
+
result._skinArrayEmissive = this._skinArrayEmissive;
|
|
5688
|
+
result._skinLayerUniform = this._skinLayerUniform;
|
|
5689
|
+
result.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
5690
|
+
result.plugin?.markAllDefinesAsDirty();
|
|
5691
|
+
result._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5692
|
+
result._skinArraySwitchingPlugin?.markAllDefinesAsDirty();
|
|
5693
|
+
}
|
|
5570
5694
|
addTextureUniform(name, texture) {
|
|
5571
5695
|
this.checkSampler(name, texture);
|
|
5572
5696
|
this._textures[name] = texture;
|
|
@@ -6009,6 +6133,301 @@ export class UnityStyleLightingPlugin extends CustomShaderMaterialPlugin {
|
|
|
6009
6133
|
this.getCustomShaderMaterial().updateCustomBindings(uniformBuffer);
|
|
6010
6134
|
}
|
|
6011
6135
|
}
|
|
6136
|
+
export class SkinArraySwitchingPlugin extends CustomShaderMaterialPlugin {
|
|
6137
|
+
constructor(material) {
|
|
6138
|
+
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);
|
|
6139
|
+
}
|
|
6140
|
+
isCompatible(shaderLanguage) {
|
|
6141
|
+
return (shaderLanguage === ShaderLanguage.WGSL || shaderLanguage === ShaderLanguage.GLSL);
|
|
6142
|
+
}
|
|
6143
|
+
getClassName() {
|
|
6144
|
+
return "SkinArraySwitchingPlugin";
|
|
6145
|
+
}
|
|
6146
|
+
getAttributes(attributes, scene, mesh) {
|
|
6147
|
+
const mat = this.getCustomShaderMaterial();
|
|
6148
|
+
if (!mat.skinArrayActive)
|
|
6149
|
+
return;
|
|
6150
|
+
if (mat.skinLayerUniform !== true && attributes.indexOf("tkSkinLayer") === -1)
|
|
6151
|
+
attributes.push("tkSkinLayer");
|
|
6152
|
+
}
|
|
6153
|
+
getSamplers(samplers) {
|
|
6154
|
+
const mat = this.getCustomShaderMaterial();
|
|
6155
|
+
if (!mat.skinArrayActive)
|
|
6156
|
+
return;
|
|
6157
|
+
const customSamplers = mat.getCustomSamplers();
|
|
6158
|
+
if (customSamplers != null) {
|
|
6159
|
+
for (const s of customSamplers)
|
|
6160
|
+
if (samplers.indexOf(s) === -1)
|
|
6161
|
+
samplers.push(s);
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
prepareDefines(defines, scene, mesh) {
|
|
6165
|
+
const mat = this.getCustomShaderMaterial();
|
|
6166
|
+
defines.TOOLKIT_SKIN_ARRAY = !!mat.skinArrayActive;
|
|
6167
|
+
defines.TOOLKIT_SKIN_LAYER_UNIFORM = !!mat.skinLayerUniform;
|
|
6168
|
+
defines.TOOLKIT_SKIN_ARRAY_ALBEDO = !!mat.skinArray;
|
|
6169
|
+
defines.TOOLKIT_SKIN_ARRAY_NORMAL = !!mat.skinArrayNormal;
|
|
6170
|
+
defines.TOOLKIT_SKIN_ARRAY_MR = !!mat.skinArrayMetalRough;
|
|
6171
|
+
defines.TOOLKIT_SKIN_ARRAY_EMISSIVE = !!mat.skinArrayEmissive;
|
|
6172
|
+
}
|
|
6173
|
+
getCustomCode(shaderType, shaderLanguage) {
|
|
6174
|
+
const wgsl = (shaderLanguage === ShaderLanguage.WGSL);
|
|
6175
|
+
if (shaderType === "vertex") {
|
|
6176
|
+
if (wgsl) {
|
|
6177
|
+
return {
|
|
6178
|
+
CUSTOM_VERTEX_DEFINITIONS: this.getWGSLVertexDefinitions(),
|
|
6179
|
+
CUSTOM_VERTEX_MAIN_END: this.getWGSLVertexMainEnd()
|
|
6180
|
+
};
|
|
6181
|
+
}
|
|
6182
|
+
return {
|
|
6183
|
+
CUSTOM_VERTEX_DEFINITIONS: this.getGLSLVertexDefinitions(),
|
|
6184
|
+
CUSTOM_VERTEX_MAIN_END: this.getGLSLVertexMainEnd()
|
|
6185
|
+
};
|
|
6186
|
+
}
|
|
6187
|
+
if (shaderType === "fragment") {
|
|
6188
|
+
if (wgsl) {
|
|
6189
|
+
return {
|
|
6190
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getWGSLFragmentDefinitions(),
|
|
6191
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getWGSLAlbedoCode() + this.getWGSLMetalRoughSampleCode(),
|
|
6192
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getWGSLNormalCode(),
|
|
6193
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getWGSLMetalRoughApplyCode(),
|
|
6194
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getWGSLEmissiveCode()
|
|
6195
|
+
};
|
|
6196
|
+
}
|
|
6197
|
+
return {
|
|
6198
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getGLSLFragmentDefinitions(),
|
|
6199
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getGLSLAlbedoCode() + this.getGLSLMetalRoughSampleCode(),
|
|
6200
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getGLSLNormalCode(),
|
|
6201
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getGLSLMetalRoughApplyCode(),
|
|
6202
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getGLSLEmissiveCode()
|
|
6203
|
+
};
|
|
6204
|
+
}
|
|
6205
|
+
return null;
|
|
6206
|
+
}
|
|
6207
|
+
getGLSLVertexDefinitions() {
|
|
6208
|
+
return `
|
|
6209
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6210
|
+
#ifndef TOOLKIT_SKIN_V_DEFINED
|
|
6211
|
+
#define TOOLKIT_SKIN_V_DEFINED
|
|
6212
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6213
|
+
uniform float tkSkinLayerUni;
|
|
6214
|
+
#else
|
|
6215
|
+
attribute float tkSkinLayer;
|
|
6216
|
+
#endif
|
|
6217
|
+
varying float vSkinLayer;
|
|
6218
|
+
varying vec2 vSkinUV;
|
|
6219
|
+
#endif
|
|
6220
|
+
#endif
|
|
6221
|
+
`;
|
|
6222
|
+
}
|
|
6223
|
+
getGLSLVertexMainEnd() {
|
|
6224
|
+
return `
|
|
6225
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6226
|
+
#ifdef UV1
|
|
6227
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6228
|
+
vSkinLayer = tkSkinLayerUni;
|
|
6229
|
+
#else
|
|
6230
|
+
vSkinLayer = tkSkinLayer;
|
|
6231
|
+
#endif
|
|
6232
|
+
vSkinUV = uv;
|
|
6233
|
+
#else
|
|
6234
|
+
vSkinLayer = 0.0;
|
|
6235
|
+
vSkinUV = vec2(0.0);
|
|
6236
|
+
#endif
|
|
6237
|
+
#endif
|
|
6238
|
+
`;
|
|
6239
|
+
}
|
|
6240
|
+
getGLSLFragmentDefinitions() {
|
|
6241
|
+
return `
|
|
6242
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6243
|
+
#ifndef TOOLKIT_SKIN_F_DEFINED
|
|
6244
|
+
#define TOOLKIT_SKIN_F_DEFINED
|
|
6245
|
+
varying float vSkinLayer;
|
|
6246
|
+
varying vec2 vSkinUV;
|
|
6247
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6248
|
+
uniform sampler2DArray tkAlbedoArray;
|
|
6249
|
+
#endif
|
|
6250
|
+
#ifdef TOOLKIT_SKIN_ARRAY_NORMAL
|
|
6251
|
+
uniform sampler2DArray tkNormalArray;
|
|
6252
|
+
#endif
|
|
6253
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6254
|
+
uniform sampler2DArray tkMetalRoughArray;
|
|
6255
|
+
vec2 _tkMR;
|
|
6256
|
+
#endif
|
|
6257
|
+
#ifdef TOOLKIT_SKIN_ARRAY_EMISSIVE
|
|
6258
|
+
uniform sampler2DArray tkEmissiveArray;
|
|
6259
|
+
#endif
|
|
6260
|
+
#endif
|
|
6261
|
+
#endif
|
|
6262
|
+
`;
|
|
6263
|
+
}
|
|
6264
|
+
getGLSLAlbedoCode() {
|
|
6265
|
+
return `
|
|
6266
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6267
|
+
{
|
|
6268
|
+
float _tkLayer = floor(vSkinLayer + 0.5);
|
|
6269
|
+
vec4 _tkAlb = texture(tkAlbedoArray, vec3(vSkinUV, _tkLayer));
|
|
6270
|
+
#ifdef GAMMAALBEDO
|
|
6271
|
+
surfaceAlbedo = toLinearSpace(_tkAlb.rgb) * vAlbedoColor.rgb;
|
|
6272
|
+
#else
|
|
6273
|
+
surfaceAlbedo = _tkAlb.rgb * vAlbedoColor.rgb;
|
|
6274
|
+
#endif
|
|
6275
|
+
#ifdef ALPHATEST
|
|
6276
|
+
if (_tkAlb.a < alphaCutOff) discard;
|
|
6277
|
+
#endif
|
|
6278
|
+
}
|
|
6279
|
+
#endif
|
|
6280
|
+
`;
|
|
6281
|
+
}
|
|
6282
|
+
getGLSLNormalCode() {
|
|
6283
|
+
return `
|
|
6284
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
6285
|
+
{
|
|
6286
|
+
vec3 _tkNrmTexel = texture(tkNormalArray, vec3(vSkinUV, floor(vSkinLayer + 0.5))).xyz;
|
|
6287
|
+
normalW = perturbNormal(vTBN, _tkNrmTexel, vBumpInfos.y);
|
|
6288
|
+
}
|
|
6289
|
+
#endif
|
|
6290
|
+
`;
|
|
6291
|
+
}
|
|
6292
|
+
getGLSLMetalRoughSampleCode() {
|
|
6293
|
+
return `
|
|
6294
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6295
|
+
{
|
|
6296
|
+
vec4 _tkMRtexel = texture(tkMetalRoughArray, vec3(vSkinUV, floor(vSkinLayer + 0.5)));
|
|
6297
|
+
_tkMR = vec2(_tkMRtexel.b, _tkMRtexel.g);
|
|
6298
|
+
}
|
|
6299
|
+
#endif
|
|
6300
|
+
`;
|
|
6301
|
+
}
|
|
6302
|
+
getGLSLMetalRoughApplyCode() {
|
|
6303
|
+
return `
|
|
6304
|
+
#if defined(TOOLKIT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
6305
|
+
metallicRoughness.r = _tkMR.x;
|
|
6306
|
+
metallicRoughness.g = _tkMR.y;
|
|
6307
|
+
#endif
|
|
6308
|
+
`;
|
|
6309
|
+
}
|
|
6310
|
+
getGLSLEmissiveCode() {
|
|
6311
|
+
return `
|
|
6312
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_EMISSIVE)
|
|
6313
|
+
{
|
|
6314
|
+
vec3 _tkEmis = texture(tkEmissiveArray, vec3(vSkinUV, floor(vSkinLayer + 0.5))).rgb;
|
|
6315
|
+
finalEmissive = toLinearSpace(_tkEmis);
|
|
6316
|
+
}
|
|
6317
|
+
#endif
|
|
6318
|
+
`;
|
|
6319
|
+
}
|
|
6320
|
+
getWGSLVertexDefinitions() {
|
|
6321
|
+
return `
|
|
6322
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6323
|
+
#ifndef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6324
|
+
attribute tkSkinLayer: f32;
|
|
6325
|
+
#endif
|
|
6326
|
+
varying vSkinLayer: f32;
|
|
6327
|
+
varying vSkinUV: vec2<f32>;
|
|
6328
|
+
#endif
|
|
6329
|
+
`;
|
|
6330
|
+
}
|
|
6331
|
+
getWGSLVertexMainEnd() {
|
|
6332
|
+
return `
|
|
6333
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6334
|
+
#ifdef UV1
|
|
6335
|
+
#ifdef TOOLKIT_SKIN_LAYER_UNIFORM
|
|
6336
|
+
vertexOutputs.vSkinLayer = uniforms.tkSkinLayerUni;
|
|
6337
|
+
#else
|
|
6338
|
+
vertexOutputs.vSkinLayer = vertexInputs.tkSkinLayer;
|
|
6339
|
+
#endif
|
|
6340
|
+
vertexOutputs.vSkinUV = vertexInputs.uv;
|
|
6341
|
+
#else
|
|
6342
|
+
vertexOutputs.vSkinLayer = 0.0;
|
|
6343
|
+
vertexOutputs.vSkinUV = vec2f(0.0);
|
|
6344
|
+
#endif
|
|
6345
|
+
#endif
|
|
6346
|
+
`;
|
|
6347
|
+
}
|
|
6348
|
+
getWGSLFragmentDefinitions() {
|
|
6349
|
+
return `
|
|
6350
|
+
#ifdef TOOLKIT_SKIN_ARRAY
|
|
6351
|
+
varying vSkinLayer: f32;
|
|
6352
|
+
varying vSkinUV: vec2<f32>;
|
|
6353
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6354
|
+
var tkAlbedoArray: texture_2d_array<f32>;
|
|
6355
|
+
var tkAlbedoArraySampler: sampler;
|
|
6356
|
+
#endif
|
|
6357
|
+
#ifdef TOOLKIT_SKIN_ARRAY_NORMAL
|
|
6358
|
+
var tkNormalArray: texture_2d_array<f32>;
|
|
6359
|
+
var tkNormalArraySampler: sampler;
|
|
6360
|
+
#endif
|
|
6361
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6362
|
+
var tkMetalRoughArray: texture_2d_array<f32>;
|
|
6363
|
+
var tkMetalRoughArraySampler: sampler;
|
|
6364
|
+
var<private> _tkMR: vec2<f32>;
|
|
6365
|
+
#endif
|
|
6366
|
+
#ifdef TOOLKIT_SKIN_ARRAY_EMISSIVE
|
|
6367
|
+
var tkEmissiveArray: texture_2d_array<f32>;
|
|
6368
|
+
var tkEmissiveArraySampler: sampler;
|
|
6369
|
+
#endif
|
|
6370
|
+
#endif
|
|
6371
|
+
`;
|
|
6372
|
+
}
|
|
6373
|
+
getWGSLAlbedoCode() {
|
|
6374
|
+
return `
|
|
6375
|
+
#ifdef TOOLKIT_SKIN_ARRAY_ALBEDO
|
|
6376
|
+
{
|
|
6377
|
+
let _tkLayer = i32(fragmentInputs.vSkinLayer + 0.5);
|
|
6378
|
+
let _tkAlb = textureSample(tkAlbedoArray, tkAlbedoArraySampler, fragmentInputs.vSkinUV, _tkLayer);
|
|
6379
|
+
#ifdef GAMMAALBEDO
|
|
6380
|
+
surfaceAlbedo = toLinearSpaceVec3(_tkAlb.rgb) * vAlbedoColor.rgb;
|
|
6381
|
+
#else
|
|
6382
|
+
surfaceAlbedo = _tkAlb.rgb * vAlbedoColor.rgb;
|
|
6383
|
+
#endif
|
|
6384
|
+
#ifdef ALPHATEST
|
|
6385
|
+
if (_tkAlb.a < alphaCutOff) { discard; }
|
|
6386
|
+
#endif
|
|
6387
|
+
}
|
|
6388
|
+
#endif
|
|
6389
|
+
`;
|
|
6390
|
+
}
|
|
6391
|
+
getWGSLNormalCode() {
|
|
6392
|
+
return `
|
|
6393
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
6394
|
+
{
|
|
6395
|
+
let _tkNrmTexel = textureSample(tkNormalArray, tkNormalArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5)).rgb;
|
|
6396
|
+
let _tkNrmTBN = mat3x3<f32>(fragmentInputs.vTBN0, fragmentInputs.vTBN1, fragmentInputs.vTBN2);
|
|
6397
|
+
normalW = perturbNormal(_tkNrmTBN, _tkNrmTexel, uniforms.vBumpInfos.y);
|
|
6398
|
+
}
|
|
6399
|
+
#endif
|
|
6400
|
+
`;
|
|
6401
|
+
}
|
|
6402
|
+
getWGSLMetalRoughSampleCode() {
|
|
6403
|
+
return `
|
|
6404
|
+
#ifdef TOOLKIT_SKIN_ARRAY_MR
|
|
6405
|
+
{
|
|
6406
|
+
let _tkMRtexel = textureSample(tkMetalRoughArray, tkMetalRoughArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5));
|
|
6407
|
+
_tkMR = vec2<f32>(_tkMRtexel.b, _tkMRtexel.g);
|
|
6408
|
+
}
|
|
6409
|
+
#endif
|
|
6410
|
+
`;
|
|
6411
|
+
}
|
|
6412
|
+
getWGSLMetalRoughApplyCode() {
|
|
6413
|
+
return `
|
|
6414
|
+
#if defined(TOOLKIT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
6415
|
+
metallicRoughness.r = _tkMR.x;
|
|
6416
|
+
metallicRoughness.g = _tkMR.y;
|
|
6417
|
+
#endif
|
|
6418
|
+
`;
|
|
6419
|
+
}
|
|
6420
|
+
getWGSLEmissiveCode() {
|
|
6421
|
+
return `
|
|
6422
|
+
#if defined(TOOLKIT_SKIN_ARRAY) && defined(TOOLKIT_SKIN_ARRAY_EMISSIVE)
|
|
6423
|
+
{
|
|
6424
|
+
let _tkEmis = textureSample(tkEmissiveArray, tkEmissiveArraySampler, fragmentInputs.vSkinUV, i32(fragmentInputs.vSkinLayer + 0.5)).rgb;
|
|
6425
|
+
finalEmissive = toLinearSpaceVec3(_tkEmis);
|
|
6426
|
+
}
|
|
6427
|
+
#endif
|
|
6428
|
+
`;
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6012
6431
|
export class UniversalShaderMaterial extends CustomShaderMaterial {
|
|
6013
6432
|
constructor(name, scene) {
|
|
6014
6433
|
super(name, scene);
|
|
@@ -11736,8 +12155,10 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11736
12155
|
constructor(name, scene) {
|
|
11737
12156
|
super(name, scene);
|
|
11738
12157
|
this.controller = null;
|
|
11739
|
-
this.
|
|
11740
|
-
this.
|
|
12158
|
+
this._vatSkinArray = false;
|
|
12159
|
+
this._vatSkinArrayNormal = false;
|
|
12160
|
+
this._vatSkinArrayMetalRough = false;
|
|
12161
|
+
this._vatSkinArrayEmissive = false;
|
|
11741
12162
|
this.shader = this.getShaderName();
|
|
11742
12163
|
this.addAttribute("g_vatAnim0");
|
|
11743
12164
|
this.addAttribute("g_vatAnim1");
|
|
@@ -11793,97 +12214,90 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11793
12214
|
cloned.alpha = this.alpha;
|
|
11794
12215
|
cloned.alphaMode = this.alphaMode;
|
|
11795
12216
|
cloned.transparencyMode = this.transparencyMode;
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
12217
|
+
if (this._vatSkinArray) {
|
|
12218
|
+
const arr = this.getTextureValue("tkAlbedoArray");
|
|
12219
|
+
if (arr != null)
|
|
12220
|
+
cloned.addTextureArrayUniform("tkAlbedoArray", arr);
|
|
12221
|
+
cloned.enableVatSkinArray();
|
|
12222
|
+
}
|
|
12223
|
+
if (this._vatSkinArrayNormal) {
|
|
12224
|
+
const narr = this.getTextureValue("tkNormalArray");
|
|
12225
|
+
if (narr != null)
|
|
12226
|
+
cloned.addTextureArrayUniform("tkNormalArray", narr);
|
|
12227
|
+
cloned.enableVatSkinArrayNormal();
|
|
12228
|
+
}
|
|
12229
|
+
if (this._vatSkinArrayMetalRough) {
|
|
12230
|
+
const mrarr = this.getTextureValue("tkMetalRoughArray");
|
|
12231
|
+
if (mrarr != null)
|
|
12232
|
+
cloned.addTextureArrayUniform("tkMetalRoughArray", mrarr);
|
|
12233
|
+
cloned.enableVatSkinArrayMetalRough();
|
|
12234
|
+
}
|
|
12235
|
+
if (this._vatSkinArrayEmissive) {
|
|
12236
|
+
const earr = this.getTextureValue("tkEmissiveArray");
|
|
12237
|
+
if (earr != null)
|
|
12238
|
+
cloned.addTextureArrayUniform("tkEmissiveArray", earr);
|
|
12239
|
+
cloned.enableVatSkinArrayEmissive();
|
|
12240
|
+
}
|
|
11799
12241
|
return cloned;
|
|
11800
12242
|
}
|
|
11801
|
-
|
|
11802
|
-
this.
|
|
11803
|
-
this.
|
|
11804
|
-
if (
|
|
11805
|
-
this.
|
|
11806
|
-
|
|
11807
|
-
}
|
|
11808
|
-
this._notifyPluginOfRuntimeSkinChange();
|
|
12243
|
+
enableVatSkinArray() {
|
|
12244
|
+
this._vatSkinArray = true;
|
|
12245
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12246
|
+
if (this.plugin)
|
|
12247
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12248
|
+
return this;
|
|
11809
12249
|
}
|
|
11810
|
-
|
|
11811
|
-
this.
|
|
11812
|
-
this.
|
|
11813
|
-
this.
|
|
12250
|
+
disableVatSkinArray() {
|
|
12251
|
+
this._vatSkinArray = false;
|
|
12252
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12253
|
+
if (this.plugin)
|
|
12254
|
+
this.plugin.markAllDefinesAsDirty();
|
|
11814
12255
|
}
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
const scene = this.getScene();
|
|
11825
|
-
const layerCount = layers.length;
|
|
11826
|
-
const bytesPerLayer = width * height * 4;
|
|
11827
|
-
const albedoData = new Uint8Array(bytesPerLayer * layerCount);
|
|
11828
|
-
const normalData = new Uint8Array(bytesPerLayer * layerCount);
|
|
11829
|
-
const resolveUrl = (rel) => {
|
|
11830
|
-
if (!rel)
|
|
11831
|
-
return "";
|
|
11832
|
-
if (rel.indexOf("://") >= 0 || rel.indexOf("blob:") === 0 || rel.indexOf("data:") === 0 || rel.indexOf("/") === 0)
|
|
11833
|
-
return rel;
|
|
11834
|
-
if (rootUrl) {
|
|
11835
|
-
const sep = rootUrl.charAt(rootUrl.length - 1) === "/" ? "" : "/";
|
|
11836
|
-
return rootUrl + sep + rel;
|
|
11837
|
-
}
|
|
11838
|
-
return rel;
|
|
11839
|
-
};
|
|
11840
|
-
const loadAndCopy = (url, dst, layerIdx, label) => {
|
|
11841
|
-
return new Promise((resolve, reject) => {
|
|
11842
|
-
const fullUrl = resolveUrl(url);
|
|
11843
|
-
const tex = new Texture(fullUrl, scene, true, true, samplingMode, () => {
|
|
11844
|
-
const size = tex.getSize();
|
|
11845
|
-
if (size.width !== width || size.height !== height) {
|
|
11846
|
-
tex.dispose();
|
|
11847
|
-
reject(new Error(`${label} '${fullUrl}' is ${size.width}x${size.height}, expected ${width}x${height}.`));
|
|
11848
|
-
return;
|
|
11849
|
-
}
|
|
11850
|
-
const pixelsPromise = tex.readPixels();
|
|
11851
|
-
const onPixels = (pixels) => {
|
|
11852
|
-
if (!pixels) {
|
|
11853
|
-
tex.dispose();
|
|
11854
|
-
reject(new Error(`${label} '${fullUrl}': readPixels returned null.`));
|
|
11855
|
-
return;
|
|
11856
|
-
}
|
|
11857
|
-
dst.set(new Uint8Array(pixels.buffer, pixels.byteOffset, pixels.byteLength), layerIdx * bytesPerLayer);
|
|
11858
|
-
tex.dispose();
|
|
11859
|
-
resolve();
|
|
11860
|
-
};
|
|
11861
|
-
if (pixelsPromise && typeof pixelsPromise.then === "function") {
|
|
11862
|
-
pixelsPromise.then(onPixels).catch((e) => { tex.dispose(); reject(e); });
|
|
11863
|
-
}
|
|
11864
|
-
else {
|
|
11865
|
-
onPixels(pixelsPromise);
|
|
11866
|
-
}
|
|
11867
|
-
}, (msg) => reject(new Error(`${label} '${fullUrl}' load failed: ${msg}`)));
|
|
11868
|
-
});
|
|
11869
|
-
};
|
|
11870
|
-
const tasks = [];
|
|
11871
|
-
for (let i = 0; i < layerCount; i++) {
|
|
11872
|
-
tasks.push(loadAndCopy(layers[i].albedo, albedoData, i, "Skin albedo"));
|
|
11873
|
-
tasks.push(loadAndCopy(layers[i].normal, normalData, i, "Skin normal"));
|
|
11874
|
-
}
|
|
11875
|
-
await Promise.all(tasks);
|
|
11876
|
-
const albedoArray = RawTexture2DArray.CreateRGBATexture(albedoData, width, height, layerCount, scene, generateMipMaps, false, samplingMode);
|
|
11877
|
-
const normalArray = RawTexture2DArray.CreateRGBATexture(normalData, width, height, layerCount, scene, generateMipMaps, false, samplingMode);
|
|
11878
|
-
normalArray.gammaSpace = false;
|
|
11879
|
-
this.setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults);
|
|
11880
|
-
}
|
|
11881
|
-
_notifyPluginOfRuntimeSkinChange() {
|
|
11882
|
-
const plug = this.plugin;
|
|
11883
|
-
if (plug && typeof plug.onRuntimeSkinArraysChanged === "function") {
|
|
11884
|
-
plug.onRuntimeSkinArraysChanged();
|
|
11885
|
-
}
|
|
12256
|
+
enableVatSkinArrayNormal() {
|
|
12257
|
+
this._vatSkinArrayNormal = true;
|
|
12258
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12259
|
+
if (this.plugin)
|
|
12260
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12261
|
+
return this;
|
|
12262
|
+
}
|
|
12263
|
+
disableVatSkinArrayNormal() {
|
|
12264
|
+
this._vatSkinArrayNormal = false;
|
|
11886
12265
|
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12266
|
+
if (this.plugin)
|
|
12267
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12268
|
+
}
|
|
12269
|
+
enableVatSkinArrayMetalRough() {
|
|
12270
|
+
this._vatSkinArrayMetalRough = true;
|
|
12271
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12272
|
+
if (this.plugin)
|
|
12273
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12274
|
+
return this;
|
|
12275
|
+
}
|
|
12276
|
+
disableVatSkinArrayMetalRough() {
|
|
12277
|
+
this._vatSkinArrayMetalRough = false;
|
|
12278
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12279
|
+
if (this.plugin)
|
|
12280
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12281
|
+
}
|
|
12282
|
+
enableVatSkinArrayEmissive() {
|
|
12283
|
+
this._vatSkinArrayEmissive = true;
|
|
12284
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12285
|
+
if (this.plugin)
|
|
12286
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12287
|
+
return this;
|
|
12288
|
+
}
|
|
12289
|
+
disableVatSkinArrayEmissive() {
|
|
12290
|
+
this._vatSkinArrayEmissive = false;
|
|
12291
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12292
|
+
if (this.plugin)
|
|
12293
|
+
this.plugin.markAllDefinesAsDirty();
|
|
12294
|
+
}
|
|
12295
|
+
get vatSkinArray() { return this._vatSkinArray; }
|
|
12296
|
+
get vatSkinArrayNormal() { return this._vatSkinArrayNormal; }
|
|
12297
|
+
get vatSkinArrayMetalRough() { return this._vatSkinArrayMetalRough; }
|
|
12298
|
+
get vatSkinArrayEmissive() { return this._vatSkinArrayEmissive; }
|
|
12299
|
+
get vatSkinArrayActive() {
|
|
12300
|
+
return this._vatSkinArray || this._vatSkinArrayNormal || this._vatSkinArrayMetalRough || this._vatSkinArrayEmissive;
|
|
11887
12301
|
}
|
|
11888
12302
|
}
|
|
11889
12303
|
export class VertexAnimationController {
|
|
@@ -11918,15 +12332,15 @@ export class VertexAnimationController {
|
|
|
11918
12332
|
}
|
|
11919
12333
|
return result;
|
|
11920
12334
|
}
|
|
11921
|
-
static
|
|
12335
|
+
static SetAtlasCellIndex(mesh, cellIndex) {
|
|
11922
12336
|
if (!mesh)
|
|
11923
12337
|
return;
|
|
11924
|
-
mesh.
|
|
12338
|
+
mesh.atlasCellIndex = Math.max(0, Math.floor(cellIndex || 0));
|
|
11925
12339
|
}
|
|
11926
|
-
static
|
|
12340
|
+
static GetAtlasCellIndex(mesh) {
|
|
11927
12341
|
if (!mesh)
|
|
11928
12342
|
return 0;
|
|
11929
|
-
const v = mesh.
|
|
12343
|
+
const v = mesh.atlasCellIndex;
|
|
11930
12344
|
return (typeof v === "number" && isFinite(v) && v >= 0) ? Math.floor(v) : 0;
|
|
11931
12345
|
}
|
|
11932
12346
|
static DisposeAll(scene) {
|
|
@@ -12010,39 +12424,6 @@ export class VertexAnimationController {
|
|
|
12010
12424
|
}
|
|
12011
12425
|
setSpeed(speed) { this._speed = speed; }
|
|
12012
12426
|
setLoop(loop) { this._manualLoopOverride = loop; this._loop = loop; }
|
|
12013
|
-
setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults = true) {
|
|
12014
|
-
for (let i = 0; i < this._plugins.length; i++) {
|
|
12015
|
-
const plugin = this._plugins[i];
|
|
12016
|
-
const mat = plugin.getCustomShaderMaterial();
|
|
12017
|
-
if (mat)
|
|
12018
|
-
mat.setRuntimeSkinArrays(albedoArray, normalArray, nullOutDefaults);
|
|
12019
|
-
}
|
|
12020
|
-
}
|
|
12021
|
-
clearRuntimeSkinArrays() {
|
|
12022
|
-
for (let i = 0; i < this._plugins.length; i++) {
|
|
12023
|
-
const plugin = this._plugins[i];
|
|
12024
|
-
const mat = plugin.getCustomShaderMaterial();
|
|
12025
|
-
if (mat)
|
|
12026
|
-
mat.clearRuntimeSkinArrays();
|
|
12027
|
-
}
|
|
12028
|
-
}
|
|
12029
|
-
async installSkinsFromUrlsAsync(layers, width, height, options) {
|
|
12030
|
-
if (this._plugins.length === 0) {
|
|
12031
|
-
throw new Error("VertexAnimationController.installSkinsFromUrlsAsync: no registered VAT materials.");
|
|
12032
|
-
}
|
|
12033
|
-
const opts = options || {};
|
|
12034
|
-
const effectiveOptions = { ...opts, rootUrl: opts.rootUrl || this.rootUrl };
|
|
12035
|
-
const nullOutDefaults = opts.nullOutDefaults !== false;
|
|
12036
|
-
const firstMat = this._plugins[0].getCustomShaderMaterial();
|
|
12037
|
-
await firstMat.installSkinsFromUrlsAsync(layers, width, height, effectiveOptions);
|
|
12038
|
-
const sharedAlbedo = firstMat.runtimeAlbedoSkins;
|
|
12039
|
-
const sharedNormal = firstMat.runtimeNormalSkins;
|
|
12040
|
-
for (let i = 1; i < this._plugins.length; i++) {
|
|
12041
|
-
const mat = this._plugins[i].getCustomShaderMaterial();
|
|
12042
|
-
if (mat)
|
|
12043
|
-
mat.setRuntimeSkinArrays(sharedAlbedo, sharedNormal, nullOutDefaults);
|
|
12044
|
-
}
|
|
12045
|
-
}
|
|
12046
12427
|
setCurrentTime(time) {
|
|
12047
12428
|
if (!this._currentClip)
|
|
12048
12429
|
return;
|
|
@@ -12252,9 +12633,9 @@ export class VertexAnimationController {
|
|
|
12252
12633
|
const s = current.settings;
|
|
12253
12634
|
anim0.set(this._time * s.vertexfps, s.vertexframes, current.fromRow, this._blendWeight);
|
|
12254
12635
|
const loopFlag = this._loopBlend ? 1.0 : 0.0;
|
|
12255
|
-
const
|
|
12256
|
-
const
|
|
12257
|
-
anim1.w =
|
|
12636
|
+
const cellRaw = imesh.atlasCellIndex;
|
|
12637
|
+
const cell = (typeof cellRaw === "number" && cellRaw >= 0) ? Math.floor(cellRaw) : 0;
|
|
12638
|
+
anim1.w = cell * 2.0 + loopFlag;
|
|
12258
12639
|
const prev = this.getPreviousRendererClip(rendererGuid);
|
|
12259
12640
|
if (prev && this._previousClip && this._blendWeight < 0.999 && this._isRendererPositionReady(prev)) {
|
|
12260
12641
|
const ps = prev.settings;
|
|
@@ -12424,17 +12805,17 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12424
12805
|
super(customMaterial, shaderName, 100, {
|
|
12425
12806
|
VERTEXANIMATIONMATERIAL: false,
|
|
12426
12807
|
VAT_NORMAL_SEPARATE: false,
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12808
|
+
VAT_SKIN_ARRAY: false,
|
|
12809
|
+
VAT_SKIN_ARRAY_ALBEDO: false,
|
|
12810
|
+
VAT_SKIN_ARRAY_NORMAL: false,
|
|
12811
|
+
VAT_SKIN_ARRAY_MR: false,
|
|
12812
|
+
VAT_SKIN_ARRAY_EMISSIVE: false
|
|
12430
12813
|
});
|
|
12431
12814
|
this.vertexAnimations = null;
|
|
12432
12815
|
this.controller = null;
|
|
12433
12816
|
this._rendererTargets = [];
|
|
12434
12817
|
this._targetRendererGuid = "";
|
|
12435
12818
|
this._placeholderTexture = null;
|
|
12436
|
-
this._placeholderAlbedoArray = null;
|
|
12437
|
-
this._placeholderNormalArray = null;
|
|
12438
12819
|
this._cc_posTex = null;
|
|
12439
12820
|
this._cc_normTex = null;
|
|
12440
12821
|
this._cc_prevPosTex = null;
|
|
@@ -12456,24 +12837,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12456
12837
|
customMaterial.setTextureValue("vatNormal", this._placeholderTexture);
|
|
12457
12838
|
customMaterial.setTextureValue("vatPrevPosition", this._placeholderTexture);
|
|
12458
12839
|
customMaterial.setTextureValue("vatPrevNormal", this._placeholderTexture);
|
|
12459
|
-
const greyArr = new Uint8Array([128, 128, 128, 255]);
|
|
12460
|
-
const flatNormalArr = new Uint8Array([128, 128, 255, 255]);
|
|
12461
|
-
this._placeholderAlbedoArray = RawTexture2DArray.CreateRGBATexture(greyArr, 1, 1, 1, scene, false, false, Texture.NEAREST_SAMPLINGMODE);
|
|
12462
|
-
this._placeholderNormalArray = RawTexture2DArray.CreateRGBATexture(flatNormalArr, 1, 1, 1, scene, false, false, Texture.NEAREST_SAMPLINGMODE);
|
|
12463
12840
|
}
|
|
12464
12841
|
dispose() {
|
|
12465
12842
|
if (this._placeholderTexture) {
|
|
12466
12843
|
this._placeholderTexture.dispose();
|
|
12467
12844
|
this._placeholderTexture = null;
|
|
12468
12845
|
}
|
|
12469
|
-
if (this._placeholderAlbedoArray) {
|
|
12470
|
-
this._placeholderAlbedoArray.dispose();
|
|
12471
|
-
this._placeholderAlbedoArray = null;
|
|
12472
|
-
}
|
|
12473
|
-
if (this._placeholderNormalArray) {
|
|
12474
|
-
this._placeholderNormalArray.dispose();
|
|
12475
|
-
this._placeholderNormalArray = null;
|
|
12476
|
-
}
|
|
12477
12846
|
super.dispose();
|
|
12478
12847
|
}
|
|
12479
12848
|
isCompatible(shaderLanguage) {
|
|
@@ -12487,28 +12856,32 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12487
12856
|
CUSTOM_VERTEX_DEFINITIONS: this.getWGSLVertexDefinitions(),
|
|
12488
12857
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getWGSLVertexPositionCode(),
|
|
12489
12858
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getWGSLVertexNormalCode(),
|
|
12490
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12859
|
+
CUSTOM_VERTEX_MAIN_END: this.getWGSLSkinLayerVaryingCode()
|
|
12491
12860
|
};
|
|
12492
12861
|
}
|
|
12493
12862
|
return {
|
|
12494
12863
|
CUSTOM_VERTEX_DEFINITIONS: this.getGLSLVertexDefinitions(),
|
|
12495
12864
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getGLSLVertexPositionCode(),
|
|
12496
12865
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getGLSLVertexNormalCode(),
|
|
12497
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12866
|
+
CUSTOM_VERTEX_MAIN_END: this.getGLSLSkinLayerVaryingCode()
|
|
12498
12867
|
};
|
|
12499
12868
|
}
|
|
12500
12869
|
if (shaderType === "fragment") {
|
|
12501
12870
|
if (wgsl) {
|
|
12502
12871
|
return {
|
|
12503
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12504
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12505
|
-
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.
|
|
12872
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getWGSLSkinFragmentDefs(),
|
|
12873
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getWGSLSkinAlbedoCode() + this.getWGSLSkinMetalRoughSampleCode(),
|
|
12874
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getWGSLSkinNormalCode(),
|
|
12875
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getWGSLSkinMetalRoughApplyCode(),
|
|
12876
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getWGSLSkinEmissiveCode()
|
|
12506
12877
|
};
|
|
12507
12878
|
}
|
|
12508
12879
|
return {
|
|
12509
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12510
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12511
|
-
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.
|
|
12880
|
+
CUSTOM_FRAGMENT_DEFINITIONS: this.getGLSLSkinFragmentDefs(),
|
|
12881
|
+
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.getGLSLSkinAlbedoCode() + this.getGLSLSkinMetalRoughSampleCode(),
|
|
12882
|
+
CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.getGLSLSkinNormalCode(),
|
|
12883
|
+
CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS: this.getGLSLSkinMetalRoughApplyCode(),
|
|
12884
|
+
CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION: this.getGLSLSkinEmissiveCode()
|
|
12512
12885
|
};
|
|
12513
12886
|
}
|
|
12514
12887
|
return null;
|
|
@@ -12523,13 +12896,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12523
12896
|
const customSamplers = this.getCustomShaderMaterial().getCustomSamplers();
|
|
12524
12897
|
if (customSamplers != null && customSamplers.length > 0)
|
|
12525
12898
|
samplers.push(...customSamplers);
|
|
12526
|
-
const mat = this.getCustomShaderMaterial();
|
|
12527
|
-
if (mat) {
|
|
12528
|
-
if (samplers.indexOf("runtimeAlbedoSkins") === -1)
|
|
12529
|
-
samplers.push("runtimeAlbedoSkins");
|
|
12530
|
-
if (samplers.indexOf("runtimeNormalSkins") === -1)
|
|
12531
|
-
samplers.push("runtimeNormalSkins");
|
|
12532
|
-
}
|
|
12533
12899
|
}
|
|
12534
12900
|
getAttributes(attributes, scene, mesh) {
|
|
12535
12901
|
const customAttributes = this.getCustomShaderMaterial().getCustomAttributes();
|
|
@@ -12545,15 +12911,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12545
12911
|
defines.VAT_NORMAL_SEPARATE = (mode === "separate");
|
|
12546
12912
|
const engine = scene ? scene.getEngine() : null;
|
|
12547
12913
|
defines.UV3 = !(engine && engine.isWebGPU);
|
|
12548
|
-
const
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
defines.
|
|
12552
|
-
defines.
|
|
12553
|
-
defines.
|
|
12554
|
-
}
|
|
12555
|
-
onRuntimeSkinArraysChanged() {
|
|
12556
|
-
this.markAllDefinesAsDirty();
|
|
12914
|
+
const matSkin = this.getCustomShaderMaterial();
|
|
12915
|
+
defines.VAT_SKIN_ARRAY = !!(matSkin && matSkin.vatSkinArrayActive);
|
|
12916
|
+
defines.VAT_SKIN_ARRAY_ALBEDO = !!(matSkin && matSkin.vatSkinArray);
|
|
12917
|
+
defines.VAT_SKIN_ARRAY_NORMAL = !!(matSkin && matSkin.vatSkinArrayNormal);
|
|
12918
|
+
defines.VAT_SKIN_ARRAY_MR = !!(matSkin && matSkin.vatSkinArrayMetalRough);
|
|
12919
|
+
defines.VAT_SKIN_ARRAY_EMISSIVE = !!(matSkin && matSkin.vatSkinArrayEmissive);
|
|
12557
12920
|
}
|
|
12558
12921
|
bindForSubMesh(uniformBuffer, scene, engine, subMesh) {
|
|
12559
12922
|
if (!this.getIsEnabled())
|
|
@@ -12561,16 +12924,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12561
12924
|
const renderMesh = subMesh && subMesh.getRenderingMesh ? subMesh.getRenderingMesh() : null;
|
|
12562
12925
|
this._captureRendererTarget(renderMesh || (subMesh ? subMesh.getMesh() : null));
|
|
12563
12926
|
this._pushVATUniforms(uniformBuffer, false);
|
|
12564
|
-
this._pushRuntimeSkinSamplers(uniformBuffer);
|
|
12565
|
-
}
|
|
12566
|
-
_pushRuntimeSkinSamplers(buf) {
|
|
12567
|
-
const mat = this.getCustomShaderMaterial();
|
|
12568
|
-
const albedoArr = (mat && mat.runtimeAlbedoSkins && mat.runtimeAlbedoSkins.isReady && mat.runtimeAlbedoSkins.isReady())
|
|
12569
|
-
? mat.runtimeAlbedoSkins : this._placeholderAlbedoArray;
|
|
12570
|
-
const normalArr = (mat && mat.runtimeNormalSkins && mat.runtimeNormalSkins.isReady && mat.runtimeNormalSkins.isReady())
|
|
12571
|
-
? mat.runtimeNormalSkins : this._placeholderNormalArray;
|
|
12572
|
-
buf.setTexture("runtimeAlbedoSkins", albedoArr);
|
|
12573
|
-
buf.setTexture("runtimeNormalSkins", normalArr);
|
|
12574
12927
|
}
|
|
12575
12928
|
setupAnimations(settings, controllerId, rootUrl = "", lazyLoadTextures = false) {
|
|
12576
12929
|
this.vertexAnimations = settings;
|
|
@@ -12823,7 +13176,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12823
13176
|
}
|
|
12824
13177
|
bindVATToEffect(effect) {
|
|
12825
13178
|
this._pushVATUniforms(effect, true);
|
|
12826
|
-
this._pushRuntimeSkinSamplers(effect);
|
|
12827
13179
|
}
|
|
12828
13180
|
_pushVATUniforms(buf, isEffect) {
|
|
12829
13181
|
const fb = this._placeholderTexture;
|
|
@@ -12896,13 +13248,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12896
13248
|
uniform sampler2D vatPrevPosition;
|
|
12897
13249
|
uniform sampler2D vatPrevNormal;
|
|
12898
13250
|
#endif
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
varying vec2 vRuntimeSkinUV;
|
|
13251
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13252
|
+
#ifndef TOOLKIT_VAT_SKIN_V_DEFINED
|
|
13253
|
+
#define TOOLKIT_VAT_SKIN_V_DEFINED
|
|
13254
|
+
varying float vVatSkinLayer;
|
|
13255
|
+
varying vec2 vVatSkinUV;
|
|
13256
|
+
#endif
|
|
12906
13257
|
#endif
|
|
12907
13258
|
`;
|
|
12908
13259
|
}
|
|
@@ -12916,8 +13267,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12916
13267
|
float vatPrevFrame = g_vatAnim1.x;
|
|
12917
13268
|
float vatPrevFrameCount = g_vatAnim1.y;
|
|
12918
13269
|
float vatPrevFromRow = g_vatAnim1.z;
|
|
12919
|
-
|
|
12920
|
-
float vatLoopBlend = mod(
|
|
13270
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13271
|
+
float vatLoopBlend = mod(g_vatAnim1.w, 2.0); // low bit is loop-blend, high bits carry the skin layer index
|
|
13272
|
+
#else
|
|
13273
|
+
float vatLoopBlend = g_vatAnim1.w;
|
|
13274
|
+
#endif
|
|
12921
13275
|
if (vatFrameCount > 0.5) {
|
|
12922
13276
|
// GLSL path uses the third UV channel:
|
|
12923
13277
|
// Unity uv3 -> glTF TEXCOORD_2 -> Babylon shader uv3
|
|
@@ -12985,9 +13339,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12985
13339
|
float vatNormFrame = g_vatAnim0.x;
|
|
12986
13340
|
float vatNormFrameCount = g_vatAnim0.y;
|
|
12987
13341
|
float vatNormFromRow = g_vatAnim0.z;
|
|
12988
|
-
|
|
12989
|
-
float
|
|
12990
|
-
|
|
13342
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13343
|
+
float vatNormLoopBlend = mod(g_vatAnim1.w, 2.0);
|
|
13344
|
+
#else
|
|
13345
|
+
float vatNormLoopBlend = g_vatAnim1.w;
|
|
13346
|
+
#endif
|
|
12991
13347
|
|
|
12992
13348
|
if (vatNormFrameCount > 0.5) {
|
|
12993
13349
|
// GLSL path uses the third UV channel:
|
|
@@ -13033,9 +13389,10 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13033
13389
|
var vatPrevPositionSampler: sampler;
|
|
13034
13390
|
var vatPrevNormal: texture_2d<f32>;
|
|
13035
13391
|
var vatPrevNormalSampler: sampler;
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
varying
|
|
13392
|
+
#endif
|
|
13393
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13394
|
+
varying vVatSkinLayer: f32;
|
|
13395
|
+
varying vVatSkinUV: vec2<f32>;
|
|
13039
13396
|
#endif
|
|
13040
13397
|
`;
|
|
13041
13398
|
}
|
|
@@ -13049,8 +13406,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13049
13406
|
let vatPrevFrame = vertexInputs.g_vatAnim1.x;
|
|
13050
13407
|
let vatPrevFrameCount = vertexInputs.g_vatAnim1.y;
|
|
13051
13408
|
let vatPrevFromRow = vertexInputs.g_vatAnim1.z;
|
|
13052
|
-
|
|
13053
|
-
let vatLoopBlend =
|
|
13409
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13410
|
+
let vatLoopBlend = vertexInputs.g_vatAnim1.w % 2.0; // low bit is loop-blend, high bits carry the skin layer index
|
|
13411
|
+
#else
|
|
13412
|
+
let vatLoopBlend = vertexInputs.g_vatAnim1.w;
|
|
13413
|
+
#endif
|
|
13054
13414
|
if (vatFrameCount > 0.5) {
|
|
13055
13415
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13056
13416
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13119,8 +13479,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13119
13479
|
let vatNormFrame = vertexInputs.g_vatAnim0.x;
|
|
13120
13480
|
let vatNormFrameCount = vertexInputs.g_vatAnim0.y;
|
|
13121
13481
|
let vatNormFromRow = vertexInputs.g_vatAnim0.z;
|
|
13122
|
-
|
|
13123
|
-
let vatNormLoopBlend =
|
|
13482
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13483
|
+
let vatNormLoopBlend = vertexInputs.g_vatAnim1.w % 2.0;
|
|
13484
|
+
#else
|
|
13485
|
+
let vatNormLoopBlend = vertexInputs.g_vatAnim1.w;
|
|
13486
|
+
#endif
|
|
13124
13487
|
if (vatNormFrameCount > 0.5) {
|
|
13125
13488
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13126
13489
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13157,130 +13520,187 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13157
13520
|
#endif
|
|
13158
13521
|
`;
|
|
13159
13522
|
}
|
|
13160
|
-
|
|
13523
|
+
getGLSLSkinLayerVaryingCode() {
|
|
13161
13524
|
return `
|
|
13162
|
-
#ifdef
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
#endif
|
|
13171
|
-
}
|
|
13525
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13526
|
+
#ifdef UV1
|
|
13527
|
+
vVatSkinLayer = floor(g_vatAnim1.w * 0.5 + 0.0001);
|
|
13528
|
+
vVatSkinUV = uv;
|
|
13529
|
+
#else
|
|
13530
|
+
vVatSkinLayer = 0.0;
|
|
13531
|
+
vVatSkinUV = vec2(0.0);
|
|
13532
|
+
#endif
|
|
13172
13533
|
#endif
|
|
13173
13534
|
`;
|
|
13174
13535
|
}
|
|
13175
|
-
|
|
13536
|
+
getGLSLSkinFragmentDefs() {
|
|
13176
13537
|
return `
|
|
13177
|
-
#ifdef
|
|
13538
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13539
|
+
varying float vVatSkinLayer;
|
|
13540
|
+
varying vec2 vVatSkinUV;
|
|
13541
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13542
|
+
uniform sampler2DArray tkAlbedoArray;
|
|
13543
|
+
#endif
|
|
13544
|
+
#ifdef VAT_SKIN_ARRAY_NORMAL
|
|
13545
|
+
uniform sampler2DArray tkNormalArray;
|
|
13546
|
+
#endif
|
|
13547
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13548
|
+
uniform sampler2DArray tkMetalRoughArray;
|
|
13549
|
+
vec2 _tkMR;
|
|
13550
|
+
#endif
|
|
13551
|
+
#ifdef VAT_SKIN_ARRAY_EMISSIVE
|
|
13552
|
+
uniform sampler2DArray tkEmissiveArray;
|
|
13553
|
+
#endif
|
|
13554
|
+
#endif
|
|
13555
|
+
`;
|
|
13556
|
+
}
|
|
13557
|
+
getGLSLSkinAlbedoCode() {
|
|
13558
|
+
return `
|
|
13559
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13178
13560
|
{
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
#ifdef
|
|
13182
|
-
|
|
13561
|
+
vec4 _vatSkinAlbedo = texture(tkAlbedoArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5)));
|
|
13562
|
+
// Match Babylon's native albedo: sRGB -> linear when the albedo is gamma-space.
|
|
13563
|
+
#ifdef GAMMAALBEDO
|
|
13564
|
+
surfaceAlbedo = toLinearSpace(_vatSkinAlbedo.rgb) * vAlbedoColor.rgb;
|
|
13183
13565
|
#else
|
|
13184
|
-
|
|
13566
|
+
surfaceAlbedo = _vatSkinAlbedo.rgb * vAlbedoColor.rgb;
|
|
13567
|
+
#endif
|
|
13568
|
+
#ifdef ALPHATEST
|
|
13569
|
+
if (_vatSkinAlbedo.a < alphaCutOff) discard;
|
|
13185
13570
|
#endif
|
|
13186
13571
|
}
|
|
13187
13572
|
#endif
|
|
13188
13573
|
`;
|
|
13189
13574
|
}
|
|
13190
|
-
|
|
13575
|
+
getGLSLSkinNormalCode() {
|
|
13191
13576
|
return `
|
|
13192
|
-
#
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
uniform highp sampler2DArray runtimeNormalSkins;
|
|
13577
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
13578
|
+
{
|
|
13579
|
+
vec3 _vatNrmTexel = texture(tkNormalArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5))).xyz;
|
|
13580
|
+
normalW = perturbNormal(vTBN, _vatNrmTexel, vBumpInfos.y);
|
|
13581
|
+
}
|
|
13198
13582
|
#endif
|
|
13199
13583
|
`;
|
|
13200
13584
|
}
|
|
13201
|
-
|
|
13585
|
+
getGLSLSkinMetalRoughSampleCode() {
|
|
13202
13586
|
return `
|
|
13203
|
-
#ifdef
|
|
13587
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13204
13588
|
{
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
surfaceAlbedo = _rsAlbedo.rgb * vAlbedoColor.rgb;
|
|
13208
|
-
#ifdef ALPHATEST
|
|
13209
|
-
if (_rsAlbedo.a < alphaCutOff) discard;
|
|
13210
|
-
#endif
|
|
13589
|
+
vec4 _vatMRtexel = texture(tkMetalRoughArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5)));
|
|
13590
|
+
_tkMR = vec2(_vatMRtexel.b, _vatMRtexel.g);
|
|
13211
13591
|
}
|
|
13212
13592
|
#endif
|
|
13213
13593
|
`;
|
|
13214
13594
|
}
|
|
13215
|
-
|
|
13595
|
+
getGLSLSkinMetalRoughApplyCode() {
|
|
13216
13596
|
return `
|
|
13217
|
-
#
|
|
13597
|
+
#if defined(VAT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
13598
|
+
metallicRoughness.r = _tkMR.x;
|
|
13599
|
+
metallicRoughness.g = _tkMR.y;
|
|
13600
|
+
#endif
|
|
13601
|
+
`;
|
|
13602
|
+
}
|
|
13603
|
+
getGLSLSkinEmissiveCode() {
|
|
13604
|
+
return `
|
|
13605
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_EMISSIVE)
|
|
13218
13606
|
{
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
vec3 _rsNormalTS = _rsNormalSample * 2.0 - 1.0;
|
|
13222
|
-
vec3 _rsP = vPositionW;
|
|
13223
|
-
vec3 _rsN = normalize(vNormalW);
|
|
13224
|
-
vec3 _rsDp1 = dFdx(_rsP);
|
|
13225
|
-
vec3 _rsDp2 = dFdy(_rsP);
|
|
13226
|
-
vec2 _rsDuv1 = dFdx(vRuntimeSkinUV);
|
|
13227
|
-
vec2 _rsDuv2 = dFdy(vRuntimeSkinUV);
|
|
13228
|
-
vec3 _rsDp2perp = cross(_rsDp2, _rsN);
|
|
13229
|
-
vec3 _rsDp1perp = cross(_rsN, _rsDp1);
|
|
13230
|
-
vec3 _rsT = _rsDp2perp * _rsDuv1.x + _rsDp1perp * _rsDuv2.x;
|
|
13231
|
-
vec3 _rsB = _rsDp2perp * _rsDuv1.y + _rsDp1perp * _rsDuv2.y;
|
|
13232
|
-
float _rsInvMax = inversesqrt(max(dot(_rsT, _rsT), dot(_rsB, _rsB)));
|
|
13233
|
-
mat3 _rsTBN = mat3(_rsT * _rsInvMax, _rsB * _rsInvMax, _rsN);
|
|
13234
|
-
normalW = normalize(_rsTBN * _rsNormalTS);
|
|
13607
|
+
vec3 _vatEmis = texture(tkEmissiveArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5))).rgb;
|
|
13608
|
+
finalEmissive = toLinearSpace(_vatEmis);
|
|
13235
13609
|
}
|
|
13236
13610
|
#endif
|
|
13237
13611
|
`;
|
|
13238
13612
|
}
|
|
13239
|
-
|
|
13613
|
+
getWGSLSkinLayerVaryingCode() {
|
|
13240
13614
|
return `
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13615
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13616
|
+
#ifdef UV1
|
|
13617
|
+
vertexOutputs.vVatSkinLayer = floor(vertexInputs.g_vatAnim1.w * 0.5 + 0.0001);
|
|
13618
|
+
vertexOutputs.vVatSkinUV = vertexInputs.uv;
|
|
13619
|
+
#else
|
|
13620
|
+
vertexOutputs.vVatSkinLayer = 0.0;
|
|
13621
|
+
vertexOutputs.vVatSkinUV = vec2f(0.0);
|
|
13622
|
+
#endif
|
|
13623
|
+
#endif
|
|
13247
13624
|
`;
|
|
13248
13625
|
}
|
|
13249
|
-
|
|
13626
|
+
getWGSLSkinFragmentDefs() {
|
|
13250
13627
|
return `
|
|
13251
|
-
#ifdef
|
|
13628
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13629
|
+
varying vVatSkinLayer: f32;
|
|
13630
|
+
varying vVatSkinUV: vec2<f32>;
|
|
13631
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13632
|
+
var tkAlbedoArray: texture_2d_array<f32>;
|
|
13633
|
+
var tkAlbedoArraySampler: sampler;
|
|
13634
|
+
#endif
|
|
13635
|
+
#ifdef VAT_SKIN_ARRAY_NORMAL
|
|
13636
|
+
var tkNormalArray: texture_2d_array<f32>;
|
|
13637
|
+
var tkNormalArraySampler: sampler;
|
|
13638
|
+
#endif
|
|
13639
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13640
|
+
var tkMetalRoughArray: texture_2d_array<f32>;
|
|
13641
|
+
var tkMetalRoughArraySampler: sampler;
|
|
13642
|
+
var<private> _tkMR: vec2<f32>;
|
|
13643
|
+
#endif
|
|
13644
|
+
#ifdef VAT_SKIN_ARRAY_EMISSIVE
|
|
13645
|
+
var tkEmissiveArray: texture_2d_array<f32>;
|
|
13646
|
+
var tkEmissiveArraySampler: sampler;
|
|
13647
|
+
#endif
|
|
13648
|
+
#endif
|
|
13649
|
+
`;
|
|
13650
|
+
}
|
|
13651
|
+
getWGSLSkinAlbedoCode() {
|
|
13652
|
+
return `
|
|
13653
|
+
#ifdef VAT_SKIN_ARRAY_ALBEDO
|
|
13252
13654
|
{
|
|
13253
|
-
let
|
|
13254
|
-
|
|
13255
|
-
|
|
13655
|
+
let _vatSkinAlbedo = textureSample(tkAlbedoArray, tkAlbedoArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5));
|
|
13656
|
+
// Match Babylon's native albedo: sRGB -> linear when the albedo is gamma-space.
|
|
13657
|
+
#ifdef GAMMAALBEDO
|
|
13658
|
+
surfaceAlbedo = toLinearSpaceVec3(_vatSkinAlbedo.rgb) * vAlbedoColor.rgb;
|
|
13659
|
+
#else
|
|
13660
|
+
surfaceAlbedo = _vatSkinAlbedo.rgb * vAlbedoColor.rgb;
|
|
13661
|
+
#endif
|
|
13256
13662
|
#ifdef ALPHATEST
|
|
13257
|
-
if (
|
|
13663
|
+
if (_vatSkinAlbedo.a < alphaCutOff) { discard; }
|
|
13258
13664
|
#endif
|
|
13259
13665
|
}
|
|
13260
13666
|
#endif
|
|
13261
13667
|
`;
|
|
13262
13668
|
}
|
|
13263
|
-
|
|
13669
|
+
getWGSLSkinNormalCode() {
|
|
13670
|
+
return `
|
|
13671
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_NORMAL) && defined(BUMP) && defined(TANGENT) && defined(NORMAL)
|
|
13672
|
+
{
|
|
13673
|
+
let _vatNrmTexel = textureSample(tkNormalArray, tkNormalArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5)).rgb;
|
|
13674
|
+
let _vatNrmTBN = mat3x3<f32>(fragmentInputs.vTBN0, fragmentInputs.vTBN1, fragmentInputs.vTBN2);
|
|
13675
|
+
normalW = perturbNormal(_vatNrmTBN, _vatNrmTexel, uniforms.vBumpInfos.y);
|
|
13676
|
+
}
|
|
13677
|
+
#endif
|
|
13678
|
+
`;
|
|
13679
|
+
}
|
|
13680
|
+
getWGSLSkinMetalRoughSampleCode() {
|
|
13264
13681
|
return `
|
|
13265
|
-
#ifdef
|
|
13682
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13266
13683
|
{
|
|
13267
|
-
let
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13684
|
+
let _vatMRtexel = textureSample(tkMetalRoughArray, tkMetalRoughArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5));
|
|
13685
|
+
_tkMR = vec2<f32>(_vatMRtexel.b, _vatMRtexel.g);
|
|
13686
|
+
}
|
|
13687
|
+
#endif
|
|
13688
|
+
`;
|
|
13689
|
+
}
|
|
13690
|
+
getWGSLSkinMetalRoughApplyCode() {
|
|
13691
|
+
return `
|
|
13692
|
+
#if defined(VAT_SKIN_ARRAY_MR) && defined(METALLICWORKFLOW)
|
|
13693
|
+
metallicRoughness.r = _tkMR.x;
|
|
13694
|
+
metallicRoughness.g = _tkMR.y;
|
|
13695
|
+
#endif
|
|
13696
|
+
`;
|
|
13697
|
+
}
|
|
13698
|
+
getWGSLSkinEmissiveCode() {
|
|
13699
|
+
return `
|
|
13700
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_EMISSIVE)
|
|
13701
|
+
{
|
|
13702
|
+
let _vatEmis = textureSample(tkEmissiveArray, tkEmissiveArraySampler, fragmentInputs.vVatSkinUV, i32(fragmentInputs.vVatSkinLayer + 0.5)).rgb;
|
|
13703
|
+
finalEmissive = toLinearSpaceVec3(_vatEmis);
|
|
13284
13704
|
}
|
|
13285
13705
|
#endif
|
|
13286
13706
|
`;
|
|
@@ -27680,6 +28100,138 @@ ShurikenParticles.UNITY_TO_BABYLON_LIFETIME_RATIO = 0.65;
|
|
|
27680
28100
|
ShurikenParticles.UNITY_TO_BABYLON_DEATH_FADE_ALPHA = 0.2;
|
|
27681
28101
|
ShurikenParticles.EMITTER_POSITION_OFFSET = new Vector3(0, 0, 0);
|
|
27682
28102
|
ShurikenParticles.EMITTER_ROTATION_OFFSET = new Vector3(90, 0, 0);
|
|
28103
|
+
export class SkinTextureArray {
|
|
28104
|
+
static Build(scene, urls, options = {}) {
|
|
28105
|
+
const requested = (urls || []).filter((u) => u != null && String(u).length > 0);
|
|
28106
|
+
if (requested.length === 0)
|
|
28107
|
+
return Promise.resolve(null);
|
|
28108
|
+
const maxLayers = SkinTextureArray._maxArrayLayers(scene.getEngine());
|
|
28109
|
+
let list = requested;
|
|
28110
|
+
if (requested.length > maxLayers) {
|
|
28111
|
+
console.warn("SkinTextureArray: " + requested.length + " slices exceeds GPU maxTextureArrayLayers ("
|
|
28112
|
+
+ maxLayers + ") — clamping to " + maxLayers + ". Skin indices >= " + maxLayers + " will be unavailable.");
|
|
28113
|
+
list = requested.slice(0, maxLayers);
|
|
28114
|
+
}
|
|
28115
|
+
const optKey = "m" + (options.mipmaps === false ? 0 : 1)
|
|
28116
|
+
+ "|y" + (options.invertY === true ? 1 : 0)
|
|
28117
|
+
+ "|s" + (options.samplingMode != null ? options.samplingMode : "d");
|
|
28118
|
+
const key = list.join("|") + "||" + optKey;
|
|
28119
|
+
if (SkinTextureArray._cache[key] != null)
|
|
28120
|
+
return SkinTextureArray._cache[key];
|
|
28121
|
+
const built = SkinTextureArray._loadImages(list).then((images) => {
|
|
28122
|
+
if (images == null || images.length === 0)
|
|
28123
|
+
return null;
|
|
28124
|
+
const w = images[0].width, h = images[0].height, depth = images.length;
|
|
28125
|
+
const canvas = document.createElement("canvas");
|
|
28126
|
+
canvas.width = w;
|
|
28127
|
+
canvas.height = h;
|
|
28128
|
+
const ctx = canvas.getContext("2d");
|
|
28129
|
+
const data = new Uint8Array(w * h * 4 * depth);
|
|
28130
|
+
const flipY = (options.invertY != null) ? options.invertY : false;
|
|
28131
|
+
for (let i = 0; i < depth; i++) {
|
|
28132
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
28133
|
+
ctx.clearRect(0, 0, w, h);
|
|
28134
|
+
if (flipY)
|
|
28135
|
+
ctx.setTransform(1, 0, 0, -1, 0, h);
|
|
28136
|
+
ctx.drawImage(images[i], 0, 0, w, h);
|
|
28137
|
+
const id = ctx.getImageData(0, 0, w, h).data;
|
|
28138
|
+
data.set(id, i * w * h * 4);
|
|
28139
|
+
}
|
|
28140
|
+
const engine = scene.getEngine();
|
|
28141
|
+
const isWebGPU = (engine != null && engine.isWebGPU === true);
|
|
28142
|
+
const genMips = (options.mipmaps !== false);
|
|
28143
|
+
const mipCount = genMips ? (Math.floor(Math.log2(Math.max(w, h))) + 1) : 1;
|
|
28144
|
+
const samplingMode = (options.samplingMode != null) ? options.samplingMode
|
|
28145
|
+
: (genMips ? Texture.TRILINEAR_SAMPLINGMODE : Texture.BILINEAR_SAMPLINGMODE);
|
|
28146
|
+
const arr = new RawTexture2DArray(data, w, h, depth, Constants.TEXTUREFORMAT_RGBA, scene, genMips, false, samplingMode, Constants.TEXTURETYPE_UNSIGNED_BYTE, 0, mipCount);
|
|
28147
|
+
if (genMips && isWebGPU && mipCount > 1)
|
|
28148
|
+
SkinTextureArray._uploadMipChain(scene, arr, data, w, h, depth);
|
|
28149
|
+
arr.wrapU = Texture.CLAMP_ADDRESSMODE;
|
|
28150
|
+
arr.wrapV = Texture.CLAMP_ADDRESSMODE;
|
|
28151
|
+
arr.anisotropicFilteringLevel = (options.aniso != null) ? options.aniso : 8;
|
|
28152
|
+
return arr;
|
|
28153
|
+
}).catch((e) => { console.warn("SkinTextureArray: build failed", e); delete SkinTextureArray._cache[key]; return null; });
|
|
28154
|
+
SkinTextureArray._cache[key] = built;
|
|
28155
|
+
return built;
|
|
28156
|
+
}
|
|
28157
|
+
static _uploadMipChain(scene, arr, base, w, h, depth) {
|
|
28158
|
+
const engine = scene.getEngine();
|
|
28159
|
+
const itex = arr.getInternalTexture();
|
|
28160
|
+
if (itex == null || typeof engine.updateRawTexture2DArray !== "function")
|
|
28161
|
+
return;
|
|
28162
|
+
const count = Math.floor(Math.log2(Math.max(w, h))) + 1;
|
|
28163
|
+
try {
|
|
28164
|
+
let prev = base, pw = w, ph = h;
|
|
28165
|
+
for (let m = 1; m < count; m++) {
|
|
28166
|
+
const nw = Math.max(1, pw >> 1), nh = Math.max(1, ph >> 1);
|
|
28167
|
+
const mip = SkinTextureArray._downsampleLayers(prev, pw, ph, depth, nw, nh);
|
|
28168
|
+
engine.updateRawTexture2DArray(itex, mip, Constants.TEXTUREFORMAT_RGBA, false, null, Constants.TEXTURETYPE_UNSIGNED_BYTE, m);
|
|
28169
|
+
prev = mip;
|
|
28170
|
+
pw = nw;
|
|
28171
|
+
ph = nh;
|
|
28172
|
+
}
|
|
28173
|
+
}
|
|
28174
|
+
catch (e) {
|
|
28175
|
+
console.warn("SkinTextureArray: mip-chain upload failed, using base level only", e);
|
|
28176
|
+
}
|
|
28177
|
+
}
|
|
28178
|
+
static _downsampleLayers(src, sw, sh, depth, dw, dh) {
|
|
28179
|
+
const out = new Uint8Array(dw * dh * 4 * depth);
|
|
28180
|
+
for (let L = 0; L < depth; L++) {
|
|
28181
|
+
const so = L * sw * sh * 4, doo = L * dw * dh * 4;
|
|
28182
|
+
for (let y = 0; y < dh; y++) {
|
|
28183
|
+
for (let x = 0; x < dw; x++) {
|
|
28184
|
+
const sx = x * 2, sy = y * 2;
|
|
28185
|
+
const sx1 = Math.min(sx + 1, sw - 1), sy1 = Math.min(sy + 1, sh - 1);
|
|
28186
|
+
for (let c = 0; c < 4; c++) {
|
|
28187
|
+
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];
|
|
28188
|
+
out[doo + (y * dw + x) * 4 + c] = (a + b + e + d) >> 2;
|
|
28189
|
+
}
|
|
28190
|
+
}
|
|
28191
|
+
}
|
|
28192
|
+
}
|
|
28193
|
+
return out;
|
|
28194
|
+
}
|
|
28195
|
+
static _maxArrayLayers(engine) {
|
|
28196
|
+
try {
|
|
28197
|
+
const dev = (engine != null) ? (engine._device || (typeof engine.getDevice === "function" ? engine.getDevice() : null)) : null;
|
|
28198
|
+
if (dev != null && dev.limits != null && typeof dev.limits.maxTextureArrayLayers === "number" && dev.limits.maxTextureArrayLayers > 0) {
|
|
28199
|
+
return dev.limits.maxTextureArrayLayers;
|
|
28200
|
+
}
|
|
28201
|
+
const gl = (engine != null) ? engine._gl : null;
|
|
28202
|
+
if (gl != null && typeof gl.getParameter === "function") {
|
|
28203
|
+
const MAX_ARRAY_TEXTURE_LAYERS = 0x88FF;
|
|
28204
|
+
const v = gl.getParameter(MAX_ARRAY_TEXTURE_LAYERS);
|
|
28205
|
+
if (typeof v === "number" && v > 0)
|
|
28206
|
+
return v;
|
|
28207
|
+
}
|
|
28208
|
+
}
|
|
28209
|
+
catch (e) { }
|
|
28210
|
+
return 256;
|
|
28211
|
+
}
|
|
28212
|
+
static _loadImages(urls) {
|
|
28213
|
+
return Promise.all(urls.map((u) => new Promise((resolve, reject) => {
|
|
28214
|
+
const img = document.createElement("img");
|
|
28215
|
+
img.crossOrigin = "anonymous";
|
|
28216
|
+
img.onload = () => resolve(img);
|
|
28217
|
+
img.onerror = () => reject(new Error("SkinTextureArray: failed to load " + u));
|
|
28218
|
+
img.src = u;
|
|
28219
|
+
})));
|
|
28220
|
+
}
|
|
28221
|
+
static Clear() {
|
|
28222
|
+
const entries = [];
|
|
28223
|
+
for (const k in SkinTextureArray._cache) {
|
|
28224
|
+
if (SkinTextureArray._cache[k] != null)
|
|
28225
|
+
entries.push(SkinTextureArray._cache[k]);
|
|
28226
|
+
}
|
|
28227
|
+
SkinTextureArray._cache = {};
|
|
28228
|
+
for (const p of entries) {
|
|
28229
|
+
p.then((arr) => { if (arr != null)
|
|
28230
|
+
arr.dispose(); }).catch(() => { });
|
|
28231
|
+
}
|
|
28232
|
+
}
|
|
28233
|
+
}
|
|
28234
|
+
SkinTextureArray._cache = {};
|
|
27683
28235
|
export class MeshNormalProxy {
|
|
27684
28236
|
constructor() {
|
|
27685
28237
|
this.blendWithPhysicsNormal = 0.0;
|
|
@@ -29254,6 +29806,410 @@ TerrainBuilder.detailChunkMaxTotalChunks = 256;
|
|
|
29254
29806
|
TerrainBuilder.meshDetailChunkMode = 1;
|
|
29255
29807
|
TerrainBuilder.meshDetailChunkTargetInstances = 20000;
|
|
29256
29808
|
TerrainBuilder.meshDetailChunkWorldSize = 64;
|
|
29809
|
+
export class TextureAtlasSkin extends ScriptComponent {
|
|
29810
|
+
constructor(transform, scene, properties = {}, alias = "TextureAtlasSkin") {
|
|
29811
|
+
super(transform, scene, properties, alias);
|
|
29812
|
+
this.abtractMesh = null;
|
|
29813
|
+
this.textureData = null;
|
|
29814
|
+
this.defaultIndex = 0;
|
|
29815
|
+
this.skinnedParts = [];
|
|
29816
|
+
this.albedoSlices = null;
|
|
29817
|
+
this.normalSlices = null;
|
|
29818
|
+
this.metallicSlices = null;
|
|
29819
|
+
this.occlusionSlices = null;
|
|
29820
|
+
this.emissiveSlices = null;
|
|
29821
|
+
this._applied = false;
|
|
29822
|
+
this._manifest = null;
|
|
29823
|
+
this._currentIndex = 0;
|
|
29824
|
+
this._targets = [];
|
|
29825
|
+
this._clonedMultiMaterial = null;
|
|
29826
|
+
}
|
|
29827
|
+
awake() {
|
|
29828
|
+
this.abtractMesh = this.getAbstractMesh();
|
|
29829
|
+
this.albedoSlices = this.getProperty("albedoSlices", null);
|
|
29830
|
+
this.normalSlices = this.getProperty("normalSlices", null);
|
|
29831
|
+
this.metallicSlices = this.getProperty("metallicSlices", null);
|
|
29832
|
+
this.occlusionSlices = this.getProperty("occlusionSlices", null);
|
|
29833
|
+
this.emissiveSlices = this.getProperty("emissiveSlices", null);
|
|
29834
|
+
window["__" + this.transform.name] = this;
|
|
29835
|
+
}
|
|
29836
|
+
start() {
|
|
29837
|
+
this.applySkins();
|
|
29838
|
+
}
|
|
29839
|
+
applySkins() {
|
|
29840
|
+
if (this._applied)
|
|
29841
|
+
return;
|
|
29842
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
29843
|
+
if (mesh == null) {
|
|
29844
|
+
console.warn("TextureAtlasSkin: no abstract mesh on " + this.transform.name);
|
|
29845
|
+
return;
|
|
29846
|
+
}
|
|
29847
|
+
let manifest = this.parseManifest();
|
|
29848
|
+
if (manifest == null) {
|
|
29849
|
+
const sliceCount = this.maxChannelSliceCount();
|
|
29850
|
+
if (sliceCount > 0) {
|
|
29851
|
+
const skins = [];
|
|
29852
|
+
for (let i = 0; i < sliceCount; i++)
|
|
29853
|
+
skins.push({ index: i, name: "skin_" + i });
|
|
29854
|
+
manifest = { skinArray: true, count: sliceCount, skins: skins };
|
|
29855
|
+
}
|
|
29856
|
+
else {
|
|
29857
|
+
console.warn("TextureAtlasSkin: no textureData manifest and no channel slices on " + this.transform.name);
|
|
29858
|
+
return;
|
|
29859
|
+
}
|
|
29860
|
+
}
|
|
29861
|
+
this._manifest = manifest;
|
|
29862
|
+
this._currentIndex = this.clampIndex(this.toInt(this.defaultIndex, 0), "defaultIndex");
|
|
29863
|
+
const isInstanced = this.isInstancedSetup(mesh);
|
|
29864
|
+
const slots = this.getMeshSlots(mesh);
|
|
29865
|
+
const parts = this.skinnedParts || [];
|
|
29866
|
+
if (parts.length === 0) {
|
|
29867
|
+
console.warn("TextureAtlasSkin: no skinnedParts on " + this.transform.name);
|
|
29868
|
+
return;
|
|
29869
|
+
}
|
|
29870
|
+
for (const part of parts) {
|
|
29871
|
+
const targetMat = this.resolvePartMaterial(part);
|
|
29872
|
+
const slot = this.matchSlot(slots, targetMat, part);
|
|
29873
|
+
if (slot == null || !(slot.material instanceof CustomShaderMaterial)) {
|
|
29874
|
+
console.warn("TextureAtlasSkin: skinned part not found / not a CustomShaderMaterial on " + this.transform.name, part);
|
|
29875
|
+
continue;
|
|
29876
|
+
}
|
|
29877
|
+
let material = slot.material;
|
|
29878
|
+
const isVat = (material instanceof VertexAnimationMaterial);
|
|
29879
|
+
const kind = isVat ? "vat" : (isInstanced ? "instanced" : "regular");
|
|
29880
|
+
if (kind === "regular") {
|
|
29881
|
+
material = this.cloneForRegular(mesh, slot, material);
|
|
29882
|
+
}
|
|
29883
|
+
this.configureMaterial(material, manifest, kind);
|
|
29884
|
+
this._targets.push({ material: material, kind: kind });
|
|
29885
|
+
console.warn(">>> TextureAtlasSkin: " + this.transform.name + " — part '" + material.name + "' → " + this.describeKind(kind) + " setup");
|
|
29886
|
+
}
|
|
29887
|
+
this.applyIndexToTargets(mesh, this._currentIndex);
|
|
29888
|
+
this._applied = true;
|
|
29889
|
+
}
|
|
29890
|
+
setSkinIndex(index) {
|
|
29891
|
+
const requested = this.toInt(index, 0);
|
|
29892
|
+
this._currentIndex = this.clampIndex(requested, "skin index");
|
|
29893
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
29894
|
+
this.applyIndexToTargets(mesh, this._currentIndex);
|
|
29895
|
+
return this._currentIndex;
|
|
29896
|
+
}
|
|
29897
|
+
clampIndex(index, label) {
|
|
29898
|
+
const count = this.skinCount();
|
|
29899
|
+
const max = Math.max(0, count - 1);
|
|
29900
|
+
const clamped = (index < 0) ? 0 : (index > max ? max : index);
|
|
29901
|
+
if (clamped !== index) {
|
|
29902
|
+
console.warn("TextureAtlasSkin: " + label + " " + index + " out of range [0, " + max + "] on " + this.transform.name + " — clamped to " + clamped);
|
|
29903
|
+
}
|
|
29904
|
+
return clamped;
|
|
29905
|
+
}
|
|
29906
|
+
skinCount() {
|
|
29907
|
+
const m = this._manifest;
|
|
29908
|
+
if (m == null)
|
|
29909
|
+
return this.maxChannelSliceCount();
|
|
29910
|
+
const skins = m.skins || [];
|
|
29911
|
+
if (skins.length > 0)
|
|
29912
|
+
return skins.length;
|
|
29913
|
+
const c = this.toInt(m.count, 0);
|
|
29914
|
+
if (c > 0)
|
|
29915
|
+
return c;
|
|
29916
|
+
return this.maxChannelSliceCount();
|
|
29917
|
+
}
|
|
29918
|
+
maxChannelSliceCount() {
|
|
29919
|
+
const lens = [this.albedoSlices, this.normalSlices, this.metallicSlices, this.occlusionSlices, this.emissiveSlices]
|
|
29920
|
+
.map((s) => (s != null) ? s.length : 0);
|
|
29921
|
+
return Math.max(0, lens[0], lens[1], lens[2], lens[3], lens[4]);
|
|
29922
|
+
}
|
|
29923
|
+
getSkinIndex() {
|
|
29924
|
+
return this._currentIndex;
|
|
29925
|
+
}
|
|
29926
|
+
configureMaterial(material, manifest, kind) {
|
|
29927
|
+
const shared = (kind !== "regular");
|
|
29928
|
+
if (shared && this.isConfigured(material))
|
|
29929
|
+
return;
|
|
29930
|
+
if (shared)
|
|
29931
|
+
this.markConfigured(material);
|
|
29932
|
+
if (kind === "instanced")
|
|
29933
|
+
this.ensureSkinLayerBuffer(this.abtractMesh || this.getAbstractMesh());
|
|
29934
|
+
const albedoUrls = this.albedoChannelUrls(manifest);
|
|
29935
|
+
const normalUrls = this.normalChannelUrls(manifest);
|
|
29936
|
+
const mrUrls = this.metalRoughChannelUrls(manifest);
|
|
29937
|
+
const emissiveUrls = this.emissiveChannelUrls(manifest);
|
|
29938
|
+
const has = (u) => (u != null && u.length > 0);
|
|
29939
|
+
if (!has(albedoUrls) && !has(normalUrls) && !has(mrUrls) && !has(emissiveUrls)) {
|
|
29940
|
+
console.warn("TextureAtlasSkin: no channel slices to build a skin array on " + this.transform.name);
|
|
29941
|
+
return;
|
|
29942
|
+
}
|
|
29943
|
+
if (kind !== "vat")
|
|
29944
|
+
material.setSkinArrayLayerMode(kind === "regular");
|
|
29945
|
+
const build = (urls, mipped) => has(urls) ? SkinTextureArray.Build(this.scene, urls, mipped ? {} : { mipmaps: false }) : Promise.resolve(null);
|
|
29946
|
+
Promise.all([build(albedoUrls, true), build(normalUrls, false), build(mrUrls, true), build(emissiveUrls, true)])
|
|
29947
|
+
.then(([albTex, nrmTex, mrTex, emisTex]) => {
|
|
29948
|
+
const vmat = (kind === "vat") ? material : null;
|
|
29949
|
+
if (albTex != null) {
|
|
29950
|
+
material.addTextureArrayUniform("tkAlbedoArray", albTex);
|
|
29951
|
+
if (vmat != null)
|
|
29952
|
+
vmat.enableVatSkinArray();
|
|
29953
|
+
else
|
|
29954
|
+
material.enableSkinArray(kind === "regular");
|
|
29955
|
+
}
|
|
29956
|
+
if (nrmTex != null) {
|
|
29957
|
+
material.addTextureArrayUniform("tkNormalArray", nrmTex);
|
|
29958
|
+
if (vmat != null)
|
|
29959
|
+
vmat.enableVatSkinArrayNormal();
|
|
29960
|
+
else
|
|
29961
|
+
material.enableSkinArrayNormal();
|
|
29962
|
+
}
|
|
29963
|
+
if (mrTex != null) {
|
|
29964
|
+
material.addTextureArrayUniform("tkMetalRoughArray", mrTex);
|
|
29965
|
+
if (vmat != null)
|
|
29966
|
+
vmat.enableVatSkinArrayMetalRough();
|
|
29967
|
+
else
|
|
29968
|
+
material.enableSkinArrayMetalRough();
|
|
29969
|
+
}
|
|
29970
|
+
if (emisTex != null) {
|
|
29971
|
+
material.addTextureArrayUniform("tkEmissiveArray", emisTex);
|
|
29972
|
+
if (vmat != null)
|
|
29973
|
+
vmat.enableVatSkinArrayEmissive();
|
|
29974
|
+
else
|
|
29975
|
+
material.enableSkinArrayEmissive();
|
|
29976
|
+
}
|
|
29977
|
+
if (albTex == null && nrmTex == null && mrTex == null && emisTex == null) {
|
|
29978
|
+
console.warn("TextureAtlasSkin: all channel arrays failed to build on " + this.transform.name);
|
|
29979
|
+
return;
|
|
29980
|
+
}
|
|
29981
|
+
this.applyLayerToMaterial(material, kind, this._currentIndex);
|
|
29982
|
+
});
|
|
29983
|
+
}
|
|
29984
|
+
albedoChannelUrls(manifest) {
|
|
29985
|
+
const fromSlices = this.sliceUrls(this.albedoSlices);
|
|
29986
|
+
if (fromSlices != null)
|
|
29987
|
+
return fromSlices;
|
|
29988
|
+
const layers = (manifest != null) ? manifest.albedoLayers : null;
|
|
29989
|
+
if (Array.isArray(layers)) {
|
|
29990
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
29991
|
+
return (out.length > 0) ? out : null;
|
|
29992
|
+
}
|
|
29993
|
+
return null;
|
|
29994
|
+
}
|
|
29995
|
+
normalChannelUrls(manifest) {
|
|
29996
|
+
const fromSlices = this.sliceUrls(this.normalSlices);
|
|
29997
|
+
if (fromSlices != null)
|
|
29998
|
+
return fromSlices;
|
|
29999
|
+
const layers = (manifest != null) ? manifest.normalLayers : null;
|
|
30000
|
+
if (Array.isArray(layers)) {
|
|
30001
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30002
|
+
return (out.length > 0) ? out : null;
|
|
30003
|
+
}
|
|
30004
|
+
return null;
|
|
30005
|
+
}
|
|
30006
|
+
metalRoughChannelUrls(manifest) {
|
|
30007
|
+
const fromSlices = this.sliceUrls(this.metallicSlices);
|
|
30008
|
+
if (fromSlices != null)
|
|
30009
|
+
return fromSlices;
|
|
30010
|
+
const layers = (manifest != null) ? manifest.metalRoughLayers : null;
|
|
30011
|
+
if (Array.isArray(layers)) {
|
|
30012
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30013
|
+
return (out.length > 0) ? out : null;
|
|
30014
|
+
}
|
|
30015
|
+
return null;
|
|
30016
|
+
}
|
|
30017
|
+
emissiveChannelUrls(manifest) {
|
|
30018
|
+
const fromSlices = this.sliceUrls(this.emissiveSlices);
|
|
30019
|
+
if (fromSlices != null)
|
|
30020
|
+
return fromSlices;
|
|
30021
|
+
const layers = (manifest != null) ? manifest.emissiveLayers : null;
|
|
30022
|
+
if (Array.isArray(layers)) {
|
|
30023
|
+
const out = layers.filter((x) => x != null && String(x).length > 0).map((x) => this.resolveLayerUrl(String(x)));
|
|
30024
|
+
return (out.length > 0) ? out : null;
|
|
30025
|
+
}
|
|
30026
|
+
return null;
|
|
30027
|
+
}
|
|
30028
|
+
sliceUrls(slices) {
|
|
30029
|
+
if (slices == null || slices.length === 0)
|
|
30030
|
+
return null;
|
|
30031
|
+
const root = SceneManager.GetRootUrl(this.scene) || "";
|
|
30032
|
+
const urls = [];
|
|
30033
|
+
for (const s of slices) {
|
|
30034
|
+
if (s == null)
|
|
30035
|
+
continue;
|
|
30036
|
+
const anyS = s;
|
|
30037
|
+
let u = null;
|
|
30038
|
+
if (anyS.url != null && String(anyS.url).length > 0)
|
|
30039
|
+
u = String(anyS.url);
|
|
30040
|
+
else if (anyS.filename != null && String(anyS.filename).length > 0)
|
|
30041
|
+
u = root + String(anyS.filename);
|
|
30042
|
+
if (u != null && u.length > 0)
|
|
30043
|
+
urls.push(u);
|
|
30044
|
+
}
|
|
30045
|
+
return (urls.length > 0) ? urls : null;
|
|
30046
|
+
}
|
|
30047
|
+
resolveLayerUrl(filename) {
|
|
30048
|
+
if (filename == null)
|
|
30049
|
+
return "";
|
|
30050
|
+
const f = String(filename);
|
|
30051
|
+
if (/^(https?:|blob:|data:|\/)/i.test(f))
|
|
30052
|
+
return f;
|
|
30053
|
+
const root = SceneManager.GetRootUrl(this.scene) || "";
|
|
30054
|
+
return root + f;
|
|
30055
|
+
}
|
|
30056
|
+
applyIndexToTargets(mesh, index) {
|
|
30057
|
+
if (mesh == null)
|
|
30058
|
+
return;
|
|
30059
|
+
for (const t of this._targets) {
|
|
30060
|
+
this.applyLayerToMaterial(t.material, t.kind, index);
|
|
30061
|
+
}
|
|
30062
|
+
}
|
|
30063
|
+
applyLayerToMaterial(material, kind, index) {
|
|
30064
|
+
if (kind === "vat") {
|
|
30065
|
+
VertexAnimationController.SetAtlasCellIndex(this.abtractMesh || this.getAbstractMesh(), index);
|
|
30066
|
+
}
|
|
30067
|
+
else if (kind === "instanced") {
|
|
30068
|
+
const mesh = this.abtractMesh || this.getAbstractMesh();
|
|
30069
|
+
this.ensureSkinLayerBuffer(mesh);
|
|
30070
|
+
mesh.instancedBuffers.tkSkinLayer = index;
|
|
30071
|
+
}
|
|
30072
|
+
else {
|
|
30073
|
+
material.setSkinLayer(index);
|
|
30074
|
+
}
|
|
30075
|
+
}
|
|
30076
|
+
isInstancedSetup(mesh) {
|
|
30077
|
+
if (mesh instanceof InstancedMesh)
|
|
30078
|
+
return true;
|
|
30079
|
+
const src = (mesh instanceof Mesh) ? mesh : null;
|
|
30080
|
+
return (src != null && src.instances != null && src.instances.length > 0);
|
|
30081
|
+
}
|
|
30082
|
+
ensureSkinLayerBuffer(mesh) {
|
|
30083
|
+
const inst = mesh;
|
|
30084
|
+
const src = (inst != null && inst.sourceMesh != null) ? inst.sourceMesh : mesh;
|
|
30085
|
+
const target = (src != null) ? src : mesh;
|
|
30086
|
+
if (target != null && typeof target.registerInstancedBuffer === "function") {
|
|
30087
|
+
const ib = target.instancedBuffers;
|
|
30088
|
+
if (ib == null || ib.tkSkinLayer === undefined) {
|
|
30089
|
+
target.registerInstancedBuffer("tkSkinLayer", 1);
|
|
30090
|
+
target.instancedBuffers = target.instancedBuffers || {};
|
|
30091
|
+
target.instancedBuffers.tkSkinLayer = 0;
|
|
30092
|
+
}
|
|
30093
|
+
}
|
|
30094
|
+
mesh.instancedBuffers = mesh.instancedBuffers || {};
|
|
30095
|
+
}
|
|
30096
|
+
getMeshSlots(mesh) {
|
|
30097
|
+
const slots = [];
|
|
30098
|
+
const mat = mesh.material;
|
|
30099
|
+
if (mat instanceof MultiMaterial) {
|
|
30100
|
+
const subs = mat.subMaterials;
|
|
30101
|
+
for (let i = 0; i < subs.length; i++) {
|
|
30102
|
+
if (subs[i] != null)
|
|
30103
|
+
slots.push({ material: subs[i], mm: mat, index: i });
|
|
30104
|
+
}
|
|
30105
|
+
}
|
|
30106
|
+
else if (mat != null) {
|
|
30107
|
+
slots.push({ material: mat, mm: null, index: -1 });
|
|
30108
|
+
}
|
|
30109
|
+
return slots;
|
|
30110
|
+
}
|
|
30111
|
+
matchSlot(slots, targetMat, part) {
|
|
30112
|
+
if (targetMat != null) {
|
|
30113
|
+
for (const s of slots)
|
|
30114
|
+
if (s.material === targetMat)
|
|
30115
|
+
return s;
|
|
30116
|
+
}
|
|
30117
|
+
const name = this.partName(part) || (targetMat != null ? targetMat.name : null);
|
|
30118
|
+
if (name != null && name.length > 0) {
|
|
30119
|
+
for (const s of slots)
|
|
30120
|
+
if (s.material.name === name)
|
|
30121
|
+
return s;
|
|
30122
|
+
for (const s of slots)
|
|
30123
|
+
if (s.material.name.indexOf(name) !== -1)
|
|
30124
|
+
return s;
|
|
30125
|
+
}
|
|
30126
|
+
if (slots.length === 1)
|
|
30127
|
+
return slots[0];
|
|
30128
|
+
return null;
|
|
30129
|
+
}
|
|
30130
|
+
resolvePartMaterial(part) {
|
|
30131
|
+
if (part == null)
|
|
30132
|
+
return null;
|
|
30133
|
+
if (part instanceof Material)
|
|
30134
|
+
return part;
|
|
30135
|
+
if (part.skinPart != null)
|
|
30136
|
+
return this.resolvePartMaterial(part.skinPart);
|
|
30137
|
+
const name = this.partName(part);
|
|
30138
|
+
if (name == null)
|
|
30139
|
+
return null;
|
|
30140
|
+
let mat = this.scene.getMaterialByName(name);
|
|
30141
|
+
if (mat == null && SceneManager.GetMaterialWithName != null)
|
|
30142
|
+
mat = SceneManager.GetMaterialWithName(this.scene, name);
|
|
30143
|
+
return mat;
|
|
30144
|
+
}
|
|
30145
|
+
partName(part) {
|
|
30146
|
+
if (part == null)
|
|
30147
|
+
return null;
|
|
30148
|
+
if (typeof part === "string")
|
|
30149
|
+
return part;
|
|
30150
|
+
if (part instanceof Material)
|
|
30151
|
+
return part.name;
|
|
30152
|
+
if (part.skinPart != null)
|
|
30153
|
+
return this.partName(part.skinPart);
|
|
30154
|
+
if (part.name != null)
|
|
30155
|
+
return part.name;
|
|
30156
|
+
if (part.material != null)
|
|
30157
|
+
return this.partName(part.material);
|
|
30158
|
+
return null;
|
|
30159
|
+
}
|
|
30160
|
+
cloneForRegular(mesh, slot, material) {
|
|
30161
|
+
const tag = "_skin_" + (this.transform != null ? this.transform.name : "skin");
|
|
30162
|
+
const cloned = material.clone(material.name + tag);
|
|
30163
|
+
if (!(cloned instanceof CustomShaderMaterial)) {
|
|
30164
|
+
console.warn("TextureAtlasSkin: clone did not preserve CustomShaderMaterial — using original (skin may be shared)", cloned);
|
|
30165
|
+
return material;
|
|
30166
|
+
}
|
|
30167
|
+
if (slot.mm != null) {
|
|
30168
|
+
if (this._clonedMultiMaterial == null) {
|
|
30169
|
+
this._clonedMultiMaterial = slot.mm.clone(slot.mm.name + tag);
|
|
30170
|
+
mesh.material = this._clonedMultiMaterial;
|
|
30171
|
+
}
|
|
30172
|
+
this._clonedMultiMaterial.subMaterials[slot.index] = cloned;
|
|
30173
|
+
}
|
|
30174
|
+
else {
|
|
30175
|
+
mesh.material = cloned;
|
|
30176
|
+
}
|
|
30177
|
+
return cloned;
|
|
30178
|
+
}
|
|
30179
|
+
parseManifest() {
|
|
30180
|
+
let data = this.textureData;
|
|
30181
|
+
if (data == null)
|
|
30182
|
+
return null;
|
|
30183
|
+
if (typeof data === "string") {
|
|
30184
|
+
try {
|
|
30185
|
+
data = JSON.parse(data);
|
|
30186
|
+
}
|
|
30187
|
+
catch (e) {
|
|
30188
|
+
console.warn("TextureAtlasSkin: bad textureData JSON", e);
|
|
30189
|
+
return null;
|
|
30190
|
+
}
|
|
30191
|
+
}
|
|
30192
|
+
return (data != null && data.skins != null) ? data : null;
|
|
30193
|
+
}
|
|
30194
|
+
toInt(v, def) {
|
|
30195
|
+
const n = (typeof v === "number") ? v : parseInt(v, 10);
|
|
30196
|
+
return isNaN(n) ? def : Math.floor(n);
|
|
30197
|
+
}
|
|
30198
|
+
isConfigured(material) {
|
|
30199
|
+
return !!(material && material.metadata && material.metadata.atlasSkinConfigured === true);
|
|
30200
|
+
}
|
|
30201
|
+
markConfigured(material) {
|
|
30202
|
+
material.metadata = material.metadata || {};
|
|
30203
|
+
material.metadata.atlasSkinConfigured = true;
|
|
30204
|
+
}
|
|
30205
|
+
describeKind(kind) {
|
|
30206
|
+
if (kind === "vat")
|
|
30207
|
+
return "VAT Mesh (packed cell index)";
|
|
30208
|
+
if (kind === "instanced")
|
|
30209
|
+
return "Instanced Mesh (per-instance UV buffer)";
|
|
30210
|
+
return "Babylon Mesh (cloned material uniform)";
|
|
30211
|
+
}
|
|
30212
|
+
}
|
|
29257
30213
|
export class UserInterface extends ScriptComponent {
|
|
29258
30214
|
constructor(transform, scene, properties = {}, alias = "UserInterface") {
|
|
29259
30215
|
super(transform, scene, properties, alias);
|
|
@@ -30775,6 +31731,7 @@ SceneManager.RegisterClass("CustomShaderMaterial", CustomShaderMaterial);
|
|
|
30775
31731
|
SceneManager.RegisterClass("UniversalShaderMaterial", UniversalShaderMaterial);
|
|
30776
31732
|
SceneManager.RegisterClass("UnityStyleLightingPlugin", UnityStyleLightingPlugin);
|
|
30777
31733
|
SceneManager.RegisterClass("CustomShaderMaterialPlugin", CustomShaderMaterialPlugin);
|
|
31734
|
+
SceneManager.RegisterClass("SkinArraySwitchingPlugin", SkinArraySwitchingPlugin);
|
|
30778
31735
|
SceneManager.RegisterClass("StandardShaderMaterial", StandardShaderMaterial);
|
|
30779
31736
|
SceneManager.RegisterClass("StandardShaderMaterialPlugin", StandardShaderMaterialPlugin);
|
|
30780
31737
|
SceneManager.RegisterClass("UniversalTerrainMaterial", UniversalTerrainMaterial);
|
|
@@ -41407,7 +42364,9 @@ SceneManager.RegisterClass("NavigationAgent", NavigationAgent);
|
|
|
41407
42364
|
SceneManager.RegisterClass("PostProcessor", PostProcessor);
|
|
41408
42365
|
SceneManager.RegisterClass("RigidbodyPhysics", RigidbodyPhysics);
|
|
41409
42366
|
SceneManager.RegisterClass("ShurikenParticles", ShurikenParticles);
|
|
42367
|
+
SceneManager.RegisterClass("SkinTextureArray", SkinTextureArray);
|
|
41410
42368
|
SceneManager.RegisterClass("TerrainBuilder", TerrainBuilder);
|
|
42369
|
+
SceneManager.RegisterClass("TextureAtlasSkin", TextureAtlasSkin);
|
|
41411
42370
|
SceneManager.RegisterClass("UnitySlider", UnitySlider);
|
|
41412
42371
|
SceneManager.RegisterClass("UnityScrollBar", UnityScrollBar);
|
|
41413
42372
|
SceneManager.RegisterClass("UnityDropdownMenu", UnityDropdownMenu);
|