Source

Program.js

import ContextResource from './ContextResource';
import FileLoader from './Loaders/FileLoader';

/**
 * A program
 *
 * @category Shaders
 * @extends {ContextResource}
 */
export class Program extends ContextResource {
    /**
     * Constructor
     *
     * @constructor
     */
    constructor() {
        super();

        /**
         * Attributes
         *
         * @type {Array.<ProgramElement>}
         * @private
         */
        this.attributes = [];

        /**
         * Shader sources
         *
         * - First index is for the vertex shader
         * - Second index is for the fragment shader
         *
         * @type {Array.<string>}
         * @private
         */
        this.sources = [null, null];

        /**
         * Uniforms
         *
         * @type {Array.<Program.Element>}
         * @private
         */
        this.uniforms = [];
    }

    /**
     * Load program from shader files
     *
     * @param {string} vertexFile Path to the vertex shader file
     * @param {string} fragmentFile Path to the fragment shader file
     */
    async loadFromFiles(vertexFile, fragmentFile) {
        const vertexReponse = await FileLoader.load(vertexFile);
        this.sources[0] = vertexReponse.data;

        const fragmentResponse = await FileLoader.load(fragmentFile);
        this.sources[1] = fragmentResponse.data;
    }

    /**
     * Load program from data
     *
     * @param {string} vertexSource Vertex shader code
     * @param {string} fragmentSource Fragment shader code
     */
    loadFromData(vertexSource, fragmentSource) {
        this.sources[0] = vertexSource;
        this.sources[1] = fragmentSource;
    }

    /**
     * Get attributes
     *
     * @return {Array.<ProgramElement>} An array of attribute
     */
    getAttributes() {
        return this.attributes;
    }

    /**
     * Get program's sources
     *
     * @return {Array.<string>} Index 0: Vertex shader, Index 1: Fragment shader
     */
    getSources() {
        return this.sources;
    }

    /**
     * Get uniform
     *
     * @param {string} name Name of the uniform
     * @return {?ProgramElement} A program Element or null if uniform doesn't exist
     */
    getUniform(name) {
        return this.uniforms[name] || null;
    }

    /**
     * Get uniforms
     *
     * @return {Array.<ProgramElement>} An array of uniforms
     */
    getUniforms() {
        return this.uniforms;
    }

    /**
     * Say if program is ready to be use
     *
     * Source array must have two elements: the fragment and the vertex shaders
     * @return {boolean} True if program is ready, otherwise false
     */
    isReady() {
        return (this.sources.length === 2 && this.sources[0] !== null && this.sources[1] !== null);
    }
}

/**
 * An element from the shader
 *
 * @category Shaders
 * @constructor
 */
export class ProgramElement {
    /**
     * Constructor
     *
     * @param {number} location Location in the shader
     * @param {string} name His name
     * @param {Type} type Element's type (float, vec, …)
     * @param {number} size Element's size
     */
    constructor(location, name, type, size) {
        /**
         * Location in the shader
         *
         * @type {number}
         * @public
         */
        this.location = location;

        /**
         * Name
         *
         * @type {string}
         * @public
         */
        this.name = name;

        /**
         * Type
         *
         * @type {Type}
         * @public
         */
        this.type = type;

        /**
         * Size/Count
         *
         * @type {number}
         * @public
         */
        this.size = size;
    }
}