const SHADER_HEAD="precision highp float;",VERT_DEFAULT=SHADER_HEAD+"attribute vec2 position;void main(){gl_Position=vec4(position,0, 1.);}",FRAG_DEFAULT=SHADER_HEAD+"precision highp float;void main(){gl_FragColor = vec4(1.,0.,0.,1.);}";function convertArray(t,e=WebGLRenderingContext.FLOAT){if(e===WebGLRenderingContext.FLOAT)return new Float32Array(t);if(e===WebGLRenderingContext.BYTE)return new Uint8Array(t);throw Error("type not supported")}function shader(t,e){return{shaderType:e,init:r=>{const i=/frag/.test(e)?WebGLRenderingContext.FRAGMENT_SHADER:WebGLRenderingContext.VERTEX_SHADER,n=r.createShader(i);if(!n)throw Error("shader type not supported");if(r.shaderSource(n,t),r.compileShader(n),!r.getShaderParameter(n,r.COMPILE_STATUS))throw"Could not compile Shader.\n\n"+r.getShaderInfoLog(n);return n}}}class GLea{constructor({canvas:t,gl:e,contextType:r="webgl",shaders:i,buffers:n,devicePixelRatio:a=1,glOptions:s}){if(this.canvas=document.createElement("canvas"),this.canvas=t||document.querySelector("canvas"),this.canvas||(this.canvas=document.createElement("canvas"),document.body.appendChild(this.canvas)),!document.querySelector("link[rel=stylesheet], style")){const t=document.createElement("style");t.innerHTML="body{margin:0}canvas{display:block;width:100vw;height:100vh}",document.head.appendChild(t)}this.contextType=r,this.glOptions=s,this.gl=e||this.getContext(r,s);const o=this.gl.createProgram();this.program=o,this.buffers={},this.shaderFactory=i,this.bufferFactory=n||this.getDefaultBuffers(),this.textures=[],this.devicePixelRatio=a}getDefaultBuffers(){return{position:GLea.buffer(2,[1,1,-1,1,1,-1,-1,-1])}}getContext(t,e){if("webgl"===t)return this.canvas.getContext("webgl",e)||this.canvas.getContext("experimental-webgl",e);if("webgl2"===t)return this.canvas.getContext("webgl2",e);throw Error(`no ${t} context available.`)}static vertexShader(t=VERT_DEFAULT){return shader(t,"vert")}static fragmentShader(t=FRAG_DEFAULT){return shader(t,"frag")}prog(t,e,r){const i=t.createProgram(),n=e.init(t),a=r.init(t);if(t.attachShader(i,n),t.attachShader(i,a),t.linkProgram(i),t.validateProgram(i),!t.getProgramParameter(i,t.LINK_STATUS)){throw"Could not compile WebGL program. \n\n"+t.getProgramInfoLog(i)}return i}static buffer(t,e,r=WebGLRenderingContext.STATIC_DRAW,i=WebGLRenderingContext.FLOAT,n=!1,a=0,s=0){return(o,h,c)=>{const f=h.getAttribLocation(c,o);h.enableVertexAttribArray(f);const u=h.createBuffer(),g=e instanceof Array?convertArray(e,i):e;return h.bindBuffer(h.ARRAY_BUFFER,u),h.bufferData(h.ARRAY_BUFFER,g,r),h.vertexAttribPointer(f,t,i,n,a,s),{id:u,name:o,data:g,loc:f,type:i,size:t,normalized:n,stride:a,offset:s}}}drawArrays(t,e=0,r){if(void 0===r){const t=Object.keys(this.buffers);if(0===t.length)return;const e=t[0],i=this.buffers[e];r=i.data.length/i.size}this.gl.drawArrays(t,e,r)}disableAttribs(){const{gl:t,program:e,buffers:r}=this;for(let i of Object.keys(r)){const r=t.getAttribLocation(e,i);t.disableVertexAttribArray(r)}}enableAttribs(){const{gl:t,program:e,buffers:r}=this;this.use();for(let i of Object.keys(r)){const n=r[i],a=t.getAttribLocation(e,i);t.enableVertexAttribArray(a),t.bindBuffer(t.ARRAY_BUFFER,r[i].id),t.vertexAttribPointer(a,n.size,n.type,n.normalized,n.stride,n.offset)}}create(){const{gl:t}=this;return this.program=this.prog(t,this.shaderFactory[0],this.shaderFactory[1]),this.use(),Object.keys(this.bufferFactory).forEach(e=>{const r=this.bufferFactory[e];this.buffers[e]=r(e,t,this.program)}),this.parent||this.resize(),this}replaceCanvas(){const{canvas:t}=this,e=t.cloneNode();t.parentNode&&(t.parentNode.insertBefore(e,t),t.parentNode.removeChild(t)),this.canvas=e}restart(){return this.replaceCanvas(),this.gl=this.getContext(this.contextType,this.glOptions),this.create(),this}add({shaders:t,buffers:e}){const r=new GLea({canvas:this.canvas,gl:this.gl,shaders:t,buffers:e||this.getDefaultBuffers()});return r.parent=this.parent||this,r.create(),r}setActiveTexture(t,e){const{gl:r}=this;r.activeTexture(r.TEXTURE0+t),r.bindTexture(r.TEXTURE_2D,e)}createTexture(t=0,e={textureWrapS:"clampToEdge",textureWrapT:"clampToEdge",textureMinFilter:"nearest",textureMagFilter:"nearest"}){const r=(t="")=>/^[A-Z0-9_]+$/.test(t)?t:t.replace(/([A-Z])/g,"_$1").toUpperCase(),{gl:i}=this,n=i.createTexture();i.activeTexture(i.TEXTURE0+t),i.bindTexture(i.TEXTURE_2D,n);for(let t in e)if(e.hasOwnProperty(t)){const n=r(t),a=r(e[t]);n in i&&a in i&&i.texParameteri(i.TEXTURE_2D,i[n],i[a])}return this.textures.push(n),n}updateBuffer(t,e=0){const{gl:r}=this,i=this.buffers[t];r.bindBuffer(r.ARRAY_BUFFER,i.id),r.bufferSubData(r.ARRAY_BUFFER,e,i.data)}resize(){const{canvas:t,gl:e,devicePixelRatio:r}=this;t&&(t.width=t.clientWidth*r,t.height=t.clientHeight*r,e.viewport(0,0,e.drawingBufferWidth,e.drawingBufferHeight))}get width(){return this.canvas?this.canvas.width:NaN}get height(){return this.canvas?this.canvas.height:NaN}use(){return this.gl.useProgram(this.program),this}uniM(t,e){const{gl:r,program:i}=this,n=r.getUniformLocation(i,t);if(4===e.length)return r.uniformMatrix2fv(n,!1,e),n;if(9===e.length)return r.uniformMatrix3fv(n,!1,e),n;if(16===e.length)return r.uniformMatrix4fv(n,!1,e),n;throw Error("unsupported uniform matrix type")}uniV(t,e){const{gl:r,program:i}=this,n=r.getUniformLocation(i,t);if(2===e.length)return r.uniform2fv(n,e),n;if(3===e.length)return r.uniform3fv(n,e),n;if(4===e.length)return r.uniform4fv(n,e),n;throw Error("unsupported uniform vector type")}uniIV(t,e){const{gl:r,program:i}=this,n=r.getUniformLocation(i,t);if(2===e.length)return r.uniform2iv(n,e),n;if(3===e.length)return r.uniform3iv(n,e),n;if(4===e.length)return r.uniform4iv(n,e),n;throw Error("unsupported uniform vector type")}uni(t,e){const{gl:r,program:i}=this,n=r.getUniformLocation(i,t);return"number"==typeof e&&r.uniform1f(n,e),n}uniI(t,e){const{gl:r,program:i}=this,n=r.getUniformLocation(i,t);"number"==typeof e&&r.uniform1i(n,e)}clear(t=null){const{gl:e}=this;t&&e.clearColor(t[0],t[1],t[2],1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}destroy(){const{gl:t,program:e}=this;try{t.deleteProgram(e),Object.values(this.buffers).forEach(e=>{t.deleteBuffer(e.id)}),this.buffers={},this.textures.forEach(e=>{t.deleteTexture(e)}),this.textures=[],t.getExtension("WEBGL_lose_context").loseContext(),this.replaceCanvas()}catch(t){console.error(t)}}}export default GLea;
