Source: shaders/shader_light_at.js

/*
 * File: shader_light_at.js 
 *      support of loading light info to the glsl shader
 *      references are pointing to uLight[index]
 */

"use strict";  // Operate in Strict mode such that variables must be declared before used!

import * as glSys from "../core/gl.js";
import { eLightType } from "../lights/light.js";

class ShaderLightAt {
    /**
     * @classdesc Support for loading light info to the GLSL shader
     * <p>Found in Chapter 8, page 435 of the textbook</p>
     * 
     * Example:
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter8/8.3.multiple_lights/index.html 8.3 Multiple Lights}
     * 
     * @constructor
     * @param {WebGLProgram} shader - the compiled light shader this ShaderLightAt belongs to
     * @param {integer} index - the index of this ShaderLightAt in the LightShader list of lights
     * @returns {ShaderLightAt} a new ShaderLightAt instance
     */
    constructor(shader, index) {
        this._setShaderReferences(shader, index);
    }

    /**
     * Attach all the necessary properties of a Light object to the gl context
     * @method
     * @param {Camera} aCamera - the Camera the light exists in
     * @param {Light} aLight - the Light object to be loaded
     */
    loadToShader(aCamera, aLight) {
        let gl = glSys.get();
        gl.uniform1i(this.mIsOnRef, aLight.isLightOn());
        // Process a light only when it is switched on
        if (aLight.isLightOn()) {
            let p = aCamera.wcPosToPixel(aLight.getPosition());
            let n = aCamera.wcSizeToPixel(aLight.getNear());
            let f = aCamera.wcSizeToPixel(aLight.getFar());
            let c = aLight.getColor();
            gl.uniform4fv(this.mColorRef, c);
            gl.uniform3fv(this.mPosRef, vec3.fromValues(p[0], p[1], p[2]));
            gl.uniform1f(this.mNearRef, n);
            gl.uniform1f(this.mFarRef, f);
            gl.uniform1f(this.mInnerRef, 0.0);
            gl.uniform1f(this.mOuterRef, 0.0);
            gl.uniform1f(this.mIntensityRef, aLight.getIntensity());
            gl.uniform1f(this.mDropOffRef, 0);
            gl.uniform1i(this.mLightTypeRef, aLight.getLightType());

            // Point light does not need the direction
            if (aLight.getLightType() === eLightType.ePointLight) {
                gl.uniform3fv(this.mDirRef, vec3.fromValues(0, 0, 0));
            } else {
                // either spot or directional lights: must compute direction
                let d = aCamera.wcDirToPixel(aLight.getDirection());
                gl.uniform3fv(this.mDirRef, vec3.fromValues(d[0], d[1], d[2]));
                if (aLight.getLightType() === eLightType.eSpotLight) {
                    gl.uniform1f(this.mInnerRef, Math.cos(0.5 * aLight.getInner())); // stores the cosine of half of inner cone angle
                    gl.uniform1f(this.mOuterRef, Math.cos(0.5 * aLight.getOuter())); // stores the cosine of half of outer cone angle
                    gl.uniform1f(this.mDropOffRef, aLight.getDropOff());
                }
            }
        }
    }
    /**
     * Turn this Light off
     * @method
     */
    switchOffLight() {
        let gl = glSys.get();
        gl.uniform1i(this.mIsOnRef, false);
    }
    //</editor-fold>

    //<editor-fold desc="private functions">
    _setShaderReferences(aLightShader, index) {
        let gl = glSys.get();
        this.mColorRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Color");
        this.mPosRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Position");
        this.mDirRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Direction");
        this.mNearRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Near");
        this.mFarRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Far");
        this.mInnerRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].CosInner");
        this.mOuterRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].CosOuter");
        this.mIntensityRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].Intensity");
        this.mDropOffRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].DropOff");
        this.mIsOnRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].IsOn");
        this.mLightTypeRef = gl.getUniformLocation(aLightShader, "uLights[" + index + "].LightType");
    }

}

export default ShaderLightAt;