namespace NT { export enum BuiltinShader { BASIC = "basic" } /**
     * Represents a WebGL shader.
     * */ export abstract class Shader { private _name : string ; private _program : WebGLProgram ; private _attributes : { [ name ] : number ; } = { } ; private _uniforms : { [ name ] : WebGLUniformLocation ; } = { } ; param name public constructor ( name ) { this . _name = name ; } /**
         * Destroys this shader.
         */ public destroy ( ) { } /**
         * The name of this shader.
         */ public get name ( ) : string { return this . _name ; } /**
         * Use this shader.
         * */ public use ( ) { if ( ShaderManager . ActiveShader !== this ) { gl . useProgram ( this . _program ) ; ShaderManager . ActiveShader = this ; } } public SetUniformMatrix4x4 ( uniformName , matrix ) { if ( this . _uniforms [ uniformName ] === undefined ) { console . warn ( `Unable to find uniform named '${ uniformName }' in shader named '${ this . _name }'` ) ; return ; } let position = this . getUniformLocation ( uniformName ) ; gl . uniformMatrix4fv ( position , false , matrix . toFloat32Array ( ) ) ; } public SetUniformColor ( uniformName , color ) { if ( this . _uniforms [ uniformName ] === undefined ) { console . warn ( `Unable to find uniform named '${ uniformName }' in shader named '${ this . _name }'` ) ; return ; } let position = this . getUniformLocation ( uniformName ) ; gl . uniform4fv ( position , color . toFloat32Array ( ) ) ; } public SetUniformInt ( uniformName , value ) { if ( this . _uniforms [ uniformName ] === undefined ) { console . warn ( `Unable to find uniform named '${ uniformName }' in shader named '${ this . _name }'` ) ; return ; } let position = this . getUniformLocation ( uniformName ) ; gl . uniform1i ( position , value ) ; } param name public getAttributeLocation ( name ) { if ( this . _attributes [ name ] === undefined ) { throw new Error ( `Unable to find attribute named '${ name }' in shader named '${ this . _name }'` ) ; } return this . _attributes [ name ] ; } param name public getUniformLocation ( name ) { if ( this . _uniforms [ name ] === undefined ) { throw new Error ( `Unable to find uniform named '${ name }' in shader named '${ this . _name }'` ) ; } return this . _uniforms [ name ] ; } /**
         * Applies standard uniforms to this shader.
         */ public abstract ApplyStandardUniforms ( material , model , view , projection ) ; param vertexSource param fragmentSource protected load ( vertexSource , fragmentSource ) { let vertexShader = this . loadShader ( vertexSource , gl . VERTEX_SHADER ) ; let fragmentShader = this . loadShader ( fragmentSource , gl . FRAGMENT_SHADER ) ; this . createProgram ( vertexShader , fragmentShader ) ; this . detectAttributes ( ) ; this . detectUniforms ( ) ; } private loadShader ( source , shaderType ) { let shader = gl . createShader ( shaderType ) ; gl . shaderSource ( shader , source ) ; gl . compileShader ( shader ) ; let error = gl . getShaderInfoLog ( shader ) . trim ( ) ; if ( error !== "" ) { throw new Error ( "Error compiling shader '" + this . _name + "': " + error ) ; } return shader ; } private createProgram ( vertexShader , fragmentShader ) { this . _program = gl . createProgram ( ) ; gl . attachShader ( this . _program , vertexShader ) ; gl . attachShader ( this . _program , fragmentShader ) ; gl . linkProgram ( this . _program ) ; let error = gl . getProgramInfoLog ( this . _program ) . trim ( ) ; if ( error !== "" ) { throw new Error ( "Error linking shader '" + this . _name + "': " + error ) ; } } private detectAttributes ( ) { let attributeCount = gl . getProgramParameter ( this . _program , gl . ACTIVE_ATTRIBUTES ) ; for ( let i = 0 ; i < attributeCount ; ++ i ) { let info = gl . getActiveAttrib ( this . _program , i ) ; if ( ! info ) { break ; } this . _attributes [ info . name ] = gl . getAttribLocation ( this . _program , info . name ) ; } } private detectUniforms ( ) { let uniformCount = gl . getProgramParameter ( this . _program , gl . ACTIVE_UNIFORMS ) ; for ( let i = 0 ; i < uniformCount ; ++ i ) { let info = gl . getActiveUniform ( this . _program , i ) ; if ( ! info ) { break ; } this . _uniforms [ info . name ] = gl . getUniformLocation ( this . _program , info . name ) ; } } } }