(vertexSource, fragmentSource)
| 106 | } |
| 107 | |
| 108 | _createProgram(vertexSource, fragmentSource) { |
| 109 | const gl = this.gl; |
| 110 | |
| 111 | const vertexShader = this._compileShader(vertexSource, gl.VERTEX_SHADER); |
| 112 | const fragmentShader = this._compileShader(fragmentSource, gl.FRAGMENT_SHADER); |
| 113 | |
| 114 | const program = gl.createProgram(); |
| 115 | gl.attachShader(program, vertexShader); |
| 116 | gl.attachShader(program, fragmentShader); |
| 117 | gl.linkProgram(program); |
| 118 | |
| 119 | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { |
| 120 | const error = gl.getProgramInfoLog(program); |
| 121 | gl.deleteProgram(program); |
| 122 | throw new Error(`Program link error: ${error}`); |
| 123 | } |
| 124 | |
| 125 | // Once linked, the individual shader objects are no longer needed; detach |
| 126 | // and delete them so they don't leak for the lifetime of the GL context. |
| 127 | gl.detachShader(program, vertexShader); |
| 128 | gl.detachShader(program, fragmentShader); |
| 129 | gl.deleteShader(vertexShader); |
| 130 | gl.deleteShader(fragmentShader); |
| 131 | |
| 132 | program.attributes = { |
| 133 | position: gl.getAttribLocation(program, 'a_position'), |
| 134 | texCoord: gl.getAttribLocation(program, 'a_texCoord') |
| 135 | }; |
| 136 | |
| 137 | program.uniforms = {}; |
| 138 | const uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); |
| 139 | for (let i = 0; i < uniformCount; i++) { |
| 140 | const info = gl.getActiveUniform(program, i); |
| 141 | program.uniforms[info.name] = gl.getUniformLocation(program, info.name); |
| 142 | } |
| 143 | |
| 144 | return program; |
| 145 | } |
| 146 | |
| 147 | _initPrograms() { |
| 148 | this.programs.passthrough = this._createProgram(VERTEX_SHADER, PASSTHROUGH_FRAGMENT_SHADER); |
no test coverage detected