UNPKG

@animech-public/playcanvas

Version:
2 lines (1 loc) 3.57 kB
import{WebglShaderInput as e}from"./webgl-shader-input.js";import{semanticToLocation as t}from"../constants.js";import{DeviceCache as r}from"../device-cache.js";const s=new Set(["gl_VertexID","gl_InstanceID","gl_DrawID","gl_BaseVertex","gl_BaseInstance"]);class i{constructor(){this.map=new Map}destroy(e){this.map.forEach((t=>{e.gl.deleteShader(t)}))}loseContext(e){this.map.clear()}}const n=new r,o=new r;class a{constructor(e){this.compileDuration=0,this.init(),this.compile(e.device,e),this.link(e.device,e),e.device.shaders.push(e)}destroy(e){this.glProgram&&(e.device.gl.deleteProgram(this.glProgram),this.glProgram=null)}init(){this.uniforms=[],this.samplers=[],this.attributes=[],this.glProgram=null,this.glVertexShader=null,this.glFragmentShader=null}loseContext(){this.init()}restoreContext(e,t){this.compile(e,t),this.link(e,t)}compile(e,t){const r=t.definition;this.glVertexShader=this._compileShaderSource(e,r.vshader,!0),this.glFragmentShader=this._compileShaderSource(e,r.fshader,!1)}link(e,r){if(this.glProgram)return;const s=e.gl;if(s.isContextLost())return;const i=s.createProgram();this.glProgram=i,s.attachShader(i,this.glVertexShader),s.attachShader(i,this.glFragmentShader);const n=r.definition,o=n.attributes;if(e.isWebGL2&&n.useTransformFeedback){const e=[];for(const t in o)o.hasOwnProperty(t)&&e.push(`out_${t}`);s.transformFeedbackVaryings(i,e,s.INTERLEAVED_ATTRIBS)}for(const e in o)if(o.hasOwnProperty(e)){const r=o[e],n=t[r];s.bindAttribLocation(i,n,e)}s.linkProgram(i)}_compileShaderSource(e,t,r){const s=e.gl;if(s.isContextLost())return null;const a=(r?n:o).get(e,(()=>new i));let l=a.map.get(t);return l||(l=s.createShader(r?s.VERTEX_SHADER:s.FRAGMENT_SHADER),s.shaderSource(l,t),s.compileShader(l),a.map.set(t,l)),l}finalize(t,r){const i=t.gl;if(i.isContextLost())return!0;const n=this.glProgram,o=r.definition;if(!i.getProgramParameter(n,i.LINK_STATUS)){if(!this._isCompiled(t,r,this.glVertexShader,o.vshader,"vertex"))return!1;if(!this._isCompiled(t,r,this.glFragmentShader,o.fshader,"fragment"))return!1;const e=`Failed to link shader program. Error: ${i.getProgramInfoLog(n)}`;return console.error(e),!1}const a=i.getProgramParameter(n,i.ACTIVE_ATTRIBUTES);for(let l=0;l<a;l++){const a=i.getActiveAttrib(n,l),h=i.getAttribLocation(n,a.name);if(!s.has(a.name))if(void 0===o.attributes[a.name])console.error(`Vertex shader attribute "${a.name}" is not mapped to a semantic in shader definition, shader [${r.label}]`,r),r.failed=!0;else{const r=new e(t,o.attributes[a.name],t.pcUniformType[a.type],h);this.attributes.push(r)}}const l=t._samplerTypes,h=i.getProgramParameter(n,i.ACTIVE_UNIFORMS);for(let r=0;r<h;r++){const s=i.getActiveUniform(n,r),o=i.getUniformLocation(n,s.name),a=new e(t,s.name,t.pcUniformType[s.type],o);l.has(s.type)?this.samplers.push(a):this.uniforms.push(a)}return r.ready=!0,!0}_isCompiled(e,t,r,s,i){const n=e.gl;if(!n.getShaderParameter(r,n.COMPILE_STATUS)){const e=n.getShaderInfoLog(r),[t,o]=this._processError(s,e),a=`Failed to compile ${i} shader:\n\n${e}\n${t} while rendering undefined`;return console.error(a),!1}return!0}isLinked(e){const{extParallelShaderCompile:t}=e;return!t||e.gl.getProgramParameter(this.glProgram,t.COMPLETION_STATUS_KHR)}_processError(e,t){const r={};let s="";if(e){const i=e.split("\n");let n=0,o=i.length;if(t&&t.startsWith("ERROR:")){const e=t.match(/^ERROR:\s(\d+):(\d+):\s*(.+)/);e&&(r.message=e[3],r.line=parseInt(e[2],10),n=Math.max(0,r.line-6),o=Math.min(i.length,r.line+5))}for(let e=n;e<o;e++)s+=`${e+1}:\t${i[e]}\n`;r.source=e}return[s,r]}}export{a as WebglShader};