export default class Shader { constructor(gl, vSource, fSource) { this.gl = gl; this.vSource = vSource; this.fSource = fSource; this.uniformBlockNum = 0; this.shaderProgram = 123; this.vShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(this.vShader, this.vSource); this.gl.compileShader(this.vShader); if (!this.gl.getShaderParameter(this.vShader, this.gl.COMPILE_STATUS)) { console.error(this.gl.getShaderInfoLog(this.vShader)); } this.fShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(this.fShader, this.fSource); this.gl.compileShader(this.fShader); if (!this.gl.getShaderParameter(this.fShader, this.gl.COMPILE_STATUS)) { console.error(this.gl.getShaderInfoLog(this.fShader)); } } get vertexShader() { return this.vShader; } get fragmentShader() { return this.fShader; } get program() { return this.shaderProgram; } getUniformBlock(name) { const location = this.gl.getUniformBlockIndex(this.shaderProgram, name); this.gl.uniformBlockBinding(this.shaderProgram, location, this.uniformBlockNum); this.uniformBlockNum++; return location; } getUniform(name) { return this.gl.getUniformLocation(this.shaderProgram, name); } attribLocation(location, name) { this.gl.bindAttribLocation(this.shaderProgram, location, name); } setUniform(uniform, value) { switch (uniform.type) { case this.gl.FLOAT: this.gl.uniform1f(uniform, value); break; case this.gl.FLOAT_VEC2: this.gl.uniform2f(uniform, value[0], value[1]); break; case this.gl.FLOAT_VEC3: this.gl.uniform3f(uniform, value[0], value[1], value[2]); break; case this.gl.FLOAT_VEC4: this.gl.uniform4f(uniform, value[0], value[1], value[2], value[3]); break; case this.gl.INT: this.gl.uniform1i(uniform, value); break; case this.gl.INT_VEC2: this.gl.uniform2i(uniform, value[0], value[1]); break; case this.gl.INT_VEC3: this.gl.uniform3i(uniform, value[0], value[1], value[2]); break; case this.gl.INT_VEC4: this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]); break; case this.gl.BOOL: this.gl.uniform1i(uniform, value); break; case this.gl.BOOL_VEC2: this.gl.uniform2i(uniform, value[0], value[1]); break; case this.gl.BOOL_VEC3: this.gl.uniform3i(uniform, value[0], value[1], value[2]); break; case this.gl.BOOL_VEC4: this.gl.uniform4i(uniform, value[0], value[1], value[2], value[3]); break; case this.gl.FLOAT_MAT2: this.gl.uniformMatrix2fv(uniform, false, value); break; case this.gl.FLOAT_MAT3: this.gl.uniformMatrix3fv(uniform, false, value); break; case this.gl.FLOAT_MAT4: this.gl.uniformMatrix4fv(uniform, false, value); break; case this.gl.SAMPLER_2D: this.gl.uniform1i(uniform, value); break; case this.gl.SAMPLER_CUBE: this.gl.uniform1i(uniform, value); break; default: console.error(`Unsupported uniform type ${uniform.type}`); } } link() { this.shaderProgram = this.gl.createProgram(); this.gl.attachShader(this.shaderProgram, this.vShader); this.gl.attachShader(this.shaderProgram, this.fShader); this.gl.linkProgram(this.shaderProgram); if (!this.gl.getProgramParameter(this.shaderProgram, this.gl.LINK_STATUS)) { console.error(this.gl.getProgramParameter(this.shaderProgram)); } } attatch() { this.gl.useProgram(this.shaderProgram); } }