"use strict"; // Common code for GLSL-based shader languages var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var types_1 = require("./types"); var intrinsics_1 = require("./intrinsics"); var stardust_core_1 = require("stardust-core"); var LinesGenerator = /** @class */ (function () { function LinesGenerator() { this._lines = []; this._currentIndent = ""; this._blocks = new stardust_core_1.Dictionary(); } LinesGenerator.prototype.addNamedBlock = function (name, code) { if (this._blocks.has(name)) { this._blocks.set(name, this._blocks.get(name) + "\n" + code); } else { this._blocks.set(name, code); } }; LinesGenerator.prototype.addLine = function (code) { this._lines.push(this._currentIndent + code); }; LinesGenerator.prototype.indent = function () { this._currentIndent += " "; }; LinesGenerator.prototype.unindent = function () { this._currentIndent = this._currentIndent.slice(0, this._currentIndent.length - 4); }; LinesGenerator.prototype.getCode = function () { var _this = this; return this._lines.map(function (line) { if (line[0] == "@" && _this._blocks.has(line.substr(1))) { return _this._blocks.get(line.substr(1)); } else { return line; } }).join("\n"); }; return LinesGenerator; }()); exports.LinesGenerator = LinesGenerator; // The basic GLSL generator var ShaderGenerator = /** @class */ (function (_super) { __extends(ShaderGenerator, _super); function ShaderGenerator() { return _super.call(this) || this; } ShaderGenerator.prototype.addAdditionalCode = function (code) { this.addNamedBlock("additionalCode", code); }; ShaderGenerator.prototype.addDeclaration = function (name, type, modifier) { if (modifier === void 0) { modifier = null; } if (modifier == null) { this.addLine(types_1.convertTypeName(type) + " " + name + ";"); } else { this.addLine(modifier + " " + types_1.convertTypeName(type) + " " + name + ";"); } }; ShaderGenerator.prototype.addArrayDeclaration = function (name, type, count, modifier) { if (count === void 0) { count = 1; } if (modifier === void 0) { modifier = null; } if (modifier == "null") { this.addLine(types_1.convertTypeName(type) + "[" + count + "] " + name + ";"); } else { this.addLine(modifier + " " + types_1.convertTypeName(type) + "[" + count + "] " + name + ";"); } }; ShaderGenerator.prototype.addUniform = function (name, type) { this.addLine("uniform " + types_1.convertTypeName(type) + " " + name + ";"); if (type == "Vector2Array" || type == "FloatArray" || type == "Vector3Array" || type == "Vector4Array") { this.addLine("uniform int " + name + "_length;"); } }; ShaderGenerator.prototype.addAttribute = function (name, type) { this.addLine("attribute " + types_1.convertTypeName(type) + " " + name + ";"); }; ShaderGenerator.prototype.addVarying = function (name, type) { this.addLine("varying " + types_1.convertTypeName(type) + " " + name + ";"); }; ShaderGenerator.prototype.addIn = function (name, type) { this.addLine("in " + types_1.convertTypeName(type) + " " + name + ";"); }; ShaderGenerator.prototype.addOut = function (name, type) { this.addLine("out " + types_1.convertTypeName(type) + " " + name + ";"); }; ShaderGenerator.prototype.generateExpression = function (expr) { var _this = this; switch (expr.type) { case "constant": { var eConstant = expr; return types_1.convertConstant(eConstant.valueType, eConstant.value); } case "variable": { var eVariable = expr; return eVariable.variableName; } case "function": { var eFunction = expr; var args = eFunction.arguments.map(function (arg) { return _this.generateExpression(arg); }); var _a = intrinsics_1.generateIntrinsicFunction(eFunction.functionName, args), code = _a.code, additionalCode = _a.additionalCode; if (additionalCode != null) { this.addAdditionalCode(additionalCode); } return code; } case "field": { var eField = expr; return this.generateExpression(eField.value) + "." + eField.fieldName; } } }; ShaderGenerator.prototype.addStatement = function (stat) { switch (stat.type) { case "assign": { var sAssign = stat; var expr = this.generateExpression(sAssign.expression); this.addLine(sAssign.variableName + " = " + expr + ";"); } break; case "condition": { var sCondition = stat; if (sCondition.trueStatements.length > 0 && sCondition.falseStatements.length > 0) { this.addLine("if(" + this.generateExpression(sCondition.condition) + ") {"); this.indent(); this.addStatements(sCondition.trueStatements); this.unindent(); this.addLine("} else {"); this.indent(); this.addStatements(sCondition.falseStatements); this.unindent(); this.addLine("}"); } else if (sCondition.trueStatements.length > 0) { this.addLine("if(" + this.generateExpression(sCondition.condition) + ") {"); this.indent(); this.addStatements(sCondition.trueStatements); this.unindent(); this.addLine("}"); } else if (sCondition.falseStatements.length > 0) { this.addLine("if(!" + this.generateExpression(sCondition.condition) + ") {"); this.indent(); this.addStatements(sCondition.trueStatements); this.unindent(); this.addLine("}"); } } break; case "for": { var sForLoop = stat; this.addLine("for(int " + sForLoop.variableName + " = " + sForLoop.rangeMin + "; " + sForLoop.variableName + " <= " + sForLoop.rangeMax + "; " + sForLoop.variableName + "++) {"); this.indent(); this.addStatements(sForLoop.statements); this.unindent(); this.addLine("}"); } break; case "emit": { var sEmit = stat; this.addEmitStatement(sEmit); } break; } }; ShaderGenerator.prototype.addStatements = function (stat) { var _this = this; stat.forEach(function (s) { return _this.addStatement(s); }); }; // Override these ShaderGenerator.prototype.addEmitStatement = function (s) { this.addLine("// Emit Statement"); }; return ShaderGenerator; }(LinesGenerator)); exports.ShaderGenerator = ShaderGenerator; var ProgramGenerator = /** @class */ (function () { function ProgramGenerator(spec, shader, asUniform) { var _this = this; this._spec = spec; this._shader = shader; this._asUniform = asUniform; // Make a record of existing names this._names = {}; var record_names = function (map) { for (var name_1 in map) { if (map.hasOwnProperty(name_1)) { _this._names[name_1] = true; } } }; record_names(spec.input); record_names(spec.output); record_names(spec.variables); record_names(shader.input); record_names(shader.output); } ProgramGenerator.prototype.getUnusedName = function (hint) { var index = 0; while (true) { var candidate = "s3" + hint + index.toString(); if (this._names[candidate] === true) { index += 1; continue; } this._names[candidate] = true; return candidate; } }; // Should we pass the mark input `name` to the fragment shader? ProgramGenerator.prototype.fragmentPassthru = function (name) { return this._spec.input.hasOwnProperty(name) && !this._spec.output.hasOwnProperty(name); }; return ProgramGenerator; }()); exports.ProgramGenerator = ProgramGenerator; //# sourceMappingURL=glsl.js.map