cables_dev/cables/src/core/cgl/cgl_shader.js
- import { Logger } from "cables-shared-client";
- import { ShaderLibMods } from "./cgl_shader_lib.js";
- import { now } from "../timer.js";
- import { MESH } from "./cgl_mesh.js";
- import { CONSTANTS } from "./constants.js";
- import { escapeHTML } from "./cgl_utils.js";
- import { CgShader } from "../cg/cg_shader.js";
- import defaultShaderSrcVert from "./cgl_shader_default_glsl.vert";
- import { simpleId } from "../utils.js";
- // ---------------------------------------------------------------------------
-
-
- /*
-
- proposal default shader variable names:
-
- attrVertex - currently: vPosition
- attrVertexIndex - currently: attrVertIndex
- attrTexCoord
- attrInstMat - currently: instMat
- attrVertColor
- attrTangent
- attrBiTangent
-
- uProjMatrix - currently: projMatrix
- uModelMatrix - currently: modelMatrix
- uNormalMatrix - currently: normalMatrix
- uCamPosition - currently: camPos
-
- */
-
-
- // ---------------------------------------------------------------------------
-
- let materialIdCounter = 0;
-
-
-
-
- function getDefaultVertexShader()
- {
- return defaultShaderSrcVert;
- }
-
-
- function getDefaultFragmentShader(r, g, b)
- {
- if (r == undefined)
- {
- r = 0.5;
- g = 0.5;
- b = 0.5;
- }
- return ""
- .endl() + "IN vec2 texCoord;"
- .endl() + "{{MODULES_HEAD}}"
- .endl() + "void main()"
- .endl() + "{"
- .endl() + " vec4 col=vec4(" + r + "," + g + "," + b + ",1.0);"
- .endl() + " {{MODULE_COLOR}}"
- .endl() + " outColor = col;"
- .endl() + "}";
- };
-
-
- /**
- * @class
- * @namespace external:CGL
- * @hideconstructor
- * @param _cgl
- * @param _name
- * @param _op
- * @example
- * var shader=new CGL.Shader(cgl,'MinimalMaterial');
- * shader.setSource(attachments.shader_vert,attachments.shader_frag);
- */
- class Shader extends CgShader
- {
- constructor (_cgl, _name, _op)
- {
- super();
- if (!_cgl) throw new Error("shader constructed without cgl " + _name);
-
- this._log = new Logger("cgl_shader");
- this._cgl = _cgl;
-
- if (!_name) this._log.stack("no shader name given");
- this._name = _name || "unknown";
-
- if (_op) this.opId = _op.id;
- this.glslVersion = 0;
- if (_cgl.glVersion > 1) this.glslVersion = 300;
-
- this._materialId = ++materialIdCounter;
-
- this._program = null;
- this._uniforms = [];
- this._drawBuffers = [true];
-
- this._needsRecompile = true;
- this._compileReason = "initial";
-
- this.ignoreMissingUniforms = false;
- this._projMatrixUniform = null;
- this._mvMatrixUniform = null;
- this._mMatrixUniform = null;
- this._vMatrixUniform = null;
- this._camPosUniform = null;
- this._normalMatrixUniform = null;
- this._inverseViewMatrixUniform = null;
- this._fromUserInteraction = false;
-
- this._attrVertexPos = -1;
- this.precision = _cgl.patch.config.glslPrecision || "highp";
-
- this._pMatrixState = -1;
- this._vMatrixState = -1;
-
- this._countMissingUniforms = 0;
- this._modGroupCount = 0; // not needed anymore...
- this._feedBackNames = [];
- this._attributes = [];
-
- this.glPrimitive = null;
- this.offScreenPass = false;
- this._extensions = [];
- this.srcVert = getDefaultVertexShader();
- this.srcFrag = getDefaultFragmentShader();
- this.lastCompile = 0;
-
-
- this._libs = [];
- this._structNames = [];
- this._structUniformNames = [];
- this._textureStackUni = [];
- this._textureStackTex = [];
- this._textureStackType = [];
- this._textureStackTexCgl = [];
-
- this._tempNormalMatrix = mat4.create();
- this._tempCamPosMatrix = mat4.create();
- this._tempInverseViewMatrix = mat4.create();
- this._tempInverseProjMatrix = mat4.create();
-
- this.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_VERTEX_MODELVIEW"]);
- };
-
-
-
-
-
-
-
- isValid()
- {
- return this._isValid;
- };
-
- getCgl()
- {
- return this._cgl;
- };
-
- getName()
- {
- return this._name;
- };
-
- /**
- * enable an extension for the shader
- * @function enableExtension
- * @memberof Shader
- * @instance
- * @param name extension name
- */
- enableExtension(name)
- {
- this.setWhyCompile("enable extension " + name);
- this._needsRecompile = true;
- this._extensions.push(name);
- };
-
- getAttrVertexPos()
- {
- return this._attrVertexPos;
- };
-
- hasTextureUniforms()
- {
- for (let i = 0; i < this._uniforms.length; i++)
- if (this._uniforms[i].getType() == "t") return true;
- return false;
- };
-
- setWhyCompile(why)
- {
- this._compileReason = why;
- };
-
- /**
- * copy all uniform values from another shader
- * @function copyUniforms
- * @memberof Shader
- * @instance
- * @param origShader uniform values will be copied from this shader
- */
- copyUniformValues(origShader)
- {
- // console.log(origShader._uniforms);
- for (let i = 0; i < origShader._uniforms.length; i++)
- {
- if (!this._uniforms[i])
- {
- this._log.log("unknown uniform?!");
- continue;
- }
-
- // this._log.log(origShader._uniforms[i].getName());
- // this.getUniform(origShader._uniforms[i].)
- // this._uniforms[i].set(origShader._uniforms[i].getValue());
-
-
- // if (origShader._uniforms[i].getName().contains("pathPoints"))
- // console.log("copyUniformValues", origShader._uniforms[i].getName(), origShader._uniforms[i].getValue());
-
- this.getUniform(origShader._uniforms[i].getName()).set(origShader._uniforms[i].getValue());
- }
-
- this.popTextures();
- for (let i = 0; i < origShader._textureStackUni.length; i++)
- {
- this._textureStackUni[i] = origShader._textureStackUni[i];
- this._textureStackTex[i] = origShader._textureStackTex[i];
- this._textureStackType[i] = origShader._textureStackType[i];
- this._textureStackTexCgl[i] = origShader._textureStackTexCgl[i];
- }
-
- // this._textureStackUni = [];
- // this._textureStackTex = [];
- // this._textureStackType = [];
- // this._textureStackTexCgl = [];
- };
-
- /**
- * copy current shader
- * @function copy
- * @memberof Shader
- * @instance
- * @returns newShader
- */
- copy()
- {
- const shader = new Shader(this._cgl, this._name + " copy");
- shader.setSource(this.srcVert, this.srcFrag);
-
- shader._modules = JSON.parse(JSON.stringify(this._modules));
- shader._defines = JSON.parse(JSON.stringify(this._defines));
-
- shader._modGroupCount = this._modGroupCount;
- shader._moduleNames = this._moduleNames;
- shader.glPrimitive = this.glPrimitive;
- shader.offScreenPass = this.offScreenPass;
- shader._extensions = this._extensions;
- shader.wireframe = this.wireframe;
- shader._attributes = this._attributes;
-
- for (let i = 0; i < this._uniforms.length; i++)
- {
- const u = this._uniforms[i].copy(shader);
- u.resetLoc();
- }
-
- this.setWhyCompile("copy");
- shader._needsRecompile = true;
- return shader;
- };
-
-
- /**
- * set shader source code
- * @function setSource
- * @memberof Shader
- * @instance
- * @param {String} srcVert
- * @param {String} srcFrag
- * @param {Bool} fromUserInteraction
- */
- setSource(srcVert, srcFrag, fromUserInteraction)
- {
- this._fromUserInteraction = fromUserInteraction;
- this.srcVert = srcVert;
- this.srcFrag = srcFrag;
- this.setWhyCompile("Source changed");
- this._needsRecompile = true;
- this._isValid = true;
- };
-
- _addLibs(src)
- {
- for (const id in ShaderLibMods)
- {
- if (src.contains(id))
- {
- const lib = new ShaderLibMods[id]();
- src = src.replace("{{" + id + "}}", lib.srcHeadFrag);
- this._libs.push(lib);
- if (lib.initUniforms)lib.initUniforms(this);
- }
- }
-
- return src;
- };
-
- createStructUniforms()
- {
- // * create structs
- let structStrFrag = "";
- let structStrVert = ""; // TODO: not used yet
-
- this._structNames = [];
- // * reset the arrays holding the value each recompile so we don't skip structs
- // * key value mapping so the same struct can be added twice (two times the same modifier)
- this._injectedStringsFrag = {};
- this._injectedStringsVert = {};
-
- this._structUniformNamesIndicesFrag = [];
- this._structUniformNamesIndicesVert = [];
-
- for (let i = 0; i < this._uniforms.length; i++)
- {
- // * only add uniforms to struct that are a member of a struct
- if (this._uniforms[i].isStructMember())
- {
- const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[i]._structName + "}}";
-
- // * check if struct is not already part of shader
- if (!this._structNames.includes(this._uniforms[i]._structName))
- {
- // * create struct definition with placeholder string to inject
- const structDefinition = "struct "
- + this._uniforms[i]._structName + " {".endl()
- + injectionString
- + "};".endl().endl();
-
- if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "frag")
- structStrFrag = structStrFrag.concat(structDefinition);
-
- if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "vert")
- structStrVert = structStrVert.concat(structDefinition);
-
- this._structNames.push(this._uniforms[i]._structName);
- this._injectedStringsFrag[this._uniforms[i]._structName] = [];
- this._injectedStringsVert[this._uniforms[i]._structName] = [];
- }
-
- // * create member & comment
- let comment = "";
- if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;
-
- let stringToInsert = "";
- if (this._uniforms[i].getGlslTypeString() == undefined)stringToInsert += "//";
- stringToInsert += " " + this._uniforms[i].getGlslTypeString()
- + " " + this._uniforms[i]._propertyName + ";"
- + comment;
-
- if (this._uniforms[i].getShaderType() === "both")
- {
- // * inject member before {injectionString}
- if (
- !this._injectedStringsFrag[this._uniforms[i]._structName].contains(stringToInsert)
- && !this._injectedStringsVert[this._uniforms[i]._structName].contains(stringToInsert))
- {
- const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);
- const insertionIndexVert = structStrVert.lastIndexOf(injectionString);
-
- structStrFrag =
- structStrFrag.slice(0, insertionIndexFrag)
- + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);
-
- structStrVert =
- structStrVert.slice(0, insertionIndexVert)
- + stringToInsert + structStrVert.slice(insertionIndexVert - 1);
-
- this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
- this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
- }
-
- if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
- if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
- }
- else if (this._uniforms[i].getShaderType() === "frag")
- {
- // * inject member before {injectionString}
- if (!this._injectedStringsFrag[this._uniforms[i]._structName].includes(stringToInsert)) //
- {
- const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);
-
- structStrFrag =
- structStrFrag.slice(0, insertionIndexFrag)
- + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);
-
- this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
- }
-
- if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
- }
- else if (this._uniforms[i].getShaderType() === "vert")
- {
- // * inject member before {injectionString}
- if (!this._injectedStringsVert[this._uniforms[i]._structName].includes(stringToInsert))
- {
- const insertionIndexVert = structStrVert.lastIndexOf(injectionString);
-
- structStrVert =
- structStrVert.slice(0, insertionIndexVert)
- + stringToInsert + structStrVert.slice(insertionIndexVert - 1);
-
- this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
- }
-
- if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
- }
- }
- }
-
- // * dedupe injected uni declarations
- this._uniDeclarationsFrag = [];
- this._uniDeclarationsVert = [];
-
- // * remove struct injection points and add uniform in fragment
- for (let i = 0; i < this._structUniformNamesIndicesFrag.length; i += 1)
- {
- const index = this._structUniformNamesIndicesFrag[i];
- const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();
-
- if (!this._uniDeclarationsFrag.includes(uniDeclarationString))
- {
- const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";
-
- structStrFrag = structStrFrag.replace(injectionString, "");
- structStrFrag += uniDeclarationString;
-
- this._uniDeclarationsFrag.push(uniDeclarationString);
- }
- }
-
- // * remove struct injection points and add uniform in vertex
- for (let i = 0; i < this._structUniformNamesIndicesVert.length; i += 1)
- {
- const index = this._structUniformNamesIndicesVert[i];
- const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();
-
- if (!this._uniDeclarationsVert.includes(uniDeclarationString))
- {
- const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";
-
- structStrVert = structStrVert.replace(injectionString, "");
- structStrVert += uniDeclarationString;
- this._uniDeclarationsVert.push(uniDeclarationString);
- }
- }
-
- return [structStrVert, structStrFrag];
- };
-
- _getAttrSrc(attr, firstLevel)
- {
- const r = {};
- if (attr.name && attr.type)
- {
- r.srcHeadVert = "";
- if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.name.endl();
- r.srcHeadVert += "#define ATTRIB_" + attr.name.endl();
- r.srcHeadVert += "IN " + attr.type + " " + attr.name + ";".endl();
- if (!firstLevel) r.srcHeadVert += "#endif".endl();
-
- if (attr.nameFrag)
- {
- r.srcHeadVert += "";
- if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.nameFrag.endl();
- r.srcHeadVert += "#define ATTRIB_" + attr.nameFrag.endl();
- r.srcHeadVert += "OUT " + attr.type + " " + attr.nameFrag + ";".endl();
- if (!firstLevel) r.srcHeadVert += "#endif".endl();
-
- r.srcVert = "".endl() + attr.nameFrag + "=" + attr.name + ";";
-
- r.srcHeadFrag = "";
- if (!firstLevel) r.srcHeadFrag += "#ifndef ATTRIB_" + attr.nameFrag.endl();
- r.srcHeadFrag += "#define ATTRIB_" + attr.nameFrag.endl();
- r.srcHeadFrag += "IN " + attr.type + " " + attr.nameFrag + ";".endl();
- if (!firstLevel) r.srcHeadFrag += "#endif".endl();
- }
- }
- return r;
- };
-
- compile()
- {
- if (this._cgl.aborted) return;
- const startTime = performance.now();
-
-
-
- this._cgl.profileData.profileShaderCompiles++;
- this._cgl.profileData.profileShaderCompileName = this._name + " [" + this._compileReason + "]";
-
- let extensionString = "";
- if (this._extensions)
- for (let i = 0; i < this._extensions.length; i++)
- extensionString += "#extension " + this._extensions[i] + " : enable".endl();
-
- let definesStr = "";
- if (this._defines.length) definesStr = "\n// cgl generated".endl();
- for (let i = 0; i < this._defines.length; i++)
- definesStr += "#define " + this._defines[i][0] + " " + this._defines[i][1] + "".endl();
-
- const structStrings = this.createStructUniforms();
- this._cgl.profileData.addHeavyEvent("shader compile", this._name + " [" + this._compileReason + "]");
- this._compileReason = "";
-
-
-
- if (this._uniforms)
- {
- // * we create an array of the uniform names to check our indices & an array to save them
- const uniNames = this._uniforms.map((uni) => { return uni._name; });
- const indicesToRemove = [];
-
- // * we go through our uniforms and check if the same name is contained somewhere further in the array
- // * if so, we add the current index to be removed later
- for (let i = 0; i < this._uniforms.length; i++)
- {
- const uni = this._uniforms[i];
- const nextIndex = uniNames.indexOf(uni._name, i + 1);
- if (nextIndex > -1) indicesToRemove.push(i);
- }
-
- // * after that, we go through the uniforms backwards (so we keep the order) and remove the indices
- // * also, we reset the locations of all the other valid uniforms
- for (let j = this._uniforms.length - 1; j >= 0; j -= 1)
- {
- if (indicesToRemove.includes(j)) this._uniforms.splice(j, 1);
- else this._uniforms[j].resetLoc();
- }
- }
-
- this._cgl.printError("uniform resets");
-
- if (this.hasTextureUniforms()) definesStr += "#define HAS_TEXTURES".endl();
-
- let vs = "";
- let fs = "";
-
- if (!this.srcFrag)
- {
- this._log.warn("[cgl shader] has no fragment source!", this._name, this);
- this.srcVert = getDefaultVertexShader();
- this.srcFrag = getDefaultFragmentShader();
- // return;
- }
-
- if (this.glslVersion == 300)
- {
- vs = "#version 300 es"
- .endl() + "// "
- .endl() + "// vertex shader " + this._name
- .endl() + "// "
- .endl() + "precision " + this.precision + " float;"
- .endl() + "precision " + this.precision + " sampler2D;"
- .endl() + ""
- .endl() + "#define WEBGL2"
- .endl() + "#define texture2D texture"
- .endl() + "#define UNI uniform"
- .endl() + "#define IN in"
- .endl() + "#define OUT out"
- .endl();
-
- fs = "#version 300 es"
- .endl() + "// "
- .endl() + "// fragment shader " + this._name
- .endl() + "// "
- .endl() + "precision " + this.precision + " float;"
- .endl() + "precision " + this.precision + " sampler2D;"
- .endl() + ""
- .endl() + "#define WEBGL2"
- .endl() + "#define texture2D texture"
- .endl() + "#define IN in"
- .endl() + "#define OUT out"
- .endl() + "#define UNI uniform"
- .endl() + "{{DRAWBUFFER}}"
-
- .endl();
- }
- else
- {
- fs = ""
- .endl() + "// "
- .endl() + "// fragment shader " + this._name
- .endl() + "// "
- .endl() + "#define WEBGL1"
- .endl() + "#define texture texture2D"
- .endl() + "#define outColor gl_FragColor"
- .endl() + "#define IN varying"
- .endl() + "#define UNI uniform"
- .endl();
-
- vs = ""
- .endl() + "// "
- .endl() + "// vertex shader " + this._name
- .endl() + "// "
- .endl() + "#define WEBGL1"
- .endl() + "#define texture texture2D"
- .endl() + "#define OUT varying"
- .endl() + "#define IN attribute"
- .endl() + "#define UNI uniform"
- .endl();
- }
-
- let uniformsStrVert = "\n// cgl generated".endl();
- let uniformsStrFrag = "\n// cgl generated".endl();
-
-
- fs += "\n// active mods: --------------- ";
- vs += "\n// active mods: --------------- ";
-
- let foundModsFrag = false;
- let foundModsVert = false;
- for (let i = 0; i < this._moduleNames.length; i++)
- {
- for (let j = 0; j < this._modules.length; j++)
- {
- if (this._modules[j].name == this._moduleNames[i])
- {
- if (this._modules[j].srcBodyFrag || this._modules[j].srcHeadFrag)
- {
- foundModsFrag = true;
- fs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
- }
- if (this._modules[j].srcBodyVert || this._modules[j].srcHeadVert)
- {
- vs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
- foundModsVert = true;
- }
- }
- }
- }
- if (!foundModsVert)fs += "\n// no mods used...";
- if (!foundModsFrag)fs += "\n// no mods used...";
- fs += "\n";
- vs += "\n";
-
- for (let i = 0; i < this._uniforms.length; i++)
- {
- if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
- {
- let uniStr = "";
- if (!this._uniforms[i].getGlslTypeString())uniStr += "// ";
- uniStr += "UNI " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName();
- let comment = "";
- if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;
-
- if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both")
- if (!this.srcVert.contains(uniStr) && !this.srcVert.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
- uniformsStrVert += uniStr + ";" + comment.endl();
-
- if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both")
- if (!this.srcFrag.contains(uniStr) && !this.srcFrag.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
- uniformsStrFrag += uniStr + ";" + comment.endl();
- }
- }
-
-
- let countUniFrag = 0;
- let countUniVert = 0;
- for (let i = 0; i < this._uniforms.length; i++)
- {
- if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
- {
- if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both") countUniVert++;
- if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both") countUniFrag++;
- }
- }
- if (countUniFrag >= this._cgl.maxUniformsFrag) this._log.warn("[cgl_shader] num uniforms frag: " + countUniFrag + " / " + this._cgl.maxUniformsFrag);
- if (countUniVert >= this._cgl.maxUniformsVert) this._log.warn("[cgl_shader] num uniforms vert: " + countUniVert + " / " + this._cgl.maxUniformsVert);
-
-
- if (!fs.contains("precision")) fs = "precision " + this.precision + " float;".endl() + fs;
- if (!vs.contains("precision")) vs = "precision " + this.precision + " float;".endl() + vs;
- if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
- {
- fs += "#define MOBILE".endl();
- vs += "#define MOBILE".endl();
- }
- vs = extensionString + vs + definesStr + structStrings[0] + uniformsStrVert + "\n// -- \n" + this.srcVert;
- fs = extensionString + fs + definesStr + structStrings[1] + uniformsStrFrag + "\n// -- \n" + this.srcFrag;
-
-
- let srcHeadVert = "";
- let srcHeadFrag = "";
-
- // testing if this breaks things...
- // this._modules.sort(function (a, b)
- // {
- // return a.group - b.group;
- // });
-
- this._modules.sort(function (a, b)
- {
- return a.priority || 0 - b.priority || 0;
- });
-
-
- let addedAttribs = false;
-
- for (let i = 0; i < this._moduleNames.length; i++)
- {
- let srcVert = "";
- let srcFrag = "";
-
- if (!addedAttribs)
- {
- addedAttribs = true;
-
- for (let k = 0; k < this._attributes.length; k++)
- {
- const r = this._getAttrSrc(this._attributes[k], true);
- if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
- if (r.srcVert)srcVert += r.srcVert;
- if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
- }
- }
-
- for (let j = 0; j < this._modules.length; j++)
- {
- const mod = this._modules[j];
- if (mod.name == this._moduleNames[i])
- {
- srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
- srcHeadFrag += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
-
- srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
- srcFrag += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
-
- if (mod.attributes)
- for (let k = 0; k < mod.attributes.length; k++)
- {
- const r = this._getAttrSrc(mod.attributes[k], false);
- if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
- if (r.srcVert)srcVert += r.srcVert;
- if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
- }
-
- srcHeadVert += mod.srcHeadVert || "";
- srcHeadFrag += mod.srcHeadFrag || "";
- srcVert += mod.srcBodyVert || "";
- srcFrag += mod.srcBodyFrag || "";
-
- srcHeadVert += "\n//---- end mod ------\n";
- srcHeadFrag += "\n//---- end mod ------\n";
-
- srcVert += "\n//---- end mod ------\n";
- srcFrag += "\n//---- end mod ------\n";
-
- srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
- srcFrag = srcFrag.replace(/{{mod}}/g, mod.prefix);
- srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);
- srcHeadFrag = srcHeadFrag.replace(/{{mod}}/g, mod.prefix);
-
- srcVert = srcVert.replace(/MOD_/g, mod.prefix);
- srcFrag = srcFrag.replace(/MOD_/g, mod.prefix);
- srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
- srcHeadFrag = srcHeadFrag.replace(/MOD_/g, mod.prefix);
- }
- }
-
-
- vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
- fs = fs.replace("{{" + this._moduleNames[i] + "}}", srcFrag);
- }
-
-
- vs = vs.replace("{{MODULES_HEAD}}", srcHeadVert);
- fs = fs.replace("{{MODULES_HEAD}}", srcHeadFrag);
-
-
- vs = this._addLibs(vs);
- fs = this._addLibs(fs);
-
-
- // SETUP draw buffers / multi texture render targets
-
- let drawBufferStr = "";
- for (let i = 0; i < 16; i++)
- if (fs.contains("outColor" + i)) this._drawBuffers[i] = true;
-
- if (this._drawBuffers.length == 1)
- {
- drawBufferStr = "out vec4 outColor;".endl();
- drawBufferStr += "#define gl_FragColor outColor".endl();
- }
- else
- {
- drawBufferStr += "#define MULTI_COLORTARGETS".endl();
- drawBufferStr += "vec4 outColor;".endl();
-
- let count = 0;
- for (let i = 0; i < this._drawBuffers.length; i++)
- {
- if (count == 0) drawBufferStr += "#define gl_FragColor outColor" + i + "".endl();
- drawBufferStr += "layout(location = " + i + ") out vec4 outColor" + i + ";".endl();
- count++;
- }
- }
-
- fs = fs.replace("{{DRAWBUFFER}}", drawBufferStr);
- // //////
-
-
- if (!this._program)
- {
- this._program = this._createProgram(vs, fs);
- }
- else
- {
- // this.vshader=createShader(vs, gl.VERTEX_SHADER, this.vshader );
- // this.fshader=createShader(fs, gl.FRAGMENT_SHADER, this.fshader );
- // linkProgram(program);
- this._program = this._createProgram(vs, fs);
-
- this._projMatrixUniform = null;
-
- for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].resetLoc();
- }
-
- this.finalShaderFrag = fs;
- this.finalShaderVert = vs;
-
-
- MESH.lastMesh = null;
- MESH.lastShader = null;
-
- this._countMissingUniforms = 0;
- this._needsRecompile = false;
- this.lastCompile = now();
-
- // this._cgl.printError("shader compile");
-
- this._cgl.profileData.shaderCompileTime += performance.now() - startTime;
- };
-
- hasChanged()
- {
- return this._needsRecompile;
- }
-
-
- bind()
- {
- if (!this._isValid || this._cgl.aborted) return;
-
- MESH.lastShader = this;
-
- if (!this._program || this._needsRecompile) this.compile();
- if (!this._isValid) return;
-
- if (!this._projMatrixUniform && !this.ignoreMissingUniforms)
- {
- this._countMissingUniforms++;
- // if (this._countMissingUniforms == 10)console.log("stopping getlocation of missing uniforms...", this._name);
- if (this._countMissingUniforms < 10)
- {
- this._projMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_PROJMAT);
- this._attrVertexPos = this._cgl.glGetAttribLocation(this._program, CONSTANTS.SHADER.SHADERVAR_VERTEX_POSITION);
- this._mvMatrixUniform = this._cgl.gl.getUniformLocation(this._program, "mvMatrix");
- this._vMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_VIEWMAT);
- this._mMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_MODELMAT);
- this._camPosUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_VIEWPOS);
- this._normalMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_NORMALMAT);
- this._inverseViewMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_INVVIEWMAT);
- this._inverseProjMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_INVPROJMAT);
- this._materialIdUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_MATERIALID);
- this._objectIdUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_OBJECTID);
-
- for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].needsUpdate = true;
- }
- }
-
-
- if (this._cgl.currentProgram != this._program)
- {
- this._cgl.profileData.profileShaderBinds++;
- this._cgl.gl.useProgram(this._program);
- this._cgl.currentProgram = this._program;
- }
-
- for (let i = 0; i < this._uniforms.length; i++)
- if (this._uniforms[i].needsUpdate) this._uniforms[i].updateValue();
-
- if (this._pMatrixState != this._cgl.getProjectionMatrixStateCount())
- {
- this._pMatrixState = this._cgl.getProjectionMatrixStateCount();
- this._cgl.gl.uniformMatrix4fv(this._projMatrixUniform, false, this._cgl.pMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
-
- if (this._objectIdUniform)
- this._cgl.gl.uniform1f(this._objectIdUniform, ++this._cgl.tempData.objectIdCounter);
-
- if (this._materialIdUniform)
- this._cgl.gl.uniform1f(this._materialIdUniform, this._materialId);
-
- if (this._vMatrixUniform)
- {
- if (this._vMatrixState != this._cgl.getViewMatrixStateCount())
- {
- this._cgl.gl.uniformMatrix4fv(this._vMatrixUniform, false, this._cgl.vMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
- this._vMatrixState = this._cgl.getViewMatrixStateCount();
-
- if (this._inverseViewMatrixUniform)
- {
- mat4.invert(this._tempInverseViewMatrix, this._cgl.vMatrix);
- this._cgl.gl.uniformMatrix4fv(this._inverseViewMatrixUniform, false, this._tempInverseViewMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
- if (this._inverseProjMatrixUniform)
- {
- mat4.invert(this._tempInverseProjMatrix, this._cgl.pMatrix);
- this._cgl.gl.uniformMatrix4fv(this._inverseProjMatrixUniform, false, this._tempInverseProjMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
- }
- this._cgl.gl.uniformMatrix4fv(this._mMatrixUniform, false, this._cgl.mMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
-
- if (this._camPosUniform)
- {
- mat4.invert(this._tempCamPosMatrix, this._cgl.vMatrix);
- this._cgl.gl.uniform3f(this._camPosUniform, this._tempCamPosMatrix[12], this._tempCamPosMatrix[13], this._tempCamPosMatrix[14]);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
- }
- else
- {
- // mvmatrix deprecated....
- const tempmv = mat4.create();
-
- mat4.mul(tempmv, this._cgl.vMatrix, this._cgl.mMatrix);
- this._cgl.gl.uniformMatrix4fv(this._mvMatrixUniform, false, tempmv);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
-
- if (this._normalMatrixUniform)
- {
- // mat4.mul(this._tempNormalMatrix, this._cgl.vMatrix, this._cgl.mMatrix);
- mat4.invert(this._tempNormalMatrix, this._cgl.mMatrix);
- mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);
-
- this._cgl.gl.uniformMatrix4fv(this._normalMatrixUniform, false, this._tempNormalMatrix);
- this._cgl.profileData.profileMVPMatrixCount++;
- }
-
- for (let i = 0; i < this._libs.length; i++)
- {
- if (this._libs[i].onBind) this._libs[i].onBind.bind(this._libs[i])(this._cgl, this);
- }
-
- this._bindTextures();
-
- return this._isValid;
- };
-
- unBind()
- {
- };
-
-
- dispose()
- {
- this._cgl.gl.deleteProgram(this._program);
- };
-
- needsRecompile()
- {
- return this._needsRecompile;
- };
-
- setDrawBuffers(arr)
- {
- console.log("useless drawbuffers...?!");
- // if (this._drawBuffers.length !== arr.length)
- // {
- // this._drawBuffers = arr;
- // this._needsRecompile = true;
- // this.setWhyCompile("setDrawBuffers");
- // return;
- // }
- // for (let i = 0; i < arr.length; i++)
- // {
- // if (arr[i] !== this._drawBuffers[i])
- // {
- // this._drawBuffers = arr;
- // this._needsRecompile = true;
- // this.setWhyCompile("setDrawBuffers");
- // return;
- // }
- // }
- };
-
- getUniforms()
- {
- return this._uniforms;
- };
-
- getUniform(name)
- {
- for (let i = 0; i < this._uniforms.length; i++)
- if (this._uniforms[i].getName() == name)
- return this._uniforms[i];
- return null;
- };
-
- removeAllUniforms()
- {
- this._uniforms = [];
- // for (let i = 0; i < this._uniforms.length; i++)
- // this.removeUniform(this._uniforms[i].name);
- };
-
- removeUniform(name)
- {
- for (let i = 0; i < this._uniforms.length; i++)
- {
- if (this._uniforms[i].getName() == name)
- {
- this._uniforms.splice(i, 1);
- }
- }
- this._needsRecompile = true;
- this.setWhyCompile("remove uniform " + name);
- };
-
-
- _addUniform(uni)
- {
- this._uniforms.push(uni);
- this.setWhyCompile("add uniform " + name);
- this._needsRecompile = true;
- };
-
- /**
- * add a uniform to the fragment shader
- * @param {String} type ['f','t', etc]
- * @param {String} name
- * @param {any} valueOrPort value or port
- * @param p2
- * @param p3
- * @param p4
- * @memberof Shader
- * @instance
- * @function addUniformFrag
- * @returns {CGL.Uniform}
- */
- addUniformFrag(type, name, valueOrPort, p2, p3, p4)
- {
- const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
- uni.shaderType = "frag";
- return uni;
- };
-
- /**
- * add a uniform to the vertex shader
- * @param {String} type ['f','t', etc]
- * @param {String} name
- * @param {any} valueOrPort value or port
- * @param p2
- * @param p3
- * @param p4
- * @memberof Shader
- * @instance
- * @function addUniformVert
- * @returns {CGL.Uniform}
- */
- addUniformVert(type, name, valueOrPort, p2, p3, p4)
- {
- const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
- uni.shaderType = "vert";
- return uni;
- };
- /**
- * add a uniform to both shaders
- * @param {String} type ['f','t', etc]
- * @param {String} name
- * @param {any} valueOrPort value or port
- * @param p2
- * @param p3
- * @param p4
- * @memberof Shader
- * @instance
- * @function addUniformBoth
- * @returns {CGL.Uniform}
- */
- addUniformBoth(type, name, valueOrPort, p2, p3, p4)
- {
- const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
- uni.shaderType = "both";
- return uni;
- };
-
- /**
- * add a struct & its uniforms to the fragment shader
- * @param {String} structName name of the struct, i.e.: LightStruct
- * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
- * @param {Array} members array of objects containing the struct members. see example for structure
-
- * @memberof Shader
- * @instance
- * @function addUniformStructFrag
- * @returns {Object}
- * @example
- * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
- * shader.setSource(attachments.shader_vert, attachments.shader_frag);
- * shader.addUniformStructFrag("Light", "uniformLight", [
- * { "type": "3f", "name": "position", "v1": null },
- * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
- * ]);
- */
- addUniformStructFrag(structName, uniformName, members)
- {
- const uniforms = {};
-
- if (!members) return uniforms;
-
- for (let i = 0; i < members.length; i += 1)
- {
- const member = members[i];
- if (!this.hasUniform(uniformName + "." + member.name))
- {
- const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
- uni.shaderType = "frag";
- uniforms[uniformName + "." + member.name] = uni;
- }
- }
-
- return uniforms;
- };
-
- /**
- * add a struct & its uniforms to the vertex shader
- * @param {String} structName name of the struct, i.e.: LightStruct
- * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
- * @param {Array} members array of objects containing the struct members. see example for structure
-
- * @memberof Shader
- * @instance
- * @function addUniformStructVert
- * @returns {CGL.Uniform}
- * @example
- * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
- * shader.setSource(attachments.shader_vert, attachments.shader_frag);
- * shader.addUniformStructVert("Light", "uniformLight", [
- * { "type": "3f", "name": "position", "v1": null },
- * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
- * ]);
- */
- addUniformStructVert(structName, uniformName, members)
- {
- const uniforms = {};
-
- if (!members) return uniforms;
-
- for (let i = 0; i < members.length; i += 1)
- {
- const member = members[i];
- if (!this.hasUniform(uniformName + "." + member.name))
- {
- const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
- uni.shaderType = "vert";
- uniforms[uniformName + "." + member.name] = uni;
- }
- }
-
- return uniforms;
- };
-
- /**
- * add a struct & its uniforms to the both shaders. PLEASE NOTE: it is not possible to add the same struct to both shaders when it contains ANY integer members.
- * @param {String} structName name of the struct, i.e.: LightStruct
- * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
- * @param {Array} members array of objects containing the struct members. see example for structure
-
- * @memberof Shader
- * @instance
- * @function addUniformStructBoth
- * @returns {Object}
- * @example
- * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
- * shader.setSource(attachments.shader_vert, attachments.shader_frag);
- * shader.addUniformStructBoth("Light", "uniformLight", [
- * { "type": "3f", "name": "position", "v1": null },
- * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
- * ]);
- */
- addUniformStructBoth(structName, uniformName, members)
- {
- const uniforms = {};
-
- if (!members) return uniforms;
-
- for (let i = 0; i < members.length; i += 1)
- {
- const member = members[i];
- if ((member.type === "2i" || member.type === "i" || member.type === "3i"))
- this._log.error("Adding an integer struct member to both shaders can potentially error. Please use different structs for each shader. Error occured in struct:", structName, " with member:", member.name, " of type:", member.type, ".");
- if (!this.hasUniform(uniformName + "." + member.name))
- {
- const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
- uni.shaderType = "both";
- uniforms[uniformName + "." + member.name] = uni;
- }
- }
-
- return uniforms;
- };
-
- hasUniform(name)
- {
- for (let i = 0; i < this._uniforms.length; i++)
- {
- if (this._uniforms[i].getName() == name) return true;
- }
- return false;
- };
-
- _createProgram(vstr, fstr)
- {
- this._cgl.printError("before _createprogram");
-
- const program = this._cgl.gl.createProgram();
-
- this.vshader = Shader.createShader(this._cgl, vstr, this._cgl.gl.VERTEX_SHADER, this);
- this.fshader = Shader.createShader(this._cgl, fstr, this._cgl.gl.FRAGMENT_SHADER, this);
-
-
- if (this.vshader && this.fshader)
- {
- this._cgl.gl.attachShader(program, this.vshader);
- this._cgl.gl.attachShader(program, this.fshader);
-
- this._linkProgram(program, vstr, fstr);
- }
- else
- {
- this._isValid = false;
- this._cgl.printError("shader _createProgram");
- this._log.error("could not link shaderprogram");
- return null;
- }
-
- this._cgl.printError("shader _createProgram");
- return program;
- };
-
- hasErrors()
- {
- return this._hasErrors;
- };
-
- _linkProgram(program, vstr, fstr)
- {
- this._cgl.printError("before _linkprogram");
-
- if (this._feedBackNames.length > 0)
- {
- this._cgl.gl.transformFeedbackVaryings(program, this._feedBackNames, this._cgl.gl.SEPARATE_ATTRIBS);
- // INTERLEAVED_ATTRIBS
- // SEPARATE_ATTRIBS
- }
-
- this._cgl.gl.linkProgram(program);
- this._cgl.printError("gl.linkprogram");
- this._isValid = true;
-
- this._hasErrors = false;
-
- if (this._cgl.patch.config.glValidateShader !== false)
- {
- this._cgl.gl.validateProgram(program);
-
- if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.VALIDATE_STATUS))
- {
- // validation failed
- console.log("shaderprogram validation failed...");
- console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
- }
-
- if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.LINK_STATUS))
- {
- this._hasErrors = true;
-
- const infoLogFrag = this._cgl.gl.getShaderInfoLog(this.fshader);
- const infoLogVert = this._cgl.gl.getShaderInfoLog(this.vshader);
-
- if (infoLogFrag) this._log.warn(this._cgl.gl.getShaderInfoLog(this.fshader));
- if (infoLogVert) this._log.warn(this._cgl.gl.getShaderInfoLog(this.vshader));
-
- this._log.error(this._name + " shader linking fail...");
-
- console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
- console.log(this);
- this._isValid = false;
-
- this._name = "errorshader";
- this.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
- this._cgl.printError("shader link err");
- }
- }
- };
-
- getProgram()
- {
- return this._program;
- };
-
- setFeedbackNames(names)
- {
- this.setWhyCompile("setFeedbackNames");
- this._needsRecompile = true;
- this._feedBackNames = names;
- };
-
- // getDefaultVertexShader()
- // {
- // return defaultShaderSrcVert;
- // }
-
- // getDefaultFragmentShader()
- // {
- // return this.getDefaultFragmentShader()
- // }
-
-
- /**
- * adds attribute definition to shader header without colliding with other shader modules...
- * when attrFrag is defined, vertex shader will output this attribute to the fragment shader
- * @function
- * @memberof Shader
- * @instance
- * @param {Object} attr {type:x,name:x,[nameFrag:x]}
- * @return {Object}
- */
- addAttribute = function (attr)
- {
- for (let i = 0; i < this._attributes.length; i++)
- {
- if (this._attributes[i].name == attr.name && this._attributes[i].nameFrag == attr.nameFrag) return;
- }
- this._attributes.push(attr);
- this._needsRecompile = true;
- this.setWhyCompile("addAttribute");
- };
-
- bindTextures()
- {
- this._bindTextures();
- }
- _bindTextures()
- {
- if (this._textureStackTex.length > this._cgl.maxTextureUnits)
- {
- this._log.warn("[shader._bindTextures] too many textures bound", this._textureStackTex.length + "/" + this._cgl.maxTextureUnits);
- }
-
- // for (let i = this._textureStackTex.length + 1; i < this._cgl.maxTextureUnits; i++) this._cgl.setTexture(i, null);
-
- for (let i = 0; i < this._textureStackTex.length; i++)
- {
- // console.log(this._textureStackTex.length, i);
- if (!this._textureStackTex[i] && !this._textureStackTexCgl[i])
- {
- this._log.warn("no texture for pushtexture", this._name);
- }
- else
- {
- let t = this._textureStackTex[i];
- if (this._textureStackTexCgl[i])
- {
- t = this._textureStackTexCgl[i].tex || CGL.Texture.getEmptyTexture(this._cgl).tex;
- }
-
- let bindOk = true;
-
- if (!this._textureStackUni[i])
- {
- // throw(new Error('no uniform given to texturestack'));
- this._log.warn("no uniform for pushtexture", this._name);
- bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);
- }
- else
- {
- this._textureStackUni[i].setValue(i);
- bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);
-
- // console.log(bindOk, i, t, this._textureStackType[i]);
- }
- if (!bindOk) console.warn("tex bind failed", this.getName(), this._textureStackUni[i]);
- }
- }
- };
-
- setUniformTexture = function (uni, tex)
- {
- tex = tex || CGL.Texture.getTempTexture(this._cgl);
- for (let i = 0; i < this._textureStackUni.length; i++)
- if (this._textureStackUni[i] == uni)
- {
- const old = this._textureStackTex[i] || this._textureStackTexCgl[i];
- if (tex.hasOwnProperty("tex"))
- {
- this._textureStackTexCgl[i] = tex;
- this._textureStackTex[i] = null;
- }
- else
- {
- this._textureStackTexCgl[i] = null;
- this._textureStackTex[i] = tex;
- }
-
- // this._textureStackTex[i] = tex;
- // this._cgl.setTexture(i, tex, this._textureStackType[i]);
- return old;
- }
- return null;
- };
-
- /**
- * push a texture on the stack. those textures will be bound when binding the shader. texture slots are automatically set
- * @param {uniform} uniform texture uniform
- * @param {texture} t texture
- * @param {type} type texture type, can be ignored when TEXTURE_2D
- * @function pushTexture
- * @memberof Shader
- * @instance
- */
- pushTexture = function (uniform, t, type)
- {
- if (!uniform)
- {
- // console.log("pushtexture: no uniform given to texturestack", "shader:"+this._name,uniform,t,type);
- return;
- }
- if (!t)
- {
- // if(uniform)this._log.warn("pushtexture: no tex","shader:"+this._name," uniform:"+uniform.name);
- return;
- }
- if (!t.hasOwnProperty("tex") && !(t instanceof WebGLTexture))
- {
- this._log.warn(new Error("invalid texture").stack);
-
- this._log.warn("[cgl_shader] invalid texture...", t);
- return;
- }
-
- this._textureStackUni.push(uniform);
-
- if (t.hasOwnProperty("tex"))
- {
- this._textureStackTexCgl.push(t);
- this._textureStackTex.push(null);
- }
- else
- {
- this._textureStackTexCgl.push(null);
- this._textureStackTex.push(t);
- }
-
- this._textureStackType.push(type);
- };
-
- /**
- * pop last texture
- * @function popTexture
- * @memberof Shader
- * @instance
- */
- popTexture = function ()
- {
- this._textureStackUni.pop();
- this._textureStackTex.pop();
- this._textureStackTexCgl.pop();
- this._textureStackType.pop();
- };
-
- /**
- * pop all textures
- * @function popTextures
- * @memberof Shader
- * @instance
- */
- popTextures = function ()
- {
- this._textureStackTex.length =
- this._textureStackTexCgl.length =
- this._textureStackType.length =
- this._textureStackUni.length = 0;
- };
-
- getMaterialId()
- {
- return this._materialId;
- };
-
- getInfo()
- {
- const info = {};
- info.name = this._name;
- // info.modules = JSON.parse(JSON.stringify(this._modules));
- // info.defines = JSON.parse(JSON.stringify(this._defines));
- info.defines = this.getDefines();
- info.hasErrors = this.hasErrors();
-
- return info;
- };
-
-
- getDefaultFragmentShader=function(r,g,b,a)
- {
- return getDefaultFragmentShader(r,g,b,a);
- }
-
- getDefaultVertexShader=function()
- {
- return getDefaultVertexShader();
- }
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- // --------------------------
-
- Shader.getDefaultVertexShader=getDefaultVertexShader;
- Shader.getDefaultFragmentShader=getDefaultFragmentShader;
-
-
- Shader.getErrorFragmentShader = function ()
- {
- return ""
- .endl() + "void main()"
- .endl() + "{"
- .endl() + " float g=mod((gl_FragCoord.y+gl_FragCoord.x),50.0)/50.0;"
- .endl() + " g= step(0.1,g);"
- .endl() + " outColor = vec4( g+0.5, 0.0, 0.0, 1.0);"
- .endl() + "}";
- };
-
- Shader.createShader = function (cgl, str, type, cglShader)
- {
- if (cgl.aborted) return;
-
- // cgl.printError("[Shader.createShader] ", cglShader._name);
-
- function getBadLines(infoLog)
- {
- const basLines = [];
- const lines = infoLog.split("\n");
- for (const i in lines)
- {
- const divide = lines[i].split(":");
- if (parseInt(divide[2], 10)) basLines.push(parseInt(divide[2], 10));
- }
- return basLines;
- }
-
-
- const shader = cgl.gl.createShader(type);
- cgl.gl.shaderSource(shader, str);
- cgl.gl.compileShader(shader);
-
- if (!cgl.gl.getShaderParameter(shader, cgl.gl.COMPILE_STATUS))
- {
- let infoLog = cgl.gl.getShaderInfoLog(shader);
- if (!infoLog)
- {
- console.warn("empty shader info log", this._name);
- return;
- }
-
-
- const badLines = getBadLines(infoLog);
- let htmlWarning = "<pre style=\"margin-bottom:0px;\"><code class=\"shaderErrorCode language-glsl\" style=\"padding-bottom:0px;max-height: initial;max-width: initial;\">";
- const lines = str.match(/^.*((\r\n|\n|\r)|$)/gm);
-
- if (!cgl.aborted && infoLog)
- {
- if (type == cgl.gl.VERTEX_SHADER) console.log("VERTEX_SHADER");
- if (type == cgl.gl.FRAGMENT_SHADER) console.log("FRAGMENT_SHADER");
-
- for (const i in lines)
- {
- const j = parseInt(i, 10) + 1;
- const line = j + ": " + lines[i];
-
- let isBadLine = false;
- for (const bj in badLines)
- if (badLines[bj] == j) isBadLine = true;
-
- if (isBadLine)
- {
- htmlWarning += "</code></pre>";
- htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\"background-color:#660000;padding-top:0px;padding-bottom:0px\">";
-
- cglShader._log.log("bad line: `" + line + "`");
- }
- htmlWarning += escapeHTML(line);
-
- if (isBadLine)
- {
- htmlWarning += "</code></pre>";
- htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\";padding-top:0px;padding-bottom:0px\">";
- }
- }
- }
-
- infoLog = infoLog.replace(/\n/g, "<br/>");
- if (cgl.patch.isEditorMode())console.log("Shader error ", cglShader._name, infoLog, this);
-
- htmlWarning = infoLog + "<br/>" + htmlWarning + "<br/><br/>";
- htmlWarning += "</code></pre>";
-
- if (this._fromUserInteraction)
- {
- // console.log("todo show modal?");
- // cgl.patch.emitEvent("criticalError", { "title": "Shader error " + cglShader._name, "text": htmlWarning, "exception": { "message": infoLog } });
- }
-
- cglShader.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
- }
- else
- {
- // console.log(name+' shader compiled...');
- }
- // cgl.printError("shader create2");
- return shader;
- };
-
-
- export { Shader };
-
-
-
-
-
-
-
-
-