@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 10.6 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import"../../../../core/has.js";import{disposeMaybe as e,destroyMaybe as t}from"../../../../core/maybe.js";import{brushes as s}from"../brushes.js";import r from"../vectorTiles/shaders/VTLMaterialManager.js";import{BitBlitRenderer as i}from"./BitBlitRenderer.js";import{backbufferStencilVisible as n}from"./definitions.js";import{WGLDrawPhase as a}from"./enums.js";import o from"./MaterialManager.js";import l from"./TextureManager.js";import{TextureUploadManager as h}from"./TextureUploadManager.js";import{WorldExtentRenderer as f}from"./WorldExtentClipRenderer.js";import{BlendEffect as c}from"./effects/BlendEffect.js";import{FeatureEffect as d}from"./effects/FeatureEffect.js";import u from"./effects/HighlightEffect.js";import{HittestEffect as p}from"./effects/HittestEffect.js";import{EffectManager as _}from"./effects/post-processing/EffectManager.js";import{SimpleMesh as b}from"./meshing/SimpleMesh.js";import m from"./painter/RenderPass.js";import{TechniqueProgramCache as E}from"./shaderGraph/techniques/TechniqueProgramCache.js";import{TextureSamplingMode as S,TextureWrapMode as g,FramebufferBit as w,CompareFunction as M,BlendFactor as P,SizedDepthStencilFormat as C,BlendOperation as B,Face as N}from"../../../webgl/enums.js";import{FramebufferObject as O}from"../../../webgl/FramebufferObject.js";import{Renderbuffer as R}from"../../../webgl/Renderbuffer.js";import{RenderbufferDescriptor as A}from"../../../webgl/RenderbufferDescriptor.js";import{TextureDescriptor as T}from"../../../webgl/TextureDescriptor.js";class F{constructor(e,t){this.context=e,this._currentPipelineStateNeedsUpdate=!1,this._blitRenderer=new i,this._worldExtentRenderer=new f,this._brushCache=new Map,this._lastWidth=null,this._lastHeight=null,this._vtlMaterialManager=new r,this._blendEffect=new c,this._stencilBuf=null,this._prevBeforeLayerFBOStack=[],this._fboPool=[],this.effects={highlight:new u,hittest:new p,insideEffect:new d("inside"),outsideEffect:new d("outside")},this._programCache=new E,this._shaderState={shader:null,uniforms:null,defines:null,optionalAttributes:null,useComputeBuffer:!1},this.materialManager=new o(e),this.textureManager=new l(t),this.textureUploadManager=new h(t),this._effectsManager=new _,this._quadMesh=b.fromVertexStream(e,[0,0,1,0,0,1,1,1])}dispose(){if(this._programCache.destroy(),this.materialManager.dispose(),this.textureManager.dispose(),this.textureUploadManager.destroy(),this._blitRenderer=e(this._blitRenderer),this._worldExtentRenderer=e(this._worldExtentRenderer),this._quadMesh=t(this._quadMesh),this._brushCache&&(this._brushCache.forEach((e=>e.dispose())),this._brushCache.clear(),this._brushCache=null),this._fbos){let e;for(e in this._fbos)this._fbos[e]&&this._fbos[e].dispose()}for(const e of this._fboPool)e.dispose();if(this._fboPool.length=0,this.effects){let e;for(e in this.effects)this.effects[e]&&this.effects[e].dispose()}this._effectsManager.dispose(),this._blendEffect.dispose(this.context),this._vtlMaterialManager=e(this._vtlMaterialManager)}clearShaderCache(){this._programCache.destroy(),this._programCache=new E}get blitRenderer(){return this._blitRenderer}get vectorTilesMaterialManager(){return this._vtlMaterialManager}get quadMesh(){return this._quadMesh}getFbos(){if(!this._fbos)throw new Error("InternalError: Painter FBOs not initialized");return this._fbos}acquireFbo(e,t){let s;if(this._fboPool.length>0)s=this._fboPool.pop();else{const r=new T(e,t);r.samplingMode=S.NEAREST,r.wrapMode=g.CLAMP_TO_EDGE,s=new O(this.context,r,this._stencilBuf)}return s.width===e&&s.height===t||s.resize(e,t),s}releaseFbo(e){this._fboPool.push(e)}getSharedStencilBuffer(){return this._stencilBuf}beforeRenderPhases(e,t,s){const{context:r}=e;this._worldExtentRenderer.render(e,t,s);const{width:i,height:n}=r.getViewport();if(this.updateFBOs(i,n),this._prevFBO=r.getBoundFramebufferObject(),r.bindFramebuffer(this.getFbos().output),r.setColorMask(!0,!0,!0,!0),null!=t){const{r:e,g:s,b:i,a:n}=t;r.setClearColor(n*e/255,n*s/255,n*i/255,n)}else r.setClearColor(0,0,0,0);r.setDepthWriteEnabled(!0),r.setClearDepth(1),r.clear(w.COLOR|w.DEPTH),r.setDepthWriteEnabled(!1)}afterRenderPhases(e){const{context:t}=e;t.bindFramebuffer(this._prevFBO),t.setStencilFunction(M.EQUAL,n,255),t.setStencilTestEnabled(!0),t.setDepthTestEnabled(!1),this.blitTexture(t,this.getFbos().output.colorTexture,S.NEAREST)}beforeRenderLayer(e,t,s){const{context:r,blendMode:i,effects:n,drawPhase:a,requireFBO:o}=e;if(r.setClearColor(0,0,0,0),o||x(a,i,n,s)){const e=r.getBoundFramebufferObject();this._prevBeforeLayerFBOStack.push(e);const{width:t,height:s}=r.getViewport(),i=this.acquireFbo(t,s);r.bindFramebuffer(i),r.setColorMask(!0,!0,!0,!0),r.setClearColor(0,0,0,0),r.setDepthWriteEnabled(!0),r.setClearDepth(1),r.clear(w.COLOR|w.DEPTH),r.setDepthWriteEnabled(!1)}r.setDepthWriteEnabled(!1),r.setDepthTestEnabled(!1),r.setStencilTestEnabled(!0),r.setClearStencil(t),r.setStencilWriteMask(255),r.clear(w.STENCIL)}afterRenderLayer(e,t){const{context:s,blendMode:r,effects:i,requireFBO:n,drawPhase:o}=e;if(n||x(o,r,i,t)){const n=s.getBoundFramebufferObject();null!=i&&i.length>0&&o===a.MAP&&(s.setColorMask(!0,!0,!0,!0),this._applyEffects(e,i,n)),s.bindFramebuffer(this._prevBeforeLayerFBOStack.pop()),s.setStencilTestEnabled(!1),s.setStencilWriteMask(0),s.setBlendingEnabled(!0),s.setBlendFunctionSeparate(P.ONE,P.ONE_MINUS_SRC_ALPHA,P.ONE,P.ONE_MINUS_SRC_ALPHA),s.setColorMask(!0,!0,!0,!0);const l=null==r||o===a.HIGHLIGHT||o===a.LABEL?"normal":r;this._blendEffect.draw(e,n.colorTexture,S.NEAREST,l,t),this.releaseFbo(n)}}renderObject(e,t,r,i){const n=s[r];if(!n)return;let a=this._brushCache.get(n);void 0===a&&(a=new n,this._brushCache.set(n,a)),a.prepareState(e),a.draw(e,t,i)}renderObjects(e,t,r,i){const n=s[r];if(!n)return;let a=this._brushCache.get(n);void 0===a&&(a=new n,this._brushCache.set(n,a)),a.drawMany(e,t,i)}registerRenderPass(e){const t=e.brushes.map((e=>(this._brushCache.has(e)||this._brushCache.set(e,new e),this._brushCache.get(e))));return new m(t,e)}blitTexture(e,t,s,r=1){e.setBlendingEnabled(!0),e.setBlendFunctionSeparate(P.ONE,P.ONE_MINUS_SRC_ALPHA,P.ONE,P.ONE_MINUS_SRC_ALPHA),e.setColorMask(!0,!0,!0,!0),this._blitRenderer.render(e,t,s,r),this._currentPipelineStateNeedsUpdate=!0}getPostProcessingEffects(e){return this._effectsManager.getPostProcessingEffects(e)}updateFBOs(e,t){if(e!==this._lastWidth||t!==this._lastHeight){if(this._lastWidth=e,this._lastHeight=t,this._fbos){let s;for(s in this._fbos)this._fbos[s].resize(e,t);return}const s=new T(e,t);s.samplingMode=S.NEAREST,s.wrapMode=g.CLAMP_TO_EDGE;const r=new A(C.DEPTH24_STENCIL8,e,t);this._stencilBuf=new R(this.context,r),this._fbos={output:new O(this.context,s,this._stencilBuf),effect0:new O(this.context,s,this._stencilBuf)}}}_applyEffects(e,t,s){const{context:r}=e,i=this._effectsManager.getPostProcessingEffects(t);for(const{postProcessingEffect:n,effect:a}of i)r.bindFramebuffer(s),n.draw(e,s,a);this._currentPipelineStateNeedsUpdate=!0}setShader(e){this._shaderState.shader=e.shader,this._shaderState.uniforms=e.uniforms,this._shaderState.defines=e.defines,this._shaderState.optionalAttributes=e.optionalAttributes,this._shaderState.useComputeBuffer=e.useComputeBuffer??!1}setPipelineState(e){e!==this._currentPipelineState&&(this._currentPipelineState=e,this._currentPipelineStateNeedsUpdate=!0)}submitDraw(e,t){const{shader:s,uniforms:r,defines:i,optionalAttributes:n}=this._shaderState,a=e.context,o=t.getAttributePrecisionPackFactors(),l=this._programCache.getProgram(s,o,r,i??{},n??{});return l.setUniforms(r),l.bind(a),this.updatePipelineState(a),this.setStencilRef(a,t),t.draw(e,s.locationInfo),l.cleanupTemporaryTextures(),{vertexShader:l.vertexShader,fragmentShader:l.fragmentShader}}submitDrawMesh(e,t,s,r){this.submitDrawMeshUntyped(e,t,s,r)}submitDrawMeshUntyped(e,t,s,r){this.setShader(t);const{shader:i,uniforms:n,defines:a,optionalAttributes:o}=this._shaderState,l=this._programCache.getProgram(i,{},n,a??{},o??{});if(l.setUniforms(n),l.bind(e),this.updatePipelineState(e),r)for(const h of r)s.bind(e,t.shader.locationInfo,h),s.draw(e);else for(let h=0;h<s.parts.length;h++)s.bind(e,t.shader.locationInfo,h),s.draw(e);s.unbind(e),l.cleanupTemporaryTextures()}updatePipelineState(e){this._currentPipelineStateNeedsUpdate&&(this._currentPipelineStateNeedsUpdate=!1,this._updatePipelineState(e))}_updatePipelineState(e){if(null==this._currentPipelineState)throw new Error("Pipeline state not defined. Call setPipelineState before calling submitDraw ");const{color:t,depth:s,stencil:r}=this._currentPipelineState;if(t){const{blendMode:s,write:r}=t;switch(e.setColorMask(...r),e.setBlendingEnabled(!0),e.setBlendEquation(B.ADD),s){case"composite":e.setBlendFunctionSeparate(P.ONE,P.ONE_MINUS_SRC_ALPHA,P.ONE,P.ONE_MINUS_SRC_ALPHA);break;case"additive":e.setBlendFunctionSeparate(P.ONE,P.ONE,P.ONE,P.ONE);break;case"custom":{const{blendParameters:s}=t,{dstAlpha:r,dstRGB:i,srcAlpha:n,srcRGB:a}=s;e.setBlendFunctionSeparate(a,i,n,r);break}case"delete":e.setBlendEquation(B.REVERSE_SUBTRACT),e.setBlendFunctionSeparate(P.ONE,P.ONE_MINUS_SRC_ALPHA,P.ONE,P.ONE_MINUS_SRC_ALPHA)}}else e.setColorMask(!1,!1,!1,!1);if(s){const{test:t,write:r}=s;r?(e.setDepthWriteEnabled(!0),e.setDepthRange(r.zNear,r.zFar)):e.setDepthWriteEnabled(!1),t?(e.setDepthTestEnabled(!0),e.setDepthFunction(t)):e.setDepthTestEnabled(!1)}else e.setDepthTestEnabled(!1),e.setDepthWriteEnabled(!1);if(r){const{test:t,write:s}=r;if(t){const{compare:s,mask:r,op:i,ref:n}=t;e.setStencilTestEnabled(!0),"function"!=typeof n&&e.setStencilFunctionSeparate(N.FRONT_AND_BACK,s,n,r),e.setStencilOpSeparate(N.FRONT_AND_BACK,i.fail,i.zFail,i.zPass)}else e.setStencilTestEnabled(!1);if(s){const{mask:t}=s;e.setStencilWriteMask(t)}else e.setStencilWriteMask(0)}else e.setStencilTestEnabled(!1),e.setStencilWriteMask(0)}setStencilRef(e,t){if(null==this._currentPipelineState)throw new Error("Pipeline state not defined. Call setPipelineState before calling submitDraw ");const{stencil:s}=this._currentPipelineState;if(s){const{test:r}=s;if(r){const{compare:s,mask:i,ref:n}=r;let a=null;if("function"==typeof n?a=n(t):"number"==typeof n&&(a=n),null==a&&(a=t.getStencilReference()),null==a)throw new Error("InternalError: Stencil reference expected for target but not defined");e.setStencilFunctionSeparate(N.FRONT_AND_BACK,s,a,i)}}}}function x(e,t,s,r){return e!==a.LABEL_ALPHA&&e!==a.LABEL&&e!==a.HIGHLIGHT&&(1!==r||null!=t&&"normal"!==t||null!=s&&s.length>0)}export{F as default};