UNPKG

@animech-public/playcanvas

Version:
2 lines (1 loc) 4.18 kB
import{hashCode as e}from"../../core/hash.js";import{version as t,revision as s}from"../../core/core.js";import{Shader as i}from"../../platform/graphics/shader.js";import{SHADER_FORWARD as r,SHADER_SHADOW as a,SHADER_DEPTH as n,SHADER_PICK as o,SHADER_PREPASS_VELOCITY as h}from"../constants.js";import{ShaderPass as c}from"../shader-pass.js";import{StandardMaterialOptions as d}from"../materials/standard-material-options.js";class l{constructor(e,t){this.processedCache=new Map,this.definitionsCache=new Map,this._generators=new Map,this._device=e,this._isClearingCache=!1,this._precached=!1,this._programsCollection=[],this._defaultStdMatOption=new d,this._defaultStdMatOptionMin=new d,t.shaderOptBuilder.updateRef(this._defaultStdMatOption,{},t,null,[],r,null),t.shaderOptBuilder.updateMinRef(this._defaultStdMatOptionMin,{},t,null,a,null),e.on("destroy:shader",(e=>{this.removeFromCache(e)}))}destroy(){this.clearCache()}register(e,t){this._generators.has(e)||this._generators.set(e,t)}unregister(e){this._generators.has(e)&&this._generators.delete(e)}isRegistered(e){return this._generators.has(e)}generateShaderDefinition(e,t,s,i){let r=this.definitionsCache.get(s);if(!r){var a,n,o;let h;null!=(a=i.litOptions)&&a.lights&&(h=i.litOptions.lights,i.litOptions.lights=h.map((e=>{const t=e.clone?e.clone():e;return t.key=e.key,t}))),this.storeNewProgram(t,i),null!=(n=i.litOptions)&&n.lights&&(i.litOptions.lights=h),this._precached;const c=this._device;r=e.createShaderDefinition(c,i),r.name=null!=(o=r.name)?o:i.pass?`${t}-pass:${i.pass}`:t,this.definitionsCache.set(s,r)}return r}getCachedShader(e){return this.processedCache.get(e)}setCachedShader(e,t){this.processedCache.set(e,t)}getProgram(t,s,r,a){const n=this._generators.get(t);if(!n)return null;const o=n.generateKey(s),h=e(o),d=r.generateKey(this._device),l=`${h}#${e(d)}`;let p=this.getCachedShader(l);if(!p){const e=this.generateShaderDefinition(n,t,h,s);let o,d="";void 0!==s.pass&&(o=c.get(this._device).getByIndex(s.pass),d=`-${o.name}`),this._device.fire("shader:generate",{userMaterialId:a,shaderPassInfo:o,definition:e});const g={name:`${e.name}${d}-proc`,attributes:e.attributes,vshader:e.vshader,vincludes:e.vincludes,fincludes:e.fincludes,fshader:e.fshader,processingOptions:r,shaderLanguage:e.shaderLanguage};p=new i(this._device,g),this.setCachedShader(l,p)}return p}storeNewProgram(e,t){let s={};if("standard"===e){const e=this._getDefaultStdMatOptions(t.pass);for(const i in t)(t.hasOwnProperty(i)&&e[i]!==t[i]||"pass"===i)&&(s[i]=t[i]);for(const e in t.litOptions)s[e]=t.litOptions[e]}else s=t;this._programsCollection.push(JSON.stringify({name:e,options:s}))}dumpPrograms(){let e="let device = pc.app ? pc.app.graphicsDevice : pc.Application.getApplication().graphicsDevice;\n";e+="let shaders = [",this._programsCollection[0]&&(e+=`\n\t${this._programsCollection[0]}`);for(let t=1;t<this._programsCollection.length;++t)e+=`,\n\t${this._programsCollection[t]}`;e+="\n];\n",e+="device.getProgramLibrary().precompile(shaders);\n",e+=`if (pc.version != "${t}" || pc.revision != "${s}")\n`,e+='\tconsole.warn("precompile-shaders.js: engine version mismatch, rebuild shaders lib with current engine");';const i=document.createElement("a");i.setAttribute("href",`data:text/plain;charset=utf-8,${encodeURIComponent(e)}`),i.setAttribute("download","precompile-shaders.js"),i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i)}clearCache(){this._isClearingCache=!0,this.processedCache.forEach((e=>{e.destroy()})),this.processedCache.clear(),this._isClearingCache=!1}removeFromCache(e){this._isClearingCache||this.processedCache.forEach(((t,s)=>{e===t&&this.processedCache.delete(s)}))}_getDefaultStdMatOptions(e){const t=c.get(this._device).getByIndex(e);return e===n||e===o||e===h||t.isShadow?this._defaultStdMatOptionMin:this._defaultStdMatOption}precompile(e){if(e){const t=new Array(e.length);for(let s=0;s<e.length;s++){if("standard"===e[s].name){const t=e[s].options,i=this._getDefaultStdMatOptions(t.pass);for(const e in i)i.hasOwnProperty(e)&&void 0===t[e]&&(t[e]=i[e])}t[s]=this.getProgram(e[s].name,e[s].options)}}this._precached=!0}}export{l as ProgramLibrary};