UNPKG

@babylonjs/materials

Version:

Babylon.js Materials Library =====================

355 lines 13.1 kB
import { Effect } from "@babylonjs/core/Materials/effect.js"; import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial.js"; import { RegisterClass } from "@babylonjs/core/Misc/typeStore.js"; import { Color3, Color4 } from "@babylonjs/core/Maths/math.color.js"; import "@babylonjs/core/Shaders/default.vertex.js"; import "@babylonjs/core/Shaders/default.fragment.js"; /** * Structure of a custom shader */ export class CustomShaderStructure { constructor() { } } /** * Parts of a shader */ export class ShaderSpecialParts { constructor() { } } /** * Customized material */ export class CustomMaterial extends StandardMaterial { /** * Runs after the material is bound to a mesh * @param mesh mesh bound * @param effect bound effect used to render */ AttachAfterBind(mesh, effect) { if (this._newUniformInstances) { for (const el in this._newUniformInstances) { const ea = el.toString().split("-"); if (ea[0] == "vec2") { effect.setVector2(ea[1], this._newUniformInstances[el]); } else if (ea[0] == "vec3") { if (this._newUniformInstances[el] instanceof Color3) { effect.setColor3(ea[1], this._newUniformInstances[el]); } else { effect.setVector3(ea[1], this._newUniformInstances[el]); } } else if (ea[0] == "vec4") { if (this._newUniformInstances[el] instanceof Color4) { effect.setDirectColor4(ea[1], this._newUniformInstances[el]); } else { effect.setVector4(ea[1], this._newUniformInstances[el]); } effect.setVector4(ea[1], this._newUniformInstances[el]); } else if (ea[0] == "mat4") { effect.setMatrix(ea[1], this._newUniformInstances[el]); } else if (ea[0] == "float") { effect.setFloat(ea[1], this._newUniformInstances[el]); } } } if (this._newSamplerInstances) { for (const el in this._newSamplerInstances) { const ea = el.toString().split("-"); if (ea[0] == "sampler2D" && this._newSamplerInstances[el].isReady && this._newSamplerInstances[el].isReady()) { effect.setTexture(ea[1], this._newSamplerInstances[el]); } } } } /** * @internal */ ReviewUniform(name, arr) { if (name == "uniform" && this._newUniforms) { for (let ind = 0; ind < this._newUniforms.length; ind++) { if (this._customUniform[ind].indexOf("sampler") == -1) { arr.push(this._newUniforms[ind].replace(/\[\d*\]/g, "")); } } } if (name == "sampler" && this._newUniforms) { for (let ind = 0; ind < this._newUniforms.length; ind++) { if (this._customUniform[ind].indexOf("sampler") != -1) { arr.push(this._newUniforms[ind].replace(/\[\d*\]/g, "")); } } } return arr; } /** * Builds the material * @param shaderName name of the shader * @param uniforms list of uniforms * @param uniformBuffers list of uniform buffers * @param samplers list of samplers * @param defines list of defines * @param attributes list of attributes * @returns the shader name */ Builder(shaderName, uniforms, uniformBuffers, samplers, defines, attributes) { if (attributes && this._customAttributes && this._customAttributes.length > 0) { attributes.push(...this._customAttributes); } this.ReviewUniform("uniform", uniforms); this.ReviewUniform("sampler", samplers); const name = this._createdShaderName; if (Effect.ShadersStore[name + "VertexShader"] && Effect.ShadersStore[name + "PixelShader"]) { return name; } Effect.ShadersStore[name + "VertexShader"] = this._injectCustomCode(this.VertexShader, "vertex"); Effect.ShadersStore[name + "PixelShader"] = this._injectCustomCode(this.FragmentShader, "fragment"); return name; } _injectCustomCode(code, shaderType) { const customCode = this._getCustomCode(shaderType); for (const point in customCode) { const injectedCode = customCode[point]; if (injectedCode && injectedCode.length > 0) { const fullPointName = "#define " + point; code = code.replace(fullPointName, "\n" + injectedCode + "\n" + fullPointName); } } return code; } _getCustomCode(shaderType) { if (shaderType === "vertex") { return { CUSTOM_VERTEX_BEGIN: this.CustomParts.Vertex_Begin, CUSTOM_VERTEX_DEFINITIONS: (this._customUniform?.join("\n") || "") + (this.CustomParts.Vertex_Definitions || ""), CUSTOM_VERTEX_MAIN_BEGIN: this.CustomParts.Vertex_MainBegin, CUSTOM_VERTEX_UPDATE_POSITION: this.CustomParts.Vertex_Before_PositionUpdated, CUSTOM_VERTEX_UPDATE_NORMAL: this.CustomParts.Vertex_Before_NormalUpdated, CUSTOM_VERTEX_MAIN_END: this.CustomParts.Vertex_MainEnd, CUSTOM_VERTEX_UPDATE_WORLDPOS: this.CustomParts.Vertex_After_WorldPosComputed, }; } return { CUSTOM_FRAGMENT_BEGIN: this.CustomParts.Fragment_Begin, CUSTOM_FRAGMENT_DEFINITIONS: (this._customUniform?.join("\n") || "") + (this.CustomParts.Fragment_Definitions || ""), CUSTOM_FRAGMENT_MAIN_BEGIN: this.CustomParts.Fragment_MainBegin, CUSTOM_FRAGMENT_UPDATE_DIFFUSE: this.CustomParts.Fragment_Custom_Diffuse, CUSTOM_FRAGMENT_UPDATE_ALPHA: this.CustomParts.Fragment_Custom_Alpha, CUSTOM_FRAGMENT_BEFORE_LIGHTS: this.CustomParts.Fragment_Before_Lights, CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: this.CustomParts.Fragment_Before_FragColor, CUSTOM_FRAGMENT_MAIN_END: this.CustomParts.Fragment_MainEnd, CUSTOM_FRAGMENT_BEFORE_FOG: this.CustomParts.Fragment_Before_Fog, }; } constructor(name, scene) { super(name, scene, true); this.CustomParts = new ShaderSpecialParts(); this.customShaderNameResolve = this.Builder; this.FragmentShader = Effect.ShadersStore["defaultPixelShader"]; this.VertexShader = Effect.ShadersStore["defaultVertexShader"]; CustomMaterial.ShaderIndexer++; this._createdShaderName = "custom_" + CustomMaterial.ShaderIndexer; } _afterBind(mesh, effect = null, subMesh) { if (!effect) { return; } this.AttachAfterBind(mesh, effect); try { super._afterBind(mesh, effect, subMesh); } catch (e) { } } /** * Adds a new uniform to the shader * @param name the name of the uniform to add * @param kind the type of the uniform to add * @param param the value of the uniform to add * @returns the current material */ AddUniform(name, kind, param) { if (!this._customUniform) { this._customUniform = new Array(); this._newUniforms = new Array(); this._newSamplerInstances = {}; this._newUniformInstances = {}; } if (param) { if (kind.indexOf("sampler") != -1) { this._newSamplerInstances[kind + "-" + name] = param; } else { this._newUniformInstances[kind + "-" + name] = param; } } this._customUniform.push("uniform " + kind + " " + name + ";"); this._newUniforms.push(name); return this; } /** * Adds a custom attribute * @param name the name of the attribute * @returns the current material */ AddAttribute(name) { if (!this._customAttributes) { this._customAttributes = []; } this._customAttributes.push(name); return this; } /** * Sets the code on Fragment_Begin portion * @param shaderPart the code string * @returns the current material */ Fragment_Begin(shaderPart) { this.CustomParts.Fragment_Begin = shaderPart; return this; } /** * Sets the code on Fragment_Definitions portion * @param shaderPart the code string * @returns the current material */ Fragment_Definitions(shaderPart) { this.CustomParts.Fragment_Definitions = shaderPart; return this; } /** * Sets the code on Fragment_MainBegin portion * @param shaderPart the code string * @returns the current material */ Fragment_MainBegin(shaderPart) { this.CustomParts.Fragment_MainBegin = shaderPart; return this; } /** * Sets the code on Fragment_MainEnd portion * @param shaderPart the code string * @returns the current material */ Fragment_MainEnd(shaderPart) { this.CustomParts.Fragment_MainEnd = shaderPart; return this; } /** * Sets the code on Fragment_Custom_Diffuse portion * @param shaderPart the code string * @returns the current material */ Fragment_Custom_Diffuse(shaderPart) { this.CustomParts.Fragment_Custom_Diffuse = shaderPart.replace("result", "diffuseColor"); return this; } /** * Sets the code on Fragment_Custom_Alpha portion * @param shaderPart the code string * @returns the current material */ Fragment_Custom_Alpha(shaderPart) { this.CustomParts.Fragment_Custom_Alpha = shaderPart.replace("result", "alpha"); return this; } /** * Sets the code on Fragment_Before_Lights portion * @param shaderPart the code string * @returns the current material */ Fragment_Before_Lights(shaderPart) { this.CustomParts.Fragment_Before_Lights = shaderPart; return this; } /** * Sets the code on Fragment_Before_Fog portion * @param shaderPart the code string * @returns the current material */ Fragment_Before_Fog(shaderPart) { this.CustomParts.Fragment_Before_Fog = shaderPart; return this; } /** * Sets the code on Fragment_Before_FragColor portion * @param shaderPart the code string * @returns the current material */ Fragment_Before_FragColor(shaderPart) { this.CustomParts.Fragment_Before_FragColor = shaderPart.replace("result", "color"); return this; } /** * Sets the code on Vertex_Begin portion * @param shaderPart the code string * @returns the current material */ Vertex_Begin(shaderPart) { this.CustomParts.Vertex_Begin = shaderPart; return this; } /** * Sets the code on Vertex_Definitions portion * @param shaderPart the code string * @returns the current material */ Vertex_Definitions(shaderPart) { this.CustomParts.Vertex_Definitions = shaderPart; return this; } /** * Sets the code on Vertex_MainBegin portion * @param shaderPart the code string * @returns the current material */ Vertex_MainBegin(shaderPart) { this.CustomParts.Vertex_MainBegin = shaderPart; return this; } /** * Sets the code on Vertex_Before_PositionUpdated portion * @param shaderPart the code string * @returns the current material */ Vertex_Before_PositionUpdated(shaderPart) { this.CustomParts.Vertex_Before_PositionUpdated = shaderPart.replace("result", "positionUpdated"); return this; } /** * Sets the code on Vertex_Before_NormalUpdated portion * @param shaderPart the code string * @returns the current material */ Vertex_Before_NormalUpdated(shaderPart) { this.CustomParts.Vertex_Before_NormalUpdated = shaderPart.replace("result", "normalUpdated"); return this; } /** * Sets the code on Vertex_After_WorldPosComputed portion * @param shaderPart the code string * @returns the current material */ Vertex_After_WorldPosComputed(shaderPart) { this.CustomParts.Vertex_After_WorldPosComputed = shaderPart; return this; } /** * Sets the code on Vertex_MainEnd portion * @param shaderPart the code string * @returns the current material */ Vertex_MainEnd(shaderPart) { this.CustomParts.Vertex_MainEnd = shaderPart; return this; } } /** * Index for each created shader */ CustomMaterial.ShaderIndexer = 1; RegisterClass("BABYLON.CustomMaterial", CustomMaterial); //# sourceMappingURL=customMaterial.js.map