UNPKG

molstar

Version:

A comprehensive macromolecular library.

194 lines 8.05 kB
"use strict"; /** * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createProgram = exports.getProgram = void 0; var shader_code_1 = require("../shader-code"); var uniform_1 = require("./uniform"); var buffer_1 = require("./buffer"); var id_factory_1 = require("../../mol-util/id-factory"); var debug_1 = require("../../mol-util/debug"); var getNextProgramId = (0, id_factory_1.idFactory)(); function getLocations(gl, program, schema) { var locations = {}; Object.keys(schema).forEach(function (k) { var spec = schema[k]; if (spec.type === 'attribute') { var loc = gl.getAttribLocation(program, k); // unused attributes will result in a `-1` location which is usually fine // if (loc === -1) console.info(`Could not get attribute location for '${k}'`) locations[k] = loc; } else if (spec.type === 'uniform' || spec.type === 'texture') { var loc = gl.getUniformLocation(program, k); // unused uniforms will result in a `null` location which is usually fine // if (loc === null) console.info(`Could not get uniform location for '${k}'`) locations[k] = loc; } }); return locations; } function checkActiveAttributes(gl, program, schema) { var attribCount = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); for (var i = 0; i < attribCount; ++i) { var info = gl.getActiveAttrib(program, i); if (info) { var name_1 = info.name, type = info.type; if (name_1.startsWith('__activeAttribute')) { // name assigned by `gl.shim.ts`, ignore for checks continue; } if (name_1 === 'gl_InstanceID') continue; // WebGL2 built-in if (name_1 === 'gl_VertexID') continue; // WebGL2 built-in var spec = schema[name_1]; if (spec === undefined) { throw new Error("missing 'uniform' or 'texture' with name '" + name_1 + "' in schema"); } if (spec.type !== 'attribute') { throw new Error("'" + name_1 + "' must be of type 'attribute' but is '" + spec.type + "'"); } var attribType = (0, buffer_1.getAttribType)(gl, spec.kind, spec.itemSize); if (attribType !== type) { throw new Error("unexpected attribute type for " + name_1); } } } } function checkActiveUniforms(gl, program, schema) { var attribCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); for (var i = 0; i < attribCount; ++i) { var info = gl.getActiveUniform(program, i); if (info) { var name_2 = info.name, type = info.type; if (name_2.startsWith('__activeUniform')) { // name assigned by `gl.shim.ts`, ignore for checks continue; } var baseName = name_2.replace(/[[0-9]+\]$/, ''); // 'array' uniforms var spec = schema[baseName]; if (spec === undefined) { throw new Error("missing 'uniform' or 'texture' with name '" + name_2 + "' in schema"); } if (spec.type === 'uniform') { var uniformType = (0, uniform_1.getUniformType)(gl, spec.kind); if (uniformType !== type) { throw new Error("unexpected uniform type for " + name_2); } } else if (spec.type === 'texture') { if (spec.kind === 'image-float32' || spec.kind === 'image-uint8') { if (type !== gl.SAMPLER_2D) { throw new Error("unexpected sampler type for '" + name_2 + "'"); } } else if (spec.kind === 'volume-float32' || spec.kind === 'volume-uint8') { if (type !== gl.SAMPLER_3D) { throw new Error("unexpected sampler type for '" + name_2 + "'"); } } else { // TODO } } else { throw new Error("'" + name_2 + "' must be of type 'uniform' or 'texture' but is '" + spec.type + "'"); } } } } function checkProgram(gl, program) { // no-op in FF on Mac, see https://bugzilla.mozilla.org/show_bug.cgi?id=1284425 // gl.validateProgram(program) if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { throw new Error("Could not compile WebGL program. \n\n" + gl.getProgramInfoLog(program)); } } function getProgram(gl) { var program = gl.createProgram(); if (program === null) { throw new Error('Could not create WebGL program'); } return program; } exports.getProgram = getProgram; function createProgram(gl, state, extensions, getShader, props) { var defineValues = props.defineValues, _shaderCode = props.shaderCode, schema = props.schema; var program = getProgram(gl); var programId = getNextProgramId(); var shaderCode = (0, shader_code_1.addShaderDefines)(gl, extensions, defineValues, _shaderCode); var vertShader = getShader('vert', shaderCode.vert); var fragShader = getShader('frag', shaderCode.frag); var locations; var uniformSetters; function init() { vertShader.attach(program); fragShader.attach(program); gl.linkProgram(program); if (debug_1.isDebugMode) { checkProgram(gl, program); } locations = getLocations(gl, program, schema); uniformSetters = (0, uniform_1.getUniformSetters)(schema); if (debug_1.isDebugMode) { checkActiveAttributes(gl, program, schema); checkActiveUniforms(gl, program, schema); } } init(); var destroyed = false; return { id: programId, use: function () { // console.log('use', programId) state.currentProgramId = programId; gl.useProgram(program); }, setUniforms: function (uniformValues) { for (var i = 0, il = uniformValues.length; i < il; ++i) { var _a = uniformValues[i], k = _a[0], v = _a[1]; if (v) { var l = locations[k]; if (l !== null) uniformSetters[k](gl, l, v.ref.value); } } }, bindAttributes: function (attributeBuffers) { for (var i = 0, il = attributeBuffers.length; i < il; ++i) { var _a = attributeBuffers[i], k = _a[0], buffer = _a[1]; var l = locations[k]; if (l !== -1) buffer.bind(l); } }, bindTextures: function (textures, startingTargetUnit) { for (var i = 0, il = textures.length; i < il; ++i) { var _a = textures[i], k = _a[0], texture = _a[1]; var l = locations[k]; if (l !== null && l !== undefined) { texture.bind((i + startingTargetUnit)); uniformSetters[k](gl, l, (i + startingTargetUnit)); } } }, reset: function () { program = getProgram(gl); init(); }, destroy: function () { if (destroyed) return; vertShader.destroy(); fragShader.destroy(); gl.deleteProgram(program); destroyed = true; } }; } exports.createProgram = createProgram; //# sourceMappingURL=program.js.map