UNPKG

@awayjs/stage

Version:
288 lines (287 loc) 12.4 kB
import { Mapping } from './Mapping'; import { Settings } from '../Settings'; var AGLSLParser = /** @class */ (function () { function AGLSLParser() { this._usedLibs = {}; this._usedTemps = {}; } AGLSLParser.prototype._linkLib = function (opcode) { var libs = this._usedLibs; if (!libs[opcode] && Mapping.lib[opcode]) { libs[opcode] = true; this._header += '\n' + Mapping.lib[opcode] + '\n'; return true; } return libs[opcode]; }; AGLSLParser.prototype.parse = function (desc, precision, es300) { if (es300 === void 0) { es300 = false; } es300 = Settings.USE_300_SHADERS_FOR_WEBGL2 && es300; this._usedTemps = {}; this._usedLibs = {}; this._header = ''; this._body = ''; this._header += es300 ? '#version 300 es\n' : '#version 100\n'; this._header += 'precision ' + precision + ' float;\n'; var tag = desc.header.type[0]; //TODO var constcount = desc.regread[0x1].length; if (constcount > 0) { this._header += 'uniform vec4 ' + tag + 'c[' + constcount + '];\n'; } /* // declare temps for (let i = 0; i < desc.regread[REGISTER.TEMP].length || i < desc.regwrite[REGISTER.TEMP].length; i++) { // duh, have to check write only also... if (desc.regread[REGISTER.TEMP][i] || desc.regwrite[REGISTER.TEMP][i]) { this._header += 'vec4 ' + tag + 't' + i + ';\n'; } }*/ // declare streams for (var i = 0; i < desc.regread[0 /* REGISTER.ATTR */].length; i++) { if (desc.regread[0 /* REGISTER.ATTR */][i]) { this._header += (es300 ? 'in' : 'attribute') + ' vec4 va' + i + ';\n'; } } // declare interpolated for (var i = 0; i < desc.regread[4 /* REGISTER.VAR */].length || i < desc.regwrite[4 /* REGISTER.VAR */].length; i++) { if (desc.regread[4 /* REGISTER.VAR */][i] || desc.regwrite[4 /* REGISTER.VAR */][i]) { if (es300) { // in ES 300 out of vertex in of fragment this._header += (desc.header.type === 'vertex' ? 'out' : 'in') + ' vec4 vi' + i + ';\n'; } else { this._header += 'varying vec4 vi' + i + ';\n'; } } } // declare samplers for (var i = 0; i < desc.samplers.length; i++) { if (desc.samplers[i]) { this._header += 'uniform sampler' + AGLSLParser.SAMPLERS[desc.samplers[i].dim & 3] + ' fs' + i + ';\n'; } } // extra gl fluff: setup position and depth adjust temps if (desc.header.type == 'vertex') { this._header += 'vec4 outpos;\n'; } else if (es300) { // target is es300, emit out color this._header += 'out vec4 outColor;\n'; } if (desc.writedepth) { this._header += 'vec4 tmp_FragDepth;\n'; } //if ( desc.hasmatrix ) // header += "vec4 tmp_matrix;\n"; var derivatives = false; // start body of code this._body += 'void main() {\n'; for (var i = 0; i < desc.tokens.length; i++) { var token = desc.tokens[i]; var lutentry = Mapping.agal2glsllut[token.opcode]; var hasLib = this._linkLib(token.opcode); if (lutentry.s.indexOf('dFdx') != -1 || lutentry.s.indexOf('dFdy') != -1) derivatives = true; if (!lutentry) { throw 'Opcode not valid or not implemented yet: '; /*+token.opcode;*/ } var sublines = hasLib ? 1 : lutentry.matrixheight || 1; for (var sl = 0; sl < sublines; sl++) { var line = ' ' + lutentry.s; var destregstring = ''; var destcaststring = 'float'; var destmaskstring = ''; if (token.dest) { if (lutentry.matrixheight && !hasLib) { if (((token.dest.mask >> sl) & 1) != 1) { continue; } destmaskstring = AGLSLParser.SWIZZLE[sl]; destregstring = this.regtostring(token.dest.regtype, token.dest.regnum, desc, tag, es300); destregstring += '.' + destmaskstring; } else { destregstring = this.regtostring(token.dest.regtype, token.dest.regnum, desc, tag, es300); if (token.dest.mask != 0xf) { var ndest = 0; destmaskstring = ''; if (token.dest.mask & 1) { ndest++; destmaskstring += 'x'; } if (token.dest.mask & 2) { ndest++; destmaskstring += 'y'; } if (token.dest.mask & 4) { ndest++; destmaskstring += 'z'; } if (token.dest.mask & 8) { ndest++; destmaskstring += 'w'; } destregstring += '.' + destmaskstring; switch (ndest) { case 1: destcaststring = 'float'; break; case 2: destcaststring = 'vec2'; break; case 3: destcaststring = 'vec3'; break; default: throw 'Unexpected destination mask'; } } else { destcaststring = 'vec4'; destmaskstring = 'xyzw'; } } if (token.dest.regtype == 2 /* REGISTER.TEMP */ && !this._usedTemps[token.dest.regnum]) { var tmp = tag + 't' + token.dest.regnum; if (destcaststring === 'vec4') { destregstring = 'vec4 ' + tmp; } else { line = ' vec4 ' + tmp + ';\n' + line; } this._usedTemps[token.dest.regnum] = true; } line = line.replace('%dest', destregstring); line = line.replace('%cast', destcaststring); line = line.replace('%dm', destmaskstring); } var dwm = 0xf; if (!lutentry.ndwm && lutentry.dest && token.dest) { dwm = token.dest.mask; } if (token.a) { line = line.replace('%a', this.sourcetostring(token.a, 0, dwm, lutentry.scalar, desc, tag, es300)); line = line.replace('%ia', '' + token.a.regnum); } if (token.b) { line = line.replace('%b', this.sourcetostring(token.b, sl, dwm, lutentry.scalar, desc, tag, es300)); line = line.replace('%ib', '' + token.b.regnum); if (token.b.regtype == 0x5) { // sampler dim var texdim = AGLSLParser.SAMPLERS[token.b.dim]; var texsize = ['vec2', 'vec3', 'vec3'][token.b.dim]; // for es 300 not required a texture type line = line.replace('%texdim', es300 ? '' : texdim); line = line.replace('%texsize', texsize); line = line.replace('%lod', ''); } } this._body += line; } } // adjust z from opengl range of -1..1 to 0..1 as in d3d, this also enforces a left handed coordinate system if (desc.header.type == 'vertex') { this._body += ' gl_Position = vec4(outpos.x, outpos.y, outpos.z*2.0 - outpos.w, outpos.w);\n'; } //flag based switch if (derivatives && desc.header.type == 'fragment') { this._header = '#extension GL_OES_standard_derivatives : enable\n' + this._header; } // clamp fragment depth if (desc.writedepth) { this._body += ' gl_FragDepth = clamp(tmp_FragDepth,0.0,1.0);\n'; } // close main this._body += '}\n'; return this._header + this._body; }; AGLSLParser.prototype.regtostring = function (regtype, regnum, desc, tag, es300) { switch (regtype) { case 0 /* REGISTER.ATTR */: return 'va' + regnum; case 1 /* REGISTER.CONST */: return desc.header.type[0] + 'c[' + regnum + ']'; // case 0x1: // if (desc.hasindirect && desc.header.type == "vertex") { // return "vcarrr[" + regnum + "]"; // } else { // return tag + "c" + regnum; // } case 2 /* REGISTER.TEMP */: { return tag + 't' + regnum; } case 3 /* REGISTER.OUT */: { if (desc.header.type == 'vertex') { return 'outpos'; } else if (es300) { return 'outColor'; } return 'gl_FragColor'; } case 4 /* REGISTER.VAR */: return 'vi' + regnum; case 5 /* REGISTER.SAMPLER */: return 'fs' + regnum; case 15 /* REGISTER.NATIVE */: { if (desc.native[regnum] === undefined) { throw 'Native mapping not presented for register:' + regnum; } return desc.native[regnum]; } default: throw 'Unknown register type'; } }; AGLSLParser.prototype.sourcetostring = function (s, subline, dwm, isscalar, desc, tag, es300) { var swiz = AGLSLParser.SWIZZLE; var r; if (s.indirectflag) { r = 'vcarrr[int(' + this.regtostring(s.indexregtype, s.regnum, desc, tag, es300) + '.' + swiz[s.indexselect] + ')'; var realofs = subline + s.indexoffset; if (realofs < 0) r += realofs.toString(); if (realofs > 0) r += '+' + realofs.toString(); r += ']'; } else { r = this.regtostring(s.regtype, s.regnum + subline, desc, tag, es300); } // samplers and native never add swizzle if (s.regtype == 5 /* REGISTER.SAMPLER */ || s.regtype == 15 /* REGISTER.NATIVE */) { return r; } // scalar, first component only if (isscalar) { return r + '.' + swiz[(s.swizzle >> 0) & 3]; } // identity if (s.swizzle == 0xe4 && dwm == 0xf) { return r; } // with destination write mask folded in r += '.'; if (dwm & 1) r += swiz[(s.swizzle >> 0) & 3]; if (dwm & 2) r += swiz[(s.swizzle >> 2) & 3]; if (dwm & 4) r += swiz[(s.swizzle >> 4) & 3]; if (dwm & 8) r += swiz[(s.swizzle >> 6) & 3]; return r; }; AGLSLParser.SWIZZLE = ['x', 'y', 'z', 'w']; AGLSLParser.SAMPLERS = ['2D', 'Cube', '3D', '']; AGLSLParser.maxvertexconstants = 128; AGLSLParser.maxfragconstants = 28; AGLSLParser.maxtemp = 8; AGLSLParser.maxstreams = 8; AGLSLParser.maxtextures = 8; return AGLSLParser; }()); export { AGLSLParser };