@babylonjs-toolkit/next 9.12.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 +141 -40
- package/lib/scenemanager.d.ts.map +1 -1
- package/lib/scenemanager.js +1268 -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.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() {
|
|
@@ -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);
|
|
@@ -5530,10 +5543,18 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5530
5543
|
this.shader = null;
|
|
5531
5544
|
this.plugin = null;
|
|
5532
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;
|
|
5533
5552
|
this.shader = "CustomShaderMaterial";
|
|
5534
5553
|
this.addFloatUniform("tkIblDiffuseScale", 1.0);
|
|
5535
5554
|
this.addFloatUniform("tkIblSpecularScale", 1.0);
|
|
5555
|
+
this.addFloatUniform("tkSkinLayerUni", 0.0);
|
|
5536
5556
|
this._unityLightingPlugin = new UnityStyleLightingPlugin(this, this.shader);
|
|
5557
|
+
this._skinArraySwitchingPlugin = new SkinArraySwitchingPlugin(this);
|
|
5537
5558
|
}
|
|
5538
5559
|
initMaterial() {
|
|
5539
5560
|
if (this["awake"])
|
|
@@ -5567,6 +5588,108 @@ export class CustomShaderMaterial extends PBRMaterial {
|
|
|
5567
5588
|
this.plugin?.markAllDefinesAsDirty();
|
|
5568
5589
|
this._unityLightingPlugin?.markAllDefinesAsDirty();
|
|
5569
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
|
+
}
|
|
5570
5693
|
addTextureUniform(name, texture) {
|
|
5571
5694
|
this.checkSampler(name, texture);
|
|
5572
5695
|
this._textures[name] = texture;
|
|
@@ -6009,6 +6132,301 @@ export class UnityStyleLightingPlugin extends CustomShaderMaterialPlugin {
|
|
|
6009
6132
|
this.getCustomShaderMaterial().updateCustomBindings(uniformBuffer);
|
|
6010
6133
|
}
|
|
6011
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
|
+
}
|
|
6012
6430
|
export class UniversalShaderMaterial extends CustomShaderMaterial {
|
|
6013
6431
|
constructor(name, scene) {
|
|
6014
6432
|
super(name, scene);
|
|
@@ -11736,8 +12154,10 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11736
12154
|
constructor(name, scene) {
|
|
11737
12155
|
super(name, scene);
|
|
11738
12156
|
this.controller = null;
|
|
11739
|
-
this.
|
|
11740
|
-
this.
|
|
12157
|
+
this._vatSkinArray = false;
|
|
12158
|
+
this._vatSkinArrayNormal = false;
|
|
12159
|
+
this._vatSkinArrayMetalRough = false;
|
|
12160
|
+
this._vatSkinArrayEmissive = false;
|
|
11741
12161
|
this.shader = this.getShaderName();
|
|
11742
12162
|
this.addAttribute("g_vatAnim0");
|
|
11743
12163
|
this.addAttribute("g_vatAnim1");
|
|
@@ -11793,97 +12213,90 @@ export class VertexAnimationMaterial extends CustomShaderMaterial {
|
|
|
11793
12213
|
cloned.alpha = this.alpha;
|
|
11794
12214
|
cloned.alphaMode = this.alphaMode;
|
|
11795
12215
|
cloned.transparencyMode = this.transparencyMode;
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
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
|
+
}
|
|
11799
12240
|
return cloned;
|
|
11800
12241
|
}
|
|
11801
|
-
|
|
11802
|
-
this.
|
|
11803
|
-
this.
|
|
11804
|
-
if (
|
|
11805
|
-
this.
|
|
11806
|
-
|
|
11807
|
-
}
|
|
11808
|
-
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;
|
|
11809
12248
|
}
|
|
11810
|
-
|
|
11811
|
-
this.
|
|
11812
|
-
this.
|
|
11813
|
-
this.
|
|
12249
|
+
disableVatSkinArray() {
|
|
12250
|
+
this._vatSkinArray = false;
|
|
12251
|
+
this.markAsDirty(Constants.MATERIAL_AllDirtyFlag);
|
|
12252
|
+
if (this.plugin)
|
|
12253
|
+
this.plugin.markAllDefinesAsDirty();
|
|
11814
12254
|
}
|
|
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
|
-
}
|
|
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;
|
|
11886
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;
|
|
11887
12300
|
}
|
|
11888
12301
|
}
|
|
11889
12302
|
export class VertexAnimationController {
|
|
@@ -11918,15 +12331,15 @@ export class VertexAnimationController {
|
|
|
11918
12331
|
}
|
|
11919
12332
|
return result;
|
|
11920
12333
|
}
|
|
11921
|
-
static
|
|
12334
|
+
static SetAtlasCellIndex(mesh, cellIndex) {
|
|
11922
12335
|
if (!mesh)
|
|
11923
12336
|
return;
|
|
11924
|
-
mesh.
|
|
12337
|
+
mesh.atlasCellIndex = Math.max(0, Math.floor(cellIndex || 0));
|
|
11925
12338
|
}
|
|
11926
|
-
static
|
|
12339
|
+
static GetAtlasCellIndex(mesh) {
|
|
11927
12340
|
if (!mesh)
|
|
11928
12341
|
return 0;
|
|
11929
|
-
const v = mesh.
|
|
12342
|
+
const v = mesh.atlasCellIndex;
|
|
11930
12343
|
return (typeof v === "number" && isFinite(v) && v >= 0) ? Math.floor(v) : 0;
|
|
11931
12344
|
}
|
|
11932
12345
|
static DisposeAll(scene) {
|
|
@@ -12010,39 +12423,6 @@ export class VertexAnimationController {
|
|
|
12010
12423
|
}
|
|
12011
12424
|
setSpeed(speed) { this._speed = speed; }
|
|
12012
12425
|
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
12426
|
setCurrentTime(time) {
|
|
12047
12427
|
if (!this._currentClip)
|
|
12048
12428
|
return;
|
|
@@ -12252,9 +12632,9 @@ export class VertexAnimationController {
|
|
|
12252
12632
|
const s = current.settings;
|
|
12253
12633
|
anim0.set(this._time * s.vertexfps, s.vertexframes, current.fromRow, this._blendWeight);
|
|
12254
12634
|
const loopFlag = this._loopBlend ? 1.0 : 0.0;
|
|
12255
|
-
const
|
|
12256
|
-
const
|
|
12257
|
-
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;
|
|
12258
12638
|
const prev = this.getPreviousRendererClip(rendererGuid);
|
|
12259
12639
|
if (prev && this._previousClip && this._blendWeight < 0.999 && this._isRendererPositionReady(prev)) {
|
|
12260
12640
|
const ps = prev.settings;
|
|
@@ -12424,17 +12804,17 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12424
12804
|
super(customMaterial, shaderName, 100, {
|
|
12425
12805
|
VERTEXANIMATIONMATERIAL: false,
|
|
12426
12806
|
VAT_NORMAL_SEPARATE: false,
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
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
|
|
12430
12812
|
});
|
|
12431
12813
|
this.vertexAnimations = null;
|
|
12432
12814
|
this.controller = null;
|
|
12433
12815
|
this._rendererTargets = [];
|
|
12434
12816
|
this._targetRendererGuid = "";
|
|
12435
12817
|
this._placeholderTexture = null;
|
|
12436
|
-
this._placeholderAlbedoArray = null;
|
|
12437
|
-
this._placeholderNormalArray = null;
|
|
12438
12818
|
this._cc_posTex = null;
|
|
12439
12819
|
this._cc_normTex = null;
|
|
12440
12820
|
this._cc_prevPosTex = null;
|
|
@@ -12456,24 +12836,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12456
12836
|
customMaterial.setTextureValue("vatNormal", this._placeholderTexture);
|
|
12457
12837
|
customMaterial.setTextureValue("vatPrevPosition", this._placeholderTexture);
|
|
12458
12838
|
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
12839
|
}
|
|
12464
12840
|
dispose() {
|
|
12465
12841
|
if (this._placeholderTexture) {
|
|
12466
12842
|
this._placeholderTexture.dispose();
|
|
12467
12843
|
this._placeholderTexture = null;
|
|
12468
12844
|
}
|
|
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
12845
|
super.dispose();
|
|
12478
12846
|
}
|
|
12479
12847
|
isCompatible(shaderLanguage) {
|
|
@@ -12487,28 +12855,32 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12487
12855
|
CUSTOM_VERTEX_DEFINITIONS: this.getWGSLVertexDefinitions(),
|
|
12488
12856
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getWGSLVertexPositionCode(),
|
|
12489
12857
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getWGSLVertexNormalCode(),
|
|
12490
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12858
|
+
CUSTOM_VERTEX_MAIN_END: this.getWGSLSkinLayerVaryingCode()
|
|
12491
12859
|
};
|
|
12492
12860
|
}
|
|
12493
12861
|
return {
|
|
12494
12862
|
CUSTOM_VERTEX_DEFINITIONS: this.getGLSLVertexDefinitions(),
|
|
12495
12863
|
CUSTOM_VERTEX_UPDATE_POSITION: this.getGLSLVertexPositionCode(),
|
|
12496
12864
|
CUSTOM_VERTEX_UPDATE_NORMAL: this.getGLSLVertexNormalCode(),
|
|
12497
|
-
CUSTOM_VERTEX_MAIN_END: this.
|
|
12865
|
+
CUSTOM_VERTEX_MAIN_END: this.getGLSLSkinLayerVaryingCode()
|
|
12498
12866
|
};
|
|
12499
12867
|
}
|
|
12500
12868
|
if (shaderType === "fragment") {
|
|
12501
12869
|
if (wgsl) {
|
|
12502
12870
|
return {
|
|
12503
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12504
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12505
|
-
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()
|
|
12506
12876
|
};
|
|
12507
12877
|
}
|
|
12508
12878
|
return {
|
|
12509
|
-
CUSTOM_FRAGMENT_DEFINITIONS: this.
|
|
12510
|
-
CUSTOM_FRAGMENT_UPDATE_ALBEDO: this.
|
|
12511
|
-
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()
|
|
12512
12884
|
};
|
|
12513
12885
|
}
|
|
12514
12886
|
return null;
|
|
@@ -12523,13 +12895,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12523
12895
|
const customSamplers = this.getCustomShaderMaterial().getCustomSamplers();
|
|
12524
12896
|
if (customSamplers != null && customSamplers.length > 0)
|
|
12525
12897
|
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
12898
|
}
|
|
12534
12899
|
getAttributes(attributes, scene, mesh) {
|
|
12535
12900
|
const customAttributes = this.getCustomShaderMaterial().getCustomAttributes();
|
|
@@ -12545,15 +12910,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12545
12910
|
defines.VAT_NORMAL_SEPARATE = (mode === "separate");
|
|
12546
12911
|
const engine = scene ? scene.getEngine() : null;
|
|
12547
12912
|
defines.UV3 = !(engine && engine.isWebGPU);
|
|
12548
|
-
const
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
defines.
|
|
12552
|
-
defines.
|
|
12553
|
-
defines.
|
|
12554
|
-
}
|
|
12555
|
-
onRuntimeSkinArraysChanged() {
|
|
12556
|
-
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);
|
|
12557
12919
|
}
|
|
12558
12920
|
bindForSubMesh(uniformBuffer, scene, engine, subMesh) {
|
|
12559
12921
|
if (!this.getIsEnabled())
|
|
@@ -12561,16 +12923,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12561
12923
|
const renderMesh = subMesh && subMesh.getRenderingMesh ? subMesh.getRenderingMesh() : null;
|
|
12562
12924
|
this._captureRendererTarget(renderMesh || (subMesh ? subMesh.getMesh() : null));
|
|
12563
12925
|
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
12926
|
}
|
|
12575
12927
|
setupAnimations(settings, controllerId, rootUrl = "", lazyLoadTextures = false) {
|
|
12576
12928
|
this.vertexAnimations = settings;
|
|
@@ -12823,7 +13175,6 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12823
13175
|
}
|
|
12824
13176
|
bindVATToEffect(effect) {
|
|
12825
13177
|
this._pushVATUniforms(effect, true);
|
|
12826
|
-
this._pushRuntimeSkinSamplers(effect);
|
|
12827
13178
|
}
|
|
12828
13179
|
_pushVATUniforms(buf, isEffect) {
|
|
12829
13180
|
const fb = this._placeholderTexture;
|
|
@@ -12896,13 +13247,12 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12896
13247
|
uniform sampler2D vatPrevPosition;
|
|
12897
13248
|
uniform sampler2D vatPrevNormal;
|
|
12898
13249
|
#endif
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
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
|
|
12906
13256
|
#endif
|
|
12907
13257
|
`;
|
|
12908
13258
|
}
|
|
@@ -12916,8 +13266,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12916
13266
|
float vatPrevFrame = g_vatAnim1.x;
|
|
12917
13267
|
float vatPrevFrameCount = g_vatAnim1.y;
|
|
12918
13268
|
float vatPrevFromRow = g_vatAnim1.z;
|
|
12919
|
-
|
|
12920
|
-
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
|
|
12921
13274
|
if (vatFrameCount > 0.5) {
|
|
12922
13275
|
// GLSL path uses the third UV channel:
|
|
12923
13276
|
// Unity uv3 -> glTF TEXCOORD_2 -> Babylon shader uv3
|
|
@@ -12985,9 +13338,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
12985
13338
|
float vatNormFrame = g_vatAnim0.x;
|
|
12986
13339
|
float vatNormFrameCount = g_vatAnim0.y;
|
|
12987
13340
|
float vatNormFromRow = g_vatAnim0.z;
|
|
12988
|
-
|
|
12989
|
-
float
|
|
12990
|
-
|
|
13341
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13342
|
+
float vatNormLoopBlend = mod(g_vatAnim1.w, 2.0);
|
|
13343
|
+
#else
|
|
13344
|
+
float vatNormLoopBlend = g_vatAnim1.w;
|
|
13345
|
+
#endif
|
|
12991
13346
|
|
|
12992
13347
|
if (vatNormFrameCount > 0.5) {
|
|
12993
13348
|
// GLSL path uses the third UV channel:
|
|
@@ -13033,9 +13388,10 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13033
13388
|
var vatPrevPositionSampler: sampler;
|
|
13034
13389
|
var vatPrevNormal: texture_2d<f32>;
|
|
13035
13390
|
var vatPrevNormalSampler: sampler;
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
varying
|
|
13391
|
+
#endif
|
|
13392
|
+
#ifdef VAT_SKIN_ARRAY
|
|
13393
|
+
varying vVatSkinLayer: f32;
|
|
13394
|
+
varying vVatSkinUV: vec2<f32>;
|
|
13039
13395
|
#endif
|
|
13040
13396
|
`;
|
|
13041
13397
|
}
|
|
@@ -13049,8 +13405,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13049
13405
|
let vatPrevFrame = vertexInputs.g_vatAnim1.x;
|
|
13050
13406
|
let vatPrevFrameCount = vertexInputs.g_vatAnim1.y;
|
|
13051
13407
|
let vatPrevFromRow = vertexInputs.g_vatAnim1.z;
|
|
13052
|
-
|
|
13053
|
-
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
|
|
13054
13413
|
if (vatFrameCount > 0.5) {
|
|
13055
13414
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13056
13415
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13119,8 +13478,11 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13119
13478
|
let vatNormFrame = vertexInputs.g_vatAnim0.x;
|
|
13120
13479
|
let vatNormFrameCount = vertexInputs.g_vatAnim0.y;
|
|
13121
13480
|
let vatNormFromRow = vertexInputs.g_vatAnim0.z;
|
|
13122
|
-
|
|
13123
|
-
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
|
|
13124
13486
|
if (vatNormFrameCount > 0.5) {
|
|
13125
13487
|
// WGSL path derives the VAT texel coordinate from the vertex index instead
|
|
13126
13488
|
// of consuming a dedicated uv3 vertex-buffer slot.
|
|
@@ -13157,130 +13519,187 @@ export class VertexAnimationMaterialPlugin extends CustomShaderMaterialPlugin {
|
|
|
13157
13519
|
#endif
|
|
13158
13520
|
`;
|
|
13159
13521
|
}
|
|
13160
|
-
|
|
13522
|
+
getGLSLSkinLayerVaryingCode() {
|
|
13161
13523
|
return `
|
|
13162
|
-
#ifdef
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
#endif
|
|
13171
|
-
}
|
|
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
|
|
13172
13532
|
#endif
|
|
13173
13533
|
`;
|
|
13174
13534
|
}
|
|
13175
|
-
|
|
13535
|
+
getGLSLSkinFragmentDefs() {
|
|
13176
13536
|
return `
|
|
13177
|
-
#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
|
|
13178
13559
|
{
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
#ifdef
|
|
13182
|
-
|
|
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;
|
|
13183
13564
|
#else
|
|
13184
|
-
|
|
13565
|
+
surfaceAlbedo = _vatSkinAlbedo.rgb * vAlbedoColor.rgb;
|
|
13566
|
+
#endif
|
|
13567
|
+
#ifdef ALPHATEST
|
|
13568
|
+
if (_vatSkinAlbedo.a < alphaCutOff) discard;
|
|
13185
13569
|
#endif
|
|
13186
13570
|
}
|
|
13187
13571
|
#endif
|
|
13188
13572
|
`;
|
|
13189
13573
|
}
|
|
13190
|
-
|
|
13574
|
+
getGLSLSkinNormalCode() {
|
|
13191
13575
|
return `
|
|
13192
|
-
#
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
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
|
+
}
|
|
13198
13581
|
#endif
|
|
13199
13582
|
`;
|
|
13200
13583
|
}
|
|
13201
|
-
|
|
13584
|
+
getGLSLSkinMetalRoughSampleCode() {
|
|
13202
13585
|
return `
|
|
13203
|
-
#ifdef
|
|
13586
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13204
13587
|
{
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
surfaceAlbedo = _rsAlbedo.rgb * vAlbedoColor.rgb;
|
|
13208
|
-
#ifdef ALPHATEST
|
|
13209
|
-
if (_rsAlbedo.a < alphaCutOff) discard;
|
|
13210
|
-
#endif
|
|
13588
|
+
vec4 _vatMRtexel = texture(tkMetalRoughArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5)));
|
|
13589
|
+
_tkMR = vec2(_vatMRtexel.b, _vatMRtexel.g);
|
|
13211
13590
|
}
|
|
13212
13591
|
#endif
|
|
13213
13592
|
`;
|
|
13214
13593
|
}
|
|
13215
|
-
|
|
13594
|
+
getGLSLSkinMetalRoughApplyCode() {
|
|
13216
13595
|
return `
|
|
13217
|
-
#
|
|
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() {
|
|
13603
|
+
return `
|
|
13604
|
+
#if defined(VAT_SKIN_ARRAY) && defined(VAT_SKIN_ARRAY_EMISSIVE)
|
|
13218
13605
|
{
|
|
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);
|
|
13606
|
+
vec3 _vatEmis = texture(tkEmissiveArray, vec3(vVatSkinUV, floor(vVatSkinLayer + 0.5))).rgb;
|
|
13607
|
+
finalEmissive = toLinearSpace(_vatEmis);
|
|
13235
13608
|
}
|
|
13236
13609
|
#endif
|
|
13237
13610
|
`;
|
|
13238
13611
|
}
|
|
13239
|
-
|
|
13612
|
+
getWGSLSkinLayerVaryingCode() {
|
|
13240
13613
|
return `
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
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
|
|
13247
13623
|
`;
|
|
13248
13624
|
}
|
|
13249
|
-
|
|
13625
|
+
getWGSLSkinFragmentDefs() {
|
|
13250
13626
|
return `
|
|
13251
|
-
#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
|
|
13252
13653
|
{
|
|
13253
|
-
let
|
|
13254
|
-
|
|
13255
|
-
|
|
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
|
|
13256
13661
|
#ifdef ALPHATEST
|
|
13257
|
-
if (
|
|
13662
|
+
if (_vatSkinAlbedo.a < alphaCutOff) { discard; }
|
|
13258
13663
|
#endif
|
|
13259
13664
|
}
|
|
13260
13665
|
#endif
|
|
13261
13666
|
`;
|
|
13262
13667
|
}
|
|
13263
|
-
|
|
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() {
|
|
13264
13680
|
return `
|
|
13265
|
-
#ifdef
|
|
13681
|
+
#ifdef VAT_SKIN_ARRAY_MR
|
|
13266
13682
|
{
|
|
13267
|
-
let
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
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);
|
|
13284
13703
|
}
|
|
13285
13704
|
#endif
|
|
13286
13705
|
`;
|
|
@@ -27680,6 +28099,138 @@ ShurikenParticles.UNITY_TO_BABYLON_LIFETIME_RATIO = 0.65;
|
|
|
27680
28099
|
ShurikenParticles.UNITY_TO_BABYLON_DEATH_FADE_ALPHA = 0.2;
|
|
27681
28100
|
ShurikenParticles.EMITTER_POSITION_OFFSET = new Vector3(0, 0, 0);
|
|
27682
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 = {};
|
|
27683
28234
|
export class MeshNormalProxy {
|
|
27684
28235
|
constructor() {
|
|
27685
28236
|
this.blendWithPhysicsNormal = 0.0;
|
|
@@ -29254,6 +29805,410 @@ TerrainBuilder.detailChunkMaxTotalChunks = 256;
|
|
|
29254
29805
|
TerrainBuilder.meshDetailChunkMode = 1;
|
|
29255
29806
|
TerrainBuilder.meshDetailChunkTargetInstances = 20000;
|
|
29256
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
|
+
}
|
|
29257
30212
|
export class UserInterface extends ScriptComponent {
|
|
29258
30213
|
constructor(transform, scene, properties = {}, alias = "UserInterface") {
|
|
29259
30214
|
super(transform, scene, properties, alias);
|
|
@@ -30775,6 +31730,7 @@ SceneManager.RegisterClass("CustomShaderMaterial", CustomShaderMaterial);
|
|
|
30775
31730
|
SceneManager.RegisterClass("UniversalShaderMaterial", UniversalShaderMaterial);
|
|
30776
31731
|
SceneManager.RegisterClass("UnityStyleLightingPlugin", UnityStyleLightingPlugin);
|
|
30777
31732
|
SceneManager.RegisterClass("CustomShaderMaterialPlugin", CustomShaderMaterialPlugin);
|
|
31733
|
+
SceneManager.RegisterClass("SkinArraySwitchingPlugin", SkinArraySwitchingPlugin);
|
|
30778
31734
|
SceneManager.RegisterClass("StandardShaderMaterial", StandardShaderMaterial);
|
|
30779
31735
|
SceneManager.RegisterClass("StandardShaderMaterialPlugin", StandardShaderMaterialPlugin);
|
|
30780
31736
|
SceneManager.RegisterClass("UniversalTerrainMaterial", UniversalTerrainMaterial);
|
|
@@ -41407,7 +42363,9 @@ SceneManager.RegisterClass("NavigationAgent", NavigationAgent);
|
|
|
41407
42363
|
SceneManager.RegisterClass("PostProcessor", PostProcessor);
|
|
41408
42364
|
SceneManager.RegisterClass("RigidbodyPhysics", RigidbodyPhysics);
|
|
41409
42365
|
SceneManager.RegisterClass("ShurikenParticles", ShurikenParticles);
|
|
42366
|
+
SceneManager.RegisterClass("SkinTextureArray", SkinTextureArray);
|
|
41410
42367
|
SceneManager.RegisterClass("TerrainBuilder", TerrainBuilder);
|
|
42368
|
+
SceneManager.RegisterClass("TextureAtlasSkin", TextureAtlasSkin);
|
|
41411
42369
|
SceneManager.RegisterClass("UnitySlider", UnitySlider);
|
|
41412
42370
|
SceneManager.RegisterClass("UnityScrollBar", UnityScrollBar);
|
|
41413
42371
|
SceneManager.RegisterClass("UnityDropdownMenu", UnityDropdownMenu);
|