import Kernel from './Kernel' ; export default class Program { ready : boolean = false ; activeInfosObject : any ; program : WebGLProgram ; private static currentProgram : Program ; private static readonly programs : Program [ ] = [ ] ; private constructor ( public vs , public fs ) { this . activeInfosObject = { } ; this . _init ( ) ; } static getProgram ( vs , fs ) { var program = Program . findProgram ( vs , fs ) ; if ( ! program ) { program = new Program ( vs , fs ) ; Program . programs . push ( program ) ; } return program ; } static findProgram ( vs , fs ) { var program = null ; Program . programs . some ( function ( item ) { if ( item . vs === vs && item . fs === fs ) { program = item ; return true ; } else { return false ; } } ) ; return program ; } use ( ) { if ( this . ready && Program . currentProgram !== this ) { Kernel . gl . useProgram ( this . program ) ; Program . currentProgram = this ; } } updateActiveAttribInfos ( ) { var count = Kernel . gl . getProgramParameter ( this . program , Kernel . gl . ACTIVE_ATTRIBUTES ) ; for ( var i = 0 , activeInfo ; i < count ; i ++ ) { activeInfo = Kernel . gl . getActiveAttrib ( this . program , i ) ; activeInfo . loc = Kernel . gl . getAttribLocation ( this . program , activeInfo . name ) ; activeInfo . isAttribute = true ; this . activeInfosObject [ activeInfo . name ] = activeInfo ; } } updateActiveUniformInfos ( ) { var count = Kernel . gl . getProgramParameter ( this . program , Kernel . gl . ACTIVE_UNIFORMS ) ; for ( var i = 0 , activeInfo ; i < count ; i ++ ) { activeInfo = Kernel . gl . getActiveUniform ( this . program , i ) ; activeInfo . loc = Kernel . gl . getUniformLocation ( this . program , activeInfo . name ) ; activeInfo . isAttribute = false ; this . activeInfosObject [ activeInfo . name ] = activeInfo ; } } getLocation ( name ) { var loc = - 1 ; var activeInfo = this . activeInfosObject [ name ] ; if ( activeInfo ) { loc = activeInfo . loc ; } return loc ; } getAttribLocation ( name ) { var loc = - 1 ; var activeInfo = this . activeInfosObject [ name ] ; if ( activeInfo && activeInfo . isAttribute ) { loc = activeInfo . loc ; } return loc ; } getUniformLocation ( name ) { var loc ; var activeInfo = this . activeInfosObject [ name ] ; if ( activeInfo && ! activeInfo . isAttribute ) { loc = activeInfo . loc ; } return loc ; } getVertexAttrib ( ) { } getUniform ( name ) { var result ; var loc = this . getUniformLocation ( name ) ; if ( loc ) { result = Kernel . gl . getUniform ( this . program , loc ) ; } return result ; } enableVertexAttribArray ( name ) { var activeInfo = this . activeInfosObject [ name ] ; if ( activeInfo && activeInfo . isAttribute && activeInfo . isEnabled !== true ) { var loc = activeInfo . loc ; Kernel . gl . enableVertexAttribArray ( loc ) ; activeInfo . isEnabled = true ; } } disableVertexAttribArray ( name ) { var activeInfo = this . activeInfosObject [ name ] ; if ( activeInfo && activeInfo . isAttribute && activeInfo . isEnabled !== false ) { var loc = activeInfo . loc ; Kernel . gl . disableVertexAttribArray ( loc ) ; activeInfo . isEnabled = false ; } } _init ( ) { var vs = this . _getShader ( Kernel . gl . VERTEX_SHADER , this . vs ) ; if ( ! vs ) { return ; } var fs = this . _getShader ( Kernel . gl . FRAGMENT_SHADER , this . fs ) ; if ( ! fs ) { return ; } this . program = Kernel . gl . createProgram ( ) ; Kernel . gl . attachShader ( this . program , vs ) ; Kernel . gl . attachShader ( this . program , fs ) ; Kernel . gl . linkProgram ( this . program ) ; if ( ! Kernel . gl . getProgramParameter ( this . program , Kernel . gl . LINK_STATUS ) ) { console . error ( "Could not link program!" ) ; Kernel . gl . deleteProgram ( this . program ) ; Kernel . gl . deleteShader ( vs ) ; Kernel . gl . deleteShader ( fs ) ; this . program = null ; return ; } this . updateActiveAttribInfos ( ) ; this . updateActiveUniformInfos ( ) ; this . ready = true ; } _getShader ( shaderType , shaderText ) { var shader = Kernel . gl . createShader ( shaderType ) ; Kernel . gl . shaderSource ( shader , shaderText ) ; Kernel . gl . compileShader ( shader ) ; if ( ! Kernel . gl . getShaderParameter ( shader , Kernel . gl . COMPILE_STATUS ) ) { console . error ( "create shader failed" , Kernel . gl . getShaderInfoLog ( shader ) ) ; Kernel . gl . deleteShader ( shader ) ; return null ; } return shader ; } } ;