123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473 |
- import { SerializationHelper } from "../Misc/decorators.serialization.js";
- import { Scene } from "../scene.js";
- import { Matrix, Vector3, Vector2, Vector4, Quaternion } from "../Maths/math.vector.js";
- import { VertexBuffer } from "../Buffers/buffer.js";
- import { Texture } from "../Materials/Textures/texture.js";
- import { RegisterClass } from "../Misc/typeStore.js";
- import { Color3, Color4 } from "../Maths/math.color.js";
- import { EffectFallbacks } from "./effectFallbacks.js";
- import { WebRequest } from "../Misc/webRequest.js";
- import { PushMaterial } from "./pushMaterial.js";
- import { EngineStore } from "../Engines/engineStore.js";
- import { addClipPlaneUniforms, bindClipPlane, prepareStringDefinesForClipPlanes } from "./clipPlaneMaterialHelper.js";
- import { BindBonesParameters, BindFogParameters, BindLogDepth, BindMorphTargetParameters, BindSceneUniformBuffer, PrepareAttributesForBakedVertexAnimation, PushAttributesForInstances, } from "./materialHelper.functions.js";
- const onCreatedEffectParameters = { effect: null, subMesh: null };
- /**
- * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
- *
- * This returned material effects how the mesh will look based on the code in the shaders.
- *
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/shaderMaterial
- */
- export class ShaderMaterial extends PushMaterial {
- /**
- * Instantiate a new shader material.
- * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
- * This returned material effects how the mesh will look based on the code in the shaders.
- * @see https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/shaderMaterial
- * @param name Define the name of the material in the scene
- * @param scene Define the scene the material belongs to
- * @param shaderPath Defines the route to the shader code.
- * @param options Define the options used to create the shader
- * @param storeEffectOnSubMeshes true to store effect on submeshes, false to store the effect directly in the material class.
- */
- constructor(name, scene, shaderPath, options = {}, storeEffectOnSubMeshes = true) {
- super(name, scene, storeEffectOnSubMeshes);
- this._textures = {};
- this._textureArrays = {};
- this._externalTextures = {};
- this._floats = {};
- this._ints = {};
- this._uints = {};
- this._floatsArrays = {};
- this._colors3 = {};
- this._colors3Arrays = {};
- this._colors4 = {};
- this._colors4Arrays = {};
- this._vectors2 = {};
- this._vectors3 = {};
- this._vectors4 = {};
- this._quaternions = {};
- this._quaternionsArrays = {};
- this._matrices = {};
- this._matrixArrays = {};
- this._matrices3x3 = {};
- this._matrices2x2 = {};
- this._vectors2Arrays = {};
- this._vectors3Arrays = {};
- this._vectors4Arrays = {};
- this._uniformBuffers = {};
- this._textureSamplers = {};
- this._storageBuffers = {};
- this._cachedWorldViewMatrix = new Matrix();
- this._cachedWorldViewProjectionMatrix = new Matrix();
- this._multiview = false;
- /**
- * @internal
- */
- this._materialHelperNeedsPreviousMatrices = false;
- this._shaderPath = shaderPath;
- this._options = {
- needAlphaBlending: false,
- needAlphaTesting: false,
- attributes: ["position", "normal", "uv"],
- uniforms: ["worldViewProjection"],
- uniformBuffers: [],
- samplers: [],
- externalTextures: [],
- samplerObjects: [],
- storageBuffers: [],
- defines: [],
- useClipPlane: false,
- ...options,
- };
- }
- /**
- * Gets the shader path used to define the shader code
- * It can be modified to trigger a new compilation
- */
- get shaderPath() {
- return this._shaderPath;
- }
- /**
- * Sets the shader path used to define the shader code
- * It can be modified to trigger a new compilation
- */
- set shaderPath(shaderPath) {
- this._shaderPath = shaderPath;
- }
- /**
- * Gets the options used to compile the shader.
- * They can be modified to trigger a new compilation
- */
- get options() {
- return this._options;
- }
- /**
- * is multiview set to true?
- */
- get isMultiview() {
- return this._multiview;
- }
- /**
- * Gets the current class name of the material e.g. "ShaderMaterial"
- * Mainly use in serialization.
- * @returns the class name
- */
- getClassName() {
- return "ShaderMaterial";
- }
- /**
- * Specifies if the material will require alpha blending
- * @returns a boolean specifying if alpha blending is needed
- */
- needAlphaBlending() {
- return this.alpha < 1.0 || this._options.needAlphaBlending;
- }
- /**
- * Specifies if this material should be rendered in alpha test mode
- * @returns a boolean specifying if an alpha test is needed.
- */
- needAlphaTesting() {
- return this._options.needAlphaTesting;
- }
- _checkUniform(uniformName) {
- if (this._options.uniforms.indexOf(uniformName) === -1) {
- this._options.uniforms.push(uniformName);
- }
- }
- /**
- * Set a texture in the shader.
- * @param name Define the name of the uniform samplers as defined in the shader
- * @param texture Define the texture to bind to this sampler
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setTexture(name, texture) {
- if (this._options.samplers.indexOf(name) === -1) {
- this._options.samplers.push(name);
- }
- this._textures[name] = texture;
- return this;
- }
- /**
- * Set a texture array in the shader.
- * @param name Define the name of the uniform sampler array as defined in the shader
- * @param textures Define the list of textures to bind to this sampler
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setTextureArray(name, textures) {
- if (this._options.samplers.indexOf(name) === -1) {
- this._options.samplers.push(name);
- }
- this._checkUniform(name);
- this._textureArrays[name] = textures;
- return this;
- }
- /**
- * Set an internal texture in the shader.
- * @param name Define the name of the uniform samplers as defined in the shader
- * @param texture Define the texture to bind to this sampler
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setExternalTexture(name, texture) {
- if (this._options.externalTextures.indexOf(name) === -1) {
- this._options.externalTextures.push(name);
- }
- this._externalTextures[name] = texture;
- return this;
- }
- /**
- * Set a float in the shader.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setFloat(name, value) {
- this._checkUniform(name);
- this._floats[name] = value;
- return this;
- }
- /**
- * Set a int in the shader.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setInt(name, value) {
- this._checkUniform(name);
- this._ints[name] = value;
- return this;
- }
- /**
- * Set a unsigned int in the shader.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setUInt(name, value) {
- this._checkUniform(name);
- this._uints[name] = value;
- return this;
- }
- /**
- * Set an array of floats in the shader.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setFloats(name, value) {
- this._checkUniform(name);
- this._floatsArrays[name] = value;
- return this;
- }
- /**
- * Set a vec3 in the shader from a Color3.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setColor3(name, value) {
- this._checkUniform(name);
- this._colors3[name] = value;
- return this;
- }
- /**
- * Set a vec3 array in the shader from a Color3 array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setColor3Array(name, value) {
- this._checkUniform(name);
- this._colors3Arrays[name] = value.reduce((arr, color) => {
- color.toArray(arr, arr.length);
- return arr;
- }, []);
- return this;
- }
- /**
- * Set a vec4 in the shader from a Color4.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setColor4(name, value) {
- this._checkUniform(name);
- this._colors4[name] = value;
- return this;
- }
- /**
- * Set a vec4 array in the shader from a Color4 array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setColor4Array(name, value) {
- this._checkUniform(name);
- this._colors4Arrays[name] = value.reduce((arr, color) => {
- color.toArray(arr, arr.length);
- return arr;
- }, []);
- return this;
- }
- /**
- * Set a vec2 in the shader from a Vector2.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setVector2(name, value) {
- this._checkUniform(name);
- this._vectors2[name] = value;
- return this;
- }
- /**
- * Set a vec3 in the shader from a Vector3.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setVector3(name, value) {
- this._checkUniform(name);
- this._vectors3[name] = value;
- return this;
- }
- /**
- * Set a vec4 in the shader from a Vector4.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setVector4(name, value) {
- this._checkUniform(name);
- this._vectors4[name] = value;
- return this;
- }
- /**
- * Set a vec4 in the shader from a Quaternion.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setQuaternion(name, value) {
- this._checkUniform(name);
- this._quaternions[name] = value;
- return this;
- }
- /**
- * Set a vec4 array in the shader from a Quaternion array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setQuaternionArray(name, value) {
- this._checkUniform(name);
- this._quaternionsArrays[name] = value.reduce((arr, quaternion) => {
- quaternion.toArray(arr, arr.length);
- return arr;
- }, []);
- return this;
- }
- /**
- * Set a mat4 in the shader from a Matrix.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setMatrix(name, value) {
- this._checkUniform(name);
- this._matrices[name] = value;
- return this;
- }
- /**
- * Set a float32Array in the shader from a matrix array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setMatrices(name, value) {
- this._checkUniform(name);
- const float32Array = new Float32Array(value.length * 16);
- for (let index = 0; index < value.length; index++) {
- const matrix = value[index];
- matrix.copyToArray(float32Array, index * 16);
- }
- this._matrixArrays[name] = float32Array;
- return this;
- }
- /**
- * Set a mat3 in the shader from a Float32Array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setMatrix3x3(name, value) {
- this._checkUniform(name);
- this._matrices3x3[name] = value;
- return this;
- }
- /**
- * Set a mat2 in the shader from a Float32Array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setMatrix2x2(name, value) {
- this._checkUniform(name);
- this._matrices2x2[name] = value;
- return this;
- }
- /**
- * Set a vec2 array in the shader from a number array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setArray2(name, value) {
- this._checkUniform(name);
- this._vectors2Arrays[name] = value;
- return this;
- }
- /**
- * Set a vec3 array in the shader from a number array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setArray3(name, value) {
- this._checkUniform(name);
- this._vectors3Arrays[name] = value;
- return this;
- }
- /**
- * Set a vec4 array in the shader from a number array.
- * @param name Define the name of the uniform as defined in the shader
- * @param value Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setArray4(name, value) {
- this._checkUniform(name);
- this._vectors4Arrays[name] = value;
- return this;
- }
- /**
- * Set a uniform buffer in the shader
- * @param name Define the name of the uniform as defined in the shader
- * @param buffer Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setUniformBuffer(name, buffer) {
- if (this._options.uniformBuffers.indexOf(name) === -1) {
- this._options.uniformBuffers.push(name);
- }
- this._uniformBuffers[name] = buffer;
- return this;
- }
- /**
- * Set a texture sampler in the shader
- * @param name Define the name of the uniform as defined in the shader
- * @param sampler Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setTextureSampler(name, sampler) {
- if (this._options.samplerObjects.indexOf(name) === -1) {
- this._options.samplerObjects.push(name);
- }
- this._textureSamplers[name] = sampler;
- return this;
- }
- /**
- * Set a storage buffer in the shader
- * @param name Define the name of the storage buffer as defined in the shader
- * @param buffer Define the value to give to the uniform
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setStorageBuffer(name, buffer) {
- if (this._options.storageBuffers.indexOf(name) === -1) {
- this._options.storageBuffers.push(name);
- }
- this._storageBuffers[name] = buffer;
- return this;
- }
- /**
- * Adds, removes, or replaces the specified shader define and value.
- * * setDefine("MY_DEFINE", true); // enables a boolean define
- * * setDefine("MY_DEFINE", "0.5"); // adds "#define MY_DEFINE 0.5" to the shader (or sets and replaces the value of any existing define with that name)
- * * setDefine("MY_DEFINE", false); // disables and removes the define
- * Note if the active defines do change, the shader will be recompiled and this can be expensive.
- * @param define the define name e.g., "OUTPUT_TO_SRGB" or "#define OUTPUT_TO_SRGB". If the define was passed into the constructor already, the version used should match that, and in either case, it should not include any appended value.
- * @param value either the value of the define (e.g. a numerical value) or for booleans, true if the define should be enabled or false if it should be disabled
- * @returns the material itself allowing "fluent" like uniform updates
- */
- setDefine(define, value) {
- // First remove any existing define with this name.
- const defineName = define.trimEnd() + " ";
- const existingDefineIdx = this.options.defines.findIndex((x) => x === define || x.startsWith(defineName));
- if (existingDefineIdx >= 0) {
- this.options.defines.splice(existingDefineIdx, 1);
- }
- // Then add the new define value. (If it's a boolean value and false, don't add it.)
- if (typeof value !== "boolean" || value) {
- this.options.defines.push(defineName + value);
- }
- return this;
- }
- /**
- * Specifies that the submesh is ready to be used
- * @param mesh defines the mesh to check
- * @param subMesh defines which submesh to check
- * @param useInstances specifies that instances should be used
- * @returns a boolean indicating that the submesh is ready or not
- */
- isReadyForSubMesh(mesh, subMesh, useInstances) {
- return this.isReady(mesh, useInstances, subMesh);
- }
- /**
- * Checks if the material is ready to render the requested mesh
- * @param mesh Define the mesh to render
- * @param useInstances Define whether or not the material is used with instances
- * @param subMesh defines which submesh to render
- * @returns true if ready, otherwise false
- */
- isReady(mesh, useInstances, subMesh) {
- const storeEffectOnSubMeshes = subMesh && this._storeEffectOnSubMeshes;
- if (this.isFrozen) {
- const drawWrapper = storeEffectOnSubMeshes ? subMesh._drawWrapper : this._drawWrapper;
- if (drawWrapper.effect && drawWrapper._wasPreviouslyReady && drawWrapper._wasPreviouslyUsingInstances === useInstances) {
- return true;
- }
- }
- const scene = this.getScene();
- const engine = scene.getEngine();
- // Instances
- const defines = [];
- const attribs = [];
- const fallbacks = new EffectFallbacks();
- let shaderName = this._shaderPath, uniforms = this._options.uniforms, uniformBuffers = this._options.uniformBuffers, samplers = this._options.samplers;
- // global multiview
- if (engine.getCaps().multiview && scene.activeCamera && scene.activeCamera.outputRenderTarget && scene.activeCamera.outputRenderTarget.getViewCount() > 1) {
- this._multiview = true;
- defines.push("#define MULTIVIEW");
- if (uniforms.indexOf("viewProjection") !== -1 && uniforms.indexOf("viewProjectionR") === -1) {
- uniforms.push("viewProjectionR");
- }
- }
- for (let index = 0; index < this._options.defines.length; index++) {
- const defineToAdd = this._options.defines[index].indexOf("#define") === 0 ? this._options.defines[index] : `#define ${this._options.defines[index]}`;
- defines.push(defineToAdd);
- }
- for (let index = 0; index < this._options.attributes.length; index++) {
- attribs.push(this._options.attributes[index]);
- }
- if (mesh && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
- if (attribs.indexOf(VertexBuffer.ColorKind) === -1) {
- attribs.push(VertexBuffer.ColorKind);
- }
- defines.push("#define VERTEXCOLOR");
- }
- if (useInstances) {
- defines.push("#define INSTANCES");
- PushAttributesForInstances(attribs, this._materialHelperNeedsPreviousMatrices);
- if (mesh?.hasThinInstances) {
- defines.push("#define THIN_INSTANCES");
- if (mesh && mesh.isVerticesDataPresent(VertexBuffer.ColorInstanceKind)) {
- attribs.push(VertexBuffer.ColorInstanceKind);
- defines.push("#define INSTANCESCOLOR");
- }
- }
- }
- // Bones
- if (mesh && mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
- attribs.push(VertexBuffer.MatricesIndicesKind);
- attribs.push(VertexBuffer.MatricesWeightsKind);
- if (mesh.numBoneInfluencers > 4) {
- attribs.push(VertexBuffer.MatricesIndicesExtraKind);
- attribs.push(VertexBuffer.MatricesWeightsExtraKind);
- }
- const skeleton = mesh.skeleton;
- defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
- fallbacks.addCPUSkinningFallback(0, mesh);
- if (skeleton.isUsingTextureForMatrices) {
- defines.push("#define BONETEXTURE");
- if (uniforms.indexOf("boneTextureWidth") === -1) {
- uniforms.push("boneTextureWidth");
- }
- if (this._options.samplers.indexOf("boneSampler") === -1) {
- this._options.samplers.push("boneSampler");
- }
- }
- else {
- defines.push("#define BonesPerMesh " + (skeleton.bones.length + 1));
- if (uniforms.indexOf("mBones") === -1) {
- uniforms.push("mBones");
- }
- }
- }
- else {
- defines.push("#define NUM_BONE_INFLUENCERS 0");
- }
- // Morph
- let numInfluencers = 0;
- const manager = mesh ? mesh.morphTargetManager : null;
- if (manager) {
- const uv = manager.supportsUVs && defines.indexOf("#define UV1") !== -1;
- const tangent = manager.supportsTangents && defines.indexOf("#define TANGENT") !== -1;
- const normal = manager.supportsNormals && defines.indexOf("#define NORMAL") !== -1;
- numInfluencers = manager.numMaxInfluencers || manager.numInfluencers;
- if (uv) {
- defines.push("#define MORPHTARGETS_UV");
- }
- if (tangent) {
- defines.push("#define MORPHTARGETS_TANGENT");
- }
- if (normal) {
- defines.push("#define MORPHTARGETS_NORMAL");
- }
- if (numInfluencers > 0) {
- defines.push("#define MORPHTARGETS");
- }
- if (manager.isUsingTextureForTargets) {
- defines.push("#define MORPHTARGETS_TEXTURE");
- if (uniforms.indexOf("morphTargetTextureIndices") === -1) {
- uniforms.push("morphTargetTextureIndices");
- }
- if (this._options.samplers.indexOf("morphTargets") === -1) {
- this._options.samplers.push("morphTargets");
- }
- }
- defines.push("#define NUM_MORPH_INFLUENCERS " + numInfluencers);
- for (let index = 0; index < numInfluencers; index++) {
- attribs.push(VertexBuffer.PositionKind + index);
- if (normal) {
- attribs.push(VertexBuffer.NormalKind + index);
- }
- if (tangent) {
- attribs.push(VertexBuffer.TangentKind + index);
- }
- if (uv) {
- attribs.push(VertexBuffer.UVKind + "_" + index);
- }
- }
- if (numInfluencers > 0) {
- uniforms = uniforms.slice();
- uniforms.push("morphTargetInfluences");
- uniforms.push("morphTargetCount");
- uniforms.push("morphTargetTextureInfo");
- uniforms.push("morphTargetTextureIndices");
- }
- }
- else {
- defines.push("#define NUM_MORPH_INFLUENCERS 0");
- }
- // Baked Vertex Animation
- if (mesh) {
- const bvaManager = mesh.bakedVertexAnimationManager;
- if (bvaManager && bvaManager.isEnabled) {
- defines.push("#define BAKED_VERTEX_ANIMATION_TEXTURE");
- if (uniforms.indexOf("bakedVertexAnimationSettings") === -1) {
- uniforms.push("bakedVertexAnimationSettings");
- }
- if (uniforms.indexOf("bakedVertexAnimationTextureSizeInverted") === -1) {
- uniforms.push("bakedVertexAnimationTextureSizeInverted");
- }
- if (uniforms.indexOf("bakedVertexAnimationTime") === -1) {
- uniforms.push("bakedVertexAnimationTime");
- }
- if (this._options.samplers.indexOf("bakedVertexAnimationTexture") === -1) {
- this._options.samplers.push("bakedVertexAnimationTexture");
- }
- }
- PrepareAttributesForBakedVertexAnimation(attribs, mesh, defines);
- }
- // Textures
- for (const name in this._textures) {
- if (!this._textures[name].isReady()) {
- return false;
- }
- }
- // Alpha test
- if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
- defines.push("#define ALPHATEST");
- }
- // Clip planes
- if (this._options.useClipPlane !== false) {
- addClipPlaneUniforms(uniforms);
- prepareStringDefinesForClipPlanes(this, scene, defines);
- }
- // Fog
- if (scene.fogEnabled && mesh?.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
- defines.push("#define FOG");
- if (uniforms.indexOf("view") === -1) {
- uniforms.push("view");
- }
- if (uniforms.indexOf("vFogInfos") === -1) {
- uniforms.push("vFogInfos");
- }
- if (uniforms.indexOf("vFogColor") === -1) {
- uniforms.push("vFogColor");
- }
- }
- // Misc
- if (this._useLogarithmicDepth) {
- defines.push("#define LOGARITHMICDEPTH");
- if (uniforms.indexOf("logarithmicDepthConstant") === -1) {
- uniforms.push("logarithmicDepthConstant");
- }
- }
- if (this.customShaderNameResolve) {
- uniforms = uniforms.slice();
- uniformBuffers = uniformBuffers.slice();
- samplers = samplers.slice();
- shaderName = this.customShaderNameResolve(this.name, uniforms, uniformBuffers, samplers, defines, attribs);
- }
- const drawWrapper = storeEffectOnSubMeshes ? subMesh._getDrawWrapper(undefined, true) : this._drawWrapper;
- const previousEffect = drawWrapper?.effect ?? null;
- const previousDefines = drawWrapper?.defines ?? null;
- const join = defines.join("\n");
- let effect = previousEffect;
- if (previousDefines !== join) {
- effect = engine.createEffect(shaderName, {
- attributes: attribs,
- uniformsNames: uniforms,
- uniformBuffersNames: uniformBuffers,
- samplers: samplers,
- defines: join,
- fallbacks: fallbacks,
- onCompiled: this.onCompiled,
- onError: this.onError,
- indexParameters: { maxSimultaneousMorphTargets: numInfluencers },
- shaderLanguage: this._options.shaderLanguage,
- }, engine);
- if (storeEffectOnSubMeshes) {
- subMesh.setEffect(effect, join, this._materialContext);
- }
- else if (drawWrapper) {
- drawWrapper.setEffect(effect, join);
- }
- if (this._onEffectCreatedObservable) {
- onCreatedEffectParameters.effect = effect;
- onCreatedEffectParameters.subMesh = subMesh ?? mesh?.subMeshes[0] ?? null;
- this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
- }
- }
- drawWrapper._wasPreviouslyUsingInstances = !!useInstances;
- if (!effect?.isReady() ?? true) {
- return false;
- }
- if (previousEffect !== effect) {
- scene.resetCachedMaterial();
- }
- drawWrapper._wasPreviouslyReady = true;
- return true;
- }
- /**
- * Binds the world matrix to the material
- * @param world defines the world transformation matrix
- * @param effectOverride - If provided, use this effect instead of internal effect
- */
- bindOnlyWorldMatrix(world, effectOverride) {
- const scene = this.getScene();
- const effect = effectOverride ?? this.getEffect();
- if (!effect) {
- return;
- }
- if (this._options.uniforms.indexOf("world") !== -1) {
- effect.setMatrix("world", world);
- }
- if (this._options.uniforms.indexOf("worldView") !== -1) {
- world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
- effect.setMatrix("worldView", this._cachedWorldViewMatrix);
- }
- if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
- world.multiplyToRef(scene.getTransformMatrix(), this._cachedWorldViewProjectionMatrix);
- effect.setMatrix("worldViewProjection", this._cachedWorldViewProjectionMatrix);
- }
- if (this._options.uniforms.indexOf("view") !== -1) {
- effect.setMatrix("view", scene.getViewMatrix());
- }
- }
- /**
- * Binds the submesh to this material by preparing the effect and shader to draw
- * @param world defines the world transformation matrix
- * @param mesh defines the mesh containing the submesh
- * @param subMesh defines the submesh to bind the material to
- */
- bindForSubMesh(world, mesh, subMesh) {
- this.bind(world, mesh, subMesh._drawWrapperOverride?.effect, subMesh);
- }
- /**
- * Binds the material to the mesh
- * @param world defines the world transformation matrix
- * @param mesh defines the mesh to bind the material to
- * @param effectOverride - If provided, use this effect instead of internal effect
- * @param subMesh defines the submesh to bind the material to
- */
- bind(world, mesh, effectOverride, subMesh) {
- // Std values
- const storeEffectOnSubMeshes = subMesh && this._storeEffectOnSubMeshes;
- const effect = effectOverride ?? (storeEffectOnSubMeshes ? subMesh.effect : this.getEffect());
- if (!effect) {
- return;
- }
- const scene = this.getScene();
- this._activeEffect = effect;
- this.bindOnlyWorldMatrix(world, effectOverride);
- const uniformBuffers = this._options.uniformBuffers;
- let useSceneUBO = false;
- if (effect && uniformBuffers && uniformBuffers.length > 0 && scene.getEngine().supportsUniformBuffers) {
- for (let i = 0; i < uniformBuffers.length; ++i) {
- const bufferName = uniformBuffers[i];
- switch (bufferName) {
- case "Mesh":
- if (mesh) {
- mesh.getMeshUniformBuffer().bindToEffect(effect, "Mesh");
- mesh.transferToEffect(world);
- }
- break;
- case "Scene":
- BindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
- scene.finalizeSceneUbo();
- useSceneUBO = true;
- break;
- }
- }
- }
- const mustRebind = mesh && storeEffectOnSubMeshes ? this._mustRebind(scene, effect, subMesh, mesh.visibility) : scene.getCachedMaterial() !== this;
- if (effect && mustRebind) {
- if (!useSceneUBO && this._options.uniforms.indexOf("view") !== -1) {
- effect.setMatrix("view", scene.getViewMatrix());
- }
- if (!useSceneUBO && this._options.uniforms.indexOf("projection") !== -1) {
- effect.setMatrix("projection", scene.getProjectionMatrix());
- }
- if (!useSceneUBO && this._options.uniforms.indexOf("viewProjection") !== -1) {
- effect.setMatrix("viewProjection", scene.getTransformMatrix());
- if (this._multiview) {
- effect.setMatrix("viewProjectionR", scene._transformMatrixR);
- }
- }
- if (scene.activeCamera && this._options.uniforms.indexOf("cameraPosition") !== -1) {
- effect.setVector3("cameraPosition", scene.activeCamera.globalPosition);
- }
- // Bones
- BindBonesParameters(mesh, effect);
- // Clip plane
- bindClipPlane(effect, this, scene);
- // Misc
- if (this._useLogarithmicDepth) {
- BindLogDepth(storeEffectOnSubMeshes ? subMesh.materialDefines : effect.defines, effect, scene);
- }
- // Fog
- if (mesh) {
- BindFogParameters(scene, mesh, effect);
- }
- let name;
- // Texture
- for (name in this._textures) {
- effect.setTexture(name, this._textures[name]);
- }
- // Texture arrays
- for (name in this._textureArrays) {
- effect.setTextureArray(name, this._textureArrays[name]);
- }
- // External texture
- for (name in this._externalTextures) {
- effect.setExternalTexture(name, this._externalTextures[name]);
- }
- // Int
- for (name in this._ints) {
- effect.setInt(name, this._ints[name]);
- }
- // UInt
- for (name in this._uints) {
- effect.setUInt(name, this._uints[name]);
- }
- // Float
- for (name in this._floats) {
- effect.setFloat(name, this._floats[name]);
- }
- // Floats
- for (name in this._floatsArrays) {
- effect.setArray(name, this._floatsArrays[name]);
- }
- // Color3
- for (name in this._colors3) {
- effect.setColor3(name, this._colors3[name]);
- }
- // Color3Array
- for (name in this._colors3Arrays) {
- effect.setArray3(name, this._colors3Arrays[name]);
- }
- // Color4
- for (name in this._colors4) {
- const color = this._colors4[name];
- effect.setFloat4(name, color.r, color.g, color.b, color.a);
- }
- // Color4Array
- for (name in this._colors4Arrays) {
- effect.setArray4(name, this._colors4Arrays[name]);
- }
- // Vector2
- for (name in this._vectors2) {
- effect.setVector2(name, this._vectors2[name]);
- }
- // Vector3
- for (name in this._vectors3) {
- effect.setVector3(name, this._vectors3[name]);
- }
- // Vector4
- for (name in this._vectors4) {
- effect.setVector4(name, this._vectors4[name]);
- }
- // Quaternion
- for (name in this._quaternions) {
- effect.setQuaternion(name, this._quaternions[name]);
- }
- // Matrix
- for (name in this._matrices) {
- effect.setMatrix(name, this._matrices[name]);
- }
- // MatrixArray
- for (name in this._matrixArrays) {
- effect.setMatrices(name, this._matrixArrays[name]);
- }
- // Matrix 3x3
- for (name in this._matrices3x3) {
- effect.setMatrix3x3(name, this._matrices3x3[name]);
- }
- // Matrix 2x2
- for (name in this._matrices2x2) {
- effect.setMatrix2x2(name, this._matrices2x2[name]);
- }
- // Vector2Array
- for (name in this._vectors2Arrays) {
- effect.setArray2(name, this._vectors2Arrays[name]);
- }
- // Vector3Array
- for (name in this._vectors3Arrays) {
- effect.setArray3(name, this._vectors3Arrays[name]);
- }
- // Vector4Array
- for (name in this._vectors4Arrays) {
- effect.setArray4(name, this._vectors4Arrays[name]);
- }
- // QuaternionArray
- for (name in this._quaternionsArrays) {
- effect.setArray4(name, this._quaternionsArrays[name]);
- }
- // Uniform buffers
- for (name in this._uniformBuffers) {
- const buffer = this._uniformBuffers[name].getBuffer();
- if (buffer) {
- effect.bindUniformBuffer(buffer, name);
- }
- }
- // Samplers
- for (name in this._textureSamplers) {
- effect.setTextureSampler(name, this._textureSamplers[name]);
- }
- // Storage buffers
- for (name in this._storageBuffers) {
- effect.setStorageBuffer(name, this._storageBuffers[name]);
- }
- }
- if (effect && mesh && (mustRebind || !this.isFrozen)) {
- // Morph targets
- const manager = mesh.morphTargetManager;
- if (manager && manager.numInfluencers > 0) {
- BindMorphTargetParameters(mesh, effect);
- }
- const bvaManager = mesh.bakedVertexAnimationManager;
- if (bvaManager && bvaManager.isEnabled) {
- const drawWrapper = storeEffectOnSubMeshes ? subMesh._drawWrapper : this._drawWrapper;
- mesh.bakedVertexAnimationManager?.bind(effect, !!drawWrapper._wasPreviouslyUsingInstances);
- }
- }
- this._afterBind(mesh, effect, subMesh);
- }
- /**
- * Gets the active textures from the material
- * @returns an array of textures
- */
- getActiveTextures() {
- const activeTextures = super.getActiveTextures();
- for (const name in this._textures) {
- activeTextures.push(this._textures[name]);
- }
- for (const name in this._textureArrays) {
- const array = this._textureArrays[name];
- for (let index = 0; index < array.length; index++) {
- activeTextures.push(array[index]);
- }
- }
- return activeTextures;
- }
- /**
- * Specifies if the material uses a texture
- * @param texture defines the texture to check against the material
- * @returns a boolean specifying if the material uses the texture
- */
- hasTexture(texture) {
- if (super.hasTexture(texture)) {
- return true;
- }
- for (const name in this._textures) {
- if (this._textures[name] === texture) {
- return true;
- }
- }
- for (const name in this._textureArrays) {
- const array = this._textureArrays[name];
- for (let index = 0; index < array.length; index++) {
- if (array[index] === texture) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * Makes a duplicate of the material, and gives it a new name
- * @param name defines the new name for the duplicated material
- * @returns the cloned material
- */
- clone(name) {
- const result = SerializationHelper.Clone(() => new ShaderMaterial(name, this.getScene(), this._shaderPath, this._options, this._storeEffectOnSubMeshes), this);
- result.name = name;
- result.id = name;
- // Shader code path
- if (typeof result._shaderPath === "object") {
- result._shaderPath = { ...result._shaderPath };
- }
- // Options
- this._options = { ...this._options };
- Object.keys(this._options).forEach((propName) => {
- const propValue = this._options[propName];
- if (Array.isArray(propValue)) {
- this._options[propName] = propValue.slice(0);
- }
- });
- // Stencil
- this.stencil.copyTo(result.stencil);
- // Texture
- for (const key in this._textures) {
- result.setTexture(key, this._textures[key]);
- }
- // TextureArray
- for (const key in this._textureArrays) {
- result.setTextureArray(key, this._textureArrays[key]);
- }
- // External texture
- for (const key in this._externalTextures) {
- result.setExternalTexture(key, this._externalTextures[key]);
- }
- // Int
- for (const key in this._ints) {
- result.setInt(key, this._ints[key]);
- }
- // UInt
- for (const key in this._uints) {
- result.setUInt(key, this._uints[key]);
- }
- // Float
- for (const key in this._floats) {
- result.setFloat(key, this._floats[key]);
- }
- // Floats
- for (const key in this._floatsArrays) {
- result.setFloats(key, this._floatsArrays[key]);
- }
- // Color3
- for (const key in this._colors3) {
- result.setColor3(key, this._colors3[key]);
- }
- // Color3Array
- for (const key in this._colors3Arrays) {
- result._colors3Arrays[key] = this._colors3Arrays[key];
- }
- // Color4
- for (const key in this._colors4) {
- result.setColor4(key, this._colors4[key]);
- }
- // Color4Array
- for (const key in this._colors4Arrays) {
- result._colors4Arrays[key] = this._colors4Arrays[key];
- }
- // Vector2
- for (const key in this._vectors2) {
- result.setVector2(key, this._vectors2[key]);
- }
- // Vector3
- for (const key in this._vectors3) {
- result.setVector3(key, this._vectors3[key]);
- }
- // Vector4
- for (const key in this._vectors4) {
- result.setVector4(key, this._vectors4[key]);
- }
- // Quaternion
- for (const key in this._quaternions) {
- result.setQuaternion(key, this._quaternions[key]);
- }
- // QuaternionArray
- for (const key in this._quaternionsArrays) {
- result._quaternionsArrays[key] = this._quaternionsArrays[key];
- }
- // Matrix
- for (const key in this._matrices) {
- result.setMatrix(key, this._matrices[key]);
- }
- // MatrixArray
- for (const key in this._matrixArrays) {
- result._matrixArrays[key] = this._matrixArrays[key].slice();
- }
- // Matrix 3x3
- for (const key in this._matrices3x3) {
- result.setMatrix3x3(key, this._matrices3x3[key]);
- }
- // Matrix 2x2
- for (const key in this._matrices2x2) {
- result.setMatrix2x2(key, this._matrices2x2[key]);
- }
- // Vector2Array
- for (const key in this._vectors2Arrays) {
- result.setArray2(key, this._vectors2Arrays[key]);
- }
- // Vector3Array
- for (const key in this._vectors3Arrays) {
- result.setArray3(key, this._vectors3Arrays[key]);
- }
- // Vector4Array
- for (const key in this._vectors4Arrays) {
- result.setArray4(key, this._vectors4Arrays[key]);
- }
- // Uniform buffers
- for (const key in this._uniformBuffers) {
- result.setUniformBuffer(key, this._uniformBuffers[key]);
- }
- // Samplers
- for (const key in this._textureSamplers) {
- result.setTextureSampler(key, this._textureSamplers[key]);
- }
- // Storag buffers
- for (const key in this._storageBuffers) {
- result.setStorageBuffer(key, this._storageBuffers[key]);
- }
- return result;
- }
- /**
- * Disposes the material
- * @param forceDisposeEffect specifies if effects should be forcefully disposed
- * @param forceDisposeTextures specifies if textures should be forcefully disposed
- * @param notBoundToMesh specifies if the material that is being disposed is known to be not bound to any mesh
- */
- dispose(forceDisposeEffect, forceDisposeTextures, notBoundToMesh) {
- if (forceDisposeTextures) {
- let name;
- for (name in this._textures) {
- this._textures[name].dispose();
- }
- for (name in this._textureArrays) {
- const array = this._textureArrays[name];
- for (let index = 0; index < array.length; index++) {
- array[index].dispose();
- }
- }
- }
- this._textures = {};
- super.dispose(forceDisposeEffect, forceDisposeTextures, notBoundToMesh);
- }
- /**
- * Serializes this material in a JSON representation
- * @returns the serialized material object
- */
- serialize() {
- const serializationObject = SerializationHelper.Serialize(this);
- serializationObject.customType = "BABYLON.ShaderMaterial";
- serializationObject.uniqueId = this.uniqueId;
- serializationObject.options = this._options;
- serializationObject.shaderPath = this._shaderPath;
- serializationObject.storeEffectOnSubMeshes = this._storeEffectOnSubMeshes;
- let name;
- // Stencil
- serializationObject.stencil = this.stencil.serialize();
- // Texture
- serializationObject.textures = {};
- for (name in this._textures) {
- serializationObject.textures[name] = this._textures[name].serialize();
- }
- // Texture arrays
- serializationObject.textureArrays = {};
- for (name in this._textureArrays) {
- serializationObject.textureArrays[name] = [];
- const array = this._textureArrays[name];
- for (let index = 0; index < array.length; index++) {
- serializationObject.textureArrays[name].push(array[index].serialize());
- }
- }
- // Int
- serializationObject.ints = {};
- for (name in this._ints) {
- serializationObject.ints[name] = this._ints[name];
- }
- // UInt
- serializationObject.uints = {};
- for (name in this._uints) {
- serializationObject.uints[name] = this._uints[name];
- }
- // Float
- serializationObject.floats = {};
- for (name in this._floats) {
- serializationObject.floats[name] = this._floats[name];
- }
- // Floats
- serializationObject.floatsArrays = {};
- for (name in this._floatsArrays) {
- serializationObject.floatsArrays[name] = this._floatsArrays[name];
- }
- // Color3
- serializationObject.colors3 = {};
- for (name in this._colors3) {
- serializationObject.colors3[name] = this._colors3[name].asArray();
- }
- // Color3 array
- serializationObject.colors3Arrays = {};
- for (name in this._colors3Arrays) {
- serializationObject.colors3Arrays[name] = this._colors3Arrays[name];
- }
- // Color4
- serializationObject.colors4 = {};
- for (name in this._colors4) {
- serializationObject.colors4[name] = this._colors4[name].asArray();
- }
- // Color4 array
- serializationObject.colors4Arrays = {};
- for (name in this._colors4Arrays) {
- serializationObject.colors4Arrays[name] = this._colors4Arrays[name];
- }
- // Vector2
- serializationObject.vectors2 = {};
- for (name in this._vectors2) {
- serializationObject.vectors2[name] = this._vectors2[name].asArray();
- }
- // Vector3
- serializationObject.vectors3 = {};
- for (name in this._vectors3) {
- serializationObject.vectors3[name] = this._vectors3[name].asArray();
- }
- // Vector4
- serializationObject.vectors4 = {};
- for (name in this._vectors4) {
- serializationObject.vectors4[name] = this._vectors4[name].asArray();
- }
- // Quaternion
- serializationObject.quaternions = {};
- for (name in this._quaternions) {
- serializationObject.quaternions[name] = this._quaternions[name].asArray();
- }
- // Matrix
- serializationObject.matrices = {};
- for (name in this._matrices) {
- serializationObject.matrices[name] = this._matrices[name].asArray();
- }
- // MatrixArray
- serializationObject.matrixArray = {};
- for (name in this._matrixArrays) {
- serializationObject.matrixArray[name] = this._matrixArrays[name];
- }
- // Matrix 3x3
- serializationObject.matrices3x3 = {};
- for (name in this._matrices3x3) {
- serializationObject.matrices3x3[name] = this._matrices3x3[name];
- }
- // Matrix 2x2
- serializationObject.matrices2x2 = {};
- for (name in this._matrices2x2) {
- serializationObject.matrices2x2[name] = this._matrices2x2[name];
- }
- // Vector2Array
- serializationObject.vectors2Arrays = {};
- for (name in this._vectors2Arrays) {
- serializationObject.vectors2Arrays[name] = this._vectors2Arrays[name];
- }
- // Vector3Array
- serializationObject.vectors3Arrays = {};
- for (name in this._vectors3Arrays) {
- serializationObject.vectors3Arrays[name] = this._vectors3Arrays[name];
- }
- // Vector4Array
- serializationObject.vectors4Arrays = {};
- for (name in this._vectors4Arrays) {
- serializationObject.vectors4Arrays[name] = this._vectors4Arrays[name];
- }
- // QuaternionArray
- serializationObject.quaternionsArrays = {};
- for (name in this._quaternionsArrays) {
- serializationObject.quaternionsArrays[name] = this._quaternionsArrays[name];
- }
- return serializationObject;
- }
- /**
- * Creates a shader material from parsed shader material data
- * @param source defines the JSON representation of the material
- * @param scene defines the hosting scene
- * @param rootUrl defines the root URL to use to load textures and relative dependencies
- * @returns a new material
- */
- static Parse(source, scene, rootUrl) {
- const material = SerializationHelper.Parse(() => new ShaderMaterial(source.name, scene, source.shaderPath, source.options, source.storeEffectOnSubMeshes), source, scene, rootUrl);
- let name;
- // Stencil
- if (source.stencil) {
- material.stencil.parse(source.stencil, scene, rootUrl);
- }
- // Texture
- for (name in source.textures) {
- material.setTexture(name, Texture.Parse(source.textures[name], scene, rootUrl));
- }
- // Texture arrays
- for (name in source.textureArrays) {
- const array = source.textureArrays[name];
- const textureArray = [];
- for (let index = 0; index < array.length; index++) {
- textureArray.push(Texture.Parse(array[index], scene, rootUrl));
- }
- material.setTextureArray(name, textureArray);
- }
- // Int
- for (name in source.ints) {
- material.setInt(name, source.ints[name]);
- }
- // UInt
- for (name in source.uints) {
- material.setUInt(name, source.uints[name]);
- }
- // Float
- for (name in source.floats) {
- material.setFloat(name, source.floats[name]);
- }
- // Floats
- for (name in source.floatsArrays) {
- material.setFloats(name, source.floatsArrays[name]);
- }
- // Color3
- for (name in source.colors3) {
- material.setColor3(name, Color3.FromArray(source.colors3[name]));
- }
- // Color3 arrays
- for (name in source.colors3Arrays) {
- const colors = source.colors3Arrays[name]
- .reduce((arr, num, i) => {
- if (i % 3 === 0) {
- arr.push([num]);
- }
- else {
- arr[arr.length - 1].push(num);
- }
- return arr;
- }, [])
- .map((color) => Color3.FromArray(color));
- material.setColor3Array(name, colors);
- }
- // Color4
- for (name in source.colors4) {
- material.setColor4(name, Color4.FromArray(source.colors4[name]));
- }
- // Color4 arrays
- for (name in source.colors4Arrays) {
- const colors = source.colors4Arrays[name]
- .reduce((arr, num, i) => {
- if (i % 4 === 0) {
- arr.push([num]);
- }
- else {
- arr[arr.length - 1].push(num);
- }
- return arr;
- }, [])
- .map((color) => Color4.FromArray(color));
- material.setColor4Array(name, colors);
- }
- // Vector2
- for (name in source.vectors2) {
- material.setVector2(name, Vector2.FromArray(source.vectors2[name]));
- }
- // Vector3
- for (name in source.vectors3) {
- material.setVector3(name, Vector3.FromArray(source.vectors3[name]));
- }
- // Vector4
- for (name in source.vectors4) {
- material.setVector4(name, Vector4.FromArray(source.vectors4[name]));
- }
- // Quaternion
- for (name in source.quaternions) {
- material.setQuaternion(name, Quaternion.FromArray(source.quaternions[name]));
- }
- // Matrix
- for (name in source.matrices) {
- material.setMatrix(name, Matrix.FromArray(source.matrices[name]));
- }
- // MatrixArray
- for (name in source.matrixArray) {
- material._matrixArrays[name] = new Float32Array(source.matrixArray[name]);
- }
- // Matrix 3x3
- for (name in source.matrices3x3) {
- material.setMatrix3x3(name, source.matrices3x3[name]);
- }
- // Matrix 2x2
- for (name in source.matrices2x2) {
- material.setMatrix2x2(name, source.matrices2x2[name]);
- }
- // Vector2Array
- for (name in source.vectors2Arrays) {
- material.setArray2(name, source.vectors2Arrays[name]);
- }
- // Vector3Array
- for (name in source.vectors3Arrays) {
- material.setArray3(name, source.vectors3Arrays[name]);
- }
- // Vector4Array
- for (name in source.vectors4Arrays) {
- material.setArray4(name, source.vectors4Arrays[name]);
- }
- // QuaternionArray
- for (name in source.quaternionsArrays) {
- material.setArray4(name, source.quaternionsArrays[name]);
- }
- return material;
- }
- /**
- * Creates a new ShaderMaterial from a snippet saved in a remote file
- * @param name defines the name of the ShaderMaterial to create (can be null or empty to use the one from the json data)
- * @param url defines the url to load from
- * @param scene defines the hosting scene
- * @param rootUrl defines the root URL to use to load textures and relative dependencies
- * @returns a promise that will resolve to the new ShaderMaterial
- */
- static ParseFromFileAsync(name, url, scene, rootUrl = "") {
- return new Promise((resolve, reject) => {
- const request = new WebRequest();
- request.addEventListener("readystatechange", () => {
- if (request.readyState == 4) {
- if (request.status == 200) {
- const serializationObject = JSON.parse(request.responseText);
- const output = this.Parse(serializationObject, scene || EngineStore.LastCreatedScene, rootUrl);
- if (name) {
- output.name = name;
- }
- resolve(output);
- }
- else {
- reject("Unable to load the ShaderMaterial");
- }
- }
- });
- request.open("GET", url);
- request.send();
- });
- }
- /**
- * Creates a ShaderMaterial from a snippet saved by the Inspector
- * @param snippetId defines the snippet to load
- * @param scene defines the hosting scene
- * @param rootUrl defines the root URL to use to load textures and relative dependencies
- * @returns a promise that will resolve to the new ShaderMaterial
- */
- static ParseFromSnippetAsync(snippetId, scene, rootUrl = "") {
- return new Promise((resolve, reject) => {
- const request = new WebRequest();
- request.addEventListener("readystatechange", () => {
- if (request.readyState == 4) {
- if (request.status == 200) {
- const snippet = JSON.parse(JSON.parse(request.responseText).jsonPayload);
- const serializationObject = JSON.parse(snippet.shaderMaterial);
- const output = this.Parse(serializationObject, scene || EngineStore.LastCreatedScene, rootUrl);
- output.snippetId = snippetId;
- resolve(output);
- }
- else {
- reject("Unable to load the snippet " + snippetId);
- }
- }
- });
- request.open("GET", this.SnippetUrl + "/" + snippetId.replace(/#/g, "/"));
- request.send();
- });
- }
- }
- /** Define the Url to load snippets */
- ShaderMaterial.SnippetUrl = `https://snippet.babylonjs.com`;
- /**
- * Creates a ShaderMaterial from a snippet saved by the Inspector
- * @deprecated Please use ParseFromSnippetAsync instead
- * @param snippetId defines the snippet to load
- * @param scene defines the hosting scene
- * @param rootUrl defines the root URL to use to load textures and relative dependencies
- * @returns a promise that will resolve to the new ShaderMaterial
- */
- ShaderMaterial.CreateFromSnippetAsync = ShaderMaterial.ParseFromSnippetAsync;
- RegisterClass("BABYLON.ShaderMaterial", ShaderMaterial);
- //# sourceMappingURL=shaderMaterial.js.map
|