cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
302 lines (301 loc) • 9.28 kB
JavaScript
import Base from "./core/Base.mjs";
import util from "./core/util.mjs";
import colorUtil from "./core/color.mjs";
var parseColor = colorUtil.parseToFloat;
var programKeyCache = {};
function getDefineCode(defines) {
var defineKeys = Object.keys(defines);
defineKeys.sort();
var defineStr = [];
for (var i = 0; i < defineKeys.length; i++) {
var key = defineKeys[i];
var value = defines[key];
if (value === null) {
defineStr.push(key);
} else {
defineStr.push(key + " " + value.toString());
}
}
return defineStr.join("\n");
}
function getProgramKey(vertexDefines, fragmentDefines, enabledTextures) {
enabledTextures.sort();
var defineStr = [];
for (var i = 0; i < enabledTextures.length; i++) {
var symbol = enabledTextures[i];
defineStr.push(symbol);
}
var key = getDefineCode(vertexDefines) + "\n" + getDefineCode(fragmentDefines) + "\n" + defineStr.join("\n");
if (programKeyCache[key]) {
return programKeyCache[key];
}
var id = util.genGUID();
programKeyCache[key] = id;
return id;
}
var Material = Base.extend(
function() {
return {
name: "",
depthTest: true,
depthMask: true,
transparent: false,
blend: null,
autoUpdateTextureStatus: true,
uniforms: {},
vertexDefines: {},
fragmentDefines: {},
_textureStatus: {},
_enabledUniforms: null
};
},
function() {
if (!this.name) {
this.name = "MATERIAL_" + this.__uid__;
}
if (this.shader) {
this.attachShader(this.shader, true);
}
},
{
precision: "highp",
setUniform: function(symbol, value) {
if (value === void 0) {
console.warn('Uniform value "' + symbol + '" is undefined');
}
var uniform = this.uniforms[symbol];
if (uniform) {
if (typeof value === "string") {
value = parseColor(value) || value;
}
uniform.value = value;
if (this.autoUpdateTextureStatus && uniform.type === "t") {
if (value) {
this.enableTexture(symbol);
} else {
this.disableTexture(symbol);
}
}
}
},
setUniforms: function(obj) {
for (var key in obj) {
var val = obj[key];
this.setUniform(key, val);
}
},
isUniformEnabled: function(symbol) {
return this._enabledUniforms.indexOf(symbol) >= 0;
},
getEnabledUniforms: function() {
return this._enabledUniforms;
},
getTextureUniforms: function() {
return this._textureUniforms;
},
set: function(symbol, value) {
if (typeof symbol === "object") {
for (var key in symbol) {
var val = symbol[key];
this.setUniform(key, val);
}
} else {
this.setUniform(symbol, value);
}
},
get: function(symbol) {
var uniform = this.uniforms[symbol];
if (uniform) {
return uniform.value;
}
},
attachShader: function(shader, keepStatus) {
var originalUniforms = this.uniforms;
this.uniforms = shader.createUniforms();
this.shader = shader;
var uniforms = this.uniforms;
this._enabledUniforms = Object.keys(uniforms);
this._enabledUniforms.sort();
this._textureUniforms = this._enabledUniforms.filter(function(uniformName) {
var type = this.uniforms[uniformName].type;
return type === "t" || type === "tv";
}, this);
var originalVertexDefines = this.vertexDefines;
var originalFragmentDefines = this.fragmentDefines;
this.vertexDefines = util.clone(shader.vertexDefines);
this.fragmentDefines = util.clone(shader.fragmentDefines);
if (keepStatus) {
for (var symbol in originalUniforms) {
if (uniforms[symbol]) {
uniforms[symbol].value = originalUniforms[symbol].value;
}
}
util.defaults(this.vertexDefines, originalVertexDefines);
util.defaults(this.fragmentDefines, originalFragmentDefines);
}
var textureStatus = {};
for (var key in shader.textures) {
textureStatus[key] = {
shaderType: shader.textures[key].shaderType,
type: shader.textures[key].type,
enabled: keepStatus && this._textureStatus[key] ? this._textureStatus[key].enabled : false
};
}
this._textureStatus = textureStatus;
this._programKey = "";
},
clone: function() {
var material = new this.constructor({
name: this.name,
shader: this.shader
});
for (var symbol in this.uniforms) {
material.uniforms[symbol].value = this.uniforms[symbol].value;
}
material.depthTest = this.depthTest;
material.depthMask = this.depthMask;
material.transparent = this.transparent;
material.blend = this.blend;
material.vertexDefines = util.clone(this.vertexDefines);
material.fragmentDefines = util.clone(this.fragmentDefines);
material.enableTexture(this.getEnabledTextures());
material.precision = this.precision;
return material;
},
define: function(shaderType, symbol, val) {
var vertexDefines = this.vertexDefines;
var fragmentDefines = this.fragmentDefines;
if (shaderType !== "vertex" && shaderType !== "fragment" && shaderType !== "both" && arguments.length < 3) {
val = symbol;
symbol = shaderType;
shaderType = "both";
}
val = val != null ? val : null;
if (shaderType === "vertex" || shaderType === "both") {
if (vertexDefines[symbol] !== val) {
vertexDefines[symbol] = val;
this._programKey = "";
}
}
if (shaderType === "fragment" || shaderType === "both") {
if (fragmentDefines[symbol] !== val) {
fragmentDefines[symbol] = val;
if (shaderType !== "both") {
this._programKey = "";
}
}
}
},
undefine: function(shaderType, symbol) {
if (shaderType !== "vertex" && shaderType !== "fragment" && shaderType !== "both" && arguments.length < 2) {
symbol = shaderType;
shaderType = "both";
}
if (shaderType === "vertex" || shaderType === "both") {
if (this.isDefined("vertex", symbol)) {
delete this.vertexDefines[symbol];
this._programKey = "";
}
}
if (shaderType === "fragment" || shaderType === "both") {
if (this.isDefined("fragment", symbol)) {
delete this.fragmentDefines[symbol];
if (shaderType !== "both") {
this._programKey = "";
}
}
}
},
isDefined: function(shaderType, symbol) {
switch (shaderType) {
case "vertex":
return this.vertexDefines[symbol] !== void 0;
case "fragment":
return this.fragmentDefines[symbol] !== void 0;
}
},
getDefine: function(shaderType, symbol) {
switch (shaderType) {
case "vertex":
return this.vertexDefines[symbol];
case "fragment":
return this.fragmentDefines[symbol];
}
},
enableTexture: function(symbol) {
if (Array.isArray(symbol)) {
for (var i = 0; i < symbol.length; i++) {
this.enableTexture(symbol[i]);
}
return;
}
var status = this._textureStatus[symbol];
if (status) {
var isEnabled = status.enabled;
if (!isEnabled) {
status.enabled = true;
this._programKey = "";
}
}
},
enableTexturesAll: function() {
var textureStatus = this._textureStatus;
for (var symbol in textureStatus) {
textureStatus[symbol].enabled = true;
}
this._programKey = "";
},
disableTexture: function(symbol) {
if (Array.isArray(symbol)) {
for (var i = 0; i < symbol.length; i++) {
this.disableTexture(symbol[i]);
}
return;
}
var status = this._textureStatus[symbol];
if (status) {
var isDisabled = !status.enabled;
if (!isDisabled) {
status.enabled = false;
this._programKey = "";
}
}
},
disableTexturesAll: function() {
var textureStatus = this._textureStatus;
for (var symbol in textureStatus) {
textureStatus[symbol].enabled = false;
}
this._programKey = "";
},
isTextureEnabled: function(symbol) {
var textureStatus = this._textureStatus;
return !!textureStatus[symbol] && textureStatus[symbol].enabled;
},
getEnabledTextures: function() {
var enabledTextures = [];
var textureStatus = this._textureStatus;
for (var symbol in textureStatus) {
if (textureStatus[symbol].enabled) {
enabledTextures.push(symbol);
}
}
return enabledTextures;
},
dirtyDefines: function() {
this._programKey = "";
},
getProgramKey: function() {
if (!this._programKey) {
this._programKey = getProgramKey(
this.vertexDefines,
this.fragmentDefines,
this.getEnabledTextures()
);
}
return this._programKey;
}
}
);
var Material$1 = Material;
export { Material$1 as default };