@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 6.74 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{_ as t}from"../../../../chunks/tslib.es6.js";import{disposeMaybe as e,destroyMaybe as i}from"../../../../core/maybe.js";import{property as r}from"../../../../core/accessorSupport/decorators/property.js";import"../../../../core/has.js";import"../../../../core/Logger.js";import"../../../../core/RandomLCG.js";import{subclass as s}from"../../../../core/accessorSupport/decorators/subclass.js";import{multiply as o,fromTranslation as n}from"../../../../core/libs/gl-matrix-2/math/mat4.js";import{create as h}from"../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{i as a,a as u}from"../../../../chunks/vec32.js";import{create as c}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{RenderCategory as p}from"../../webgl.js";import f from"../../webgl/RenderNode.js";import{ColorFormat as _}from"../core/FBOCacheFormats.js";import{RenderRequestType as l}from"./basicInterfaces.js";import{Default3D as d}from"./DefaultVertexAttributeLocations.js";import{TaskPriority as m}from"../../../support/Scheduler.js";import{Yield as g}from"../../../support/Yield.js";import{PixelFormat as x,DataType as v,PixelType as T,TextureSamplingMode as w}from"../../../webgl/enums.js";import{makePipelineState as y,defaultColorWrite as b}from"../../../webgl/renderState.js";import{Sync as j}from"../../../webgl/Sync.js";import{Texture as E}from"../../../webgl/Texture.js";import{TextureDescriptor as P}from"../../../webgl/TextureDescriptor.js";let B=class extends f{constructor(t){super(t),this.category=p.COMPOSITE,this.running=!1,this.done=!0,this._origin=c(),this._textureWidth=256,this._uploadBuffer=new Float32Array(3*this._textureWidth),this._counter=0,this._width=0,this._height=0,this._pipeline=y({colorWrite:b}),this._format=0}initialize(){this.view.resourceController.scheduler.registerTask(m.GRAPHICS_CORE,this),this.produces="disabled",this.consumes.required=[this.category],this.formatOverride&&(this._format=this.formatOverride)}destroy(){this._program=e(this._program);const t=this.gl;this._sync=i(this._sync),this._pixelBuffer&&(t.deleteBuffer(this._pixelBuffer),this._pixelBuffer=null),this._texture=e(this._texture)}precompile(){this._ensureShader(this.renderingContext)}render(t){const e=t.find((({name:t})=>t===this.category));if(this._sync)return e;this.produces="disabled";const i=this.renderingContext,r=this.gl,s=e.getTexture(r.DEPTH_STENCIL_ATTACHMENT);if(!s)return e;const h=this.view.stage.renderer.fboCache.acquire(this._width,this._height,"hud visibility",_.R32FLOAT);i.bindFramebuffer(h.fbo),i.setPipelineState(this._pipeline);const a=this._ensureShader(i);i.useProgram(a);const u=0;i.bindTexture(s,u),a.setUniform1i("depthTex",u);const c=1;return i.bindTexture(this._texture,c),a.setUniform1i("positionTex",c),o(D,this.camera.viewMatrix,n(D,this._origin)),a.setUniformMatrix4fv("view",D),a.setUniformMatrix4fv("proj",this.camera.projectionMatrix),a.setUniform1i("count",this._counter),i.screen.draw(),this._pixelBuffer||(this._pixelBuffer=r.createBuffer()),0===this._format&&(this._format=r.getParameter(r.IMPLEMENTATION_COLOR_READ_FORMAT)===x.RED&&r.getParameter(r.IMPLEMENTATION_COLOR_READ_TYPE)===v.FLOAT?x.RED:x.RGBA),r.bindBuffer(r.PIXEL_PACK_BUFFER,this._pixelBuffer),r.bufferData(r.PIXEL_PACK_BUFFER,this._width*this._height*(this._format===x.RED?4:16),r.STREAM_READ),r.readPixels(0,0,this._width,this._height,this._format,v.FLOAT,0),this._sync=new j(r),h.release(),setTimeout((()=>this.running=!0),0),e}runTask(){if(!this._sync)return void(this.running=!1);try{if(!this._sync.poll())return g}catch(e){return this.running=!1,void(this._sync=i(this._sync))}this.running=!1,this._sync=i(this._sync);const t=this.gl;t.bindBuffer(t.PIXEL_PACK_BUFFER,this._pixelBuffer),this._cpuBuffer=new Float32Array(this._width*this._height*(this._format===x.RED?1:4)),t.getBufferSubData(t.PIXEL_PACK_BUFFER,0,this._cpuBuffer),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),this.done=!0}init(t,e){const i=this._textureWidth;if(this._width=i,this._height=Math.ceil(t/i),this._counter=0,this._texture?.dispose(),0===this._height)return;const r=new P(this._width,this._height);r.pixelFormat=x.RGB,r.dataType=T.FLOAT,r.samplingMode=w.NEAREST,this._texture=new E(this.renderingContext,r),this.done=!1,a(this._origin,Math.fround(e[0]),Math.fround(e[1]),Math.fround(e[2]))}addPosition(t){const e=this._width;if(this._counter>=e*this._height)return-1;const i=this._counter%e;return u(A,t,this._origin),this._uploadBuffer[3*i+0]=A[0],this._uploadBuffer[3*i+1]=A[1],this._uploadBuffer[3*i+2]=A[2],i===e-1&&this._flush(),this._counter++}start(){if(0===this._width||0===this._height)return;const t=this._width;this._counter%t>0&&this._flush(),this.produces=this.category,this.requestRender(l.UPDATE)}getOcclusion(t){return this._cpuBuffer?.[this._format===x.RED?t:4*t]??-1}_flush(){const t=this._width,e=Math.floor(this._counter/t);this._texture?.updateData(0,0,e,t,1,this._uploadBuffer)}_ensureShader(t){return null!=this._program||(this._program=t.programCache.acquire(C,R,d)),this._program}};t([r()],B.prototype,"category",void 0),t([r()],B.prototype,"formatOverride",void 0),t([r()],B.prototype,"running",void 0),t([r()],B.prototype,"done",void 0),B=t([s("esri.views.3d.webgl-engine.lib.GPUPointOcclusionQuery")],B);const C="#version 300 es\nprecision highp float;\nin vec2 position;\n\nvoid main() {\n gl_Position = vec4(position, 0.0, 1.0);\n}",R="#version 300 es\nprecision highp float;\nout highp vec4 fragColor;\n\nuniform highp mat4 proj;\nuniform highp mat4 view;\n\nuniform highp int count;\n\nuniform highp sampler2D depthTex;\nuniform highp sampler2D positionTex;\n\nfloat linearizeDepth(float depth) {\n float depthNdc = depth * 2.0 - 1.0;\n float c1 = proj[3][2];\n float c2 = proj[2][2];\n return -c1 / (depthNdc + c2 + 1e-7);\n}\n\nvoid main() {\n int u = int(floor(gl_FragCoord.x));\n int v = int(floor(gl_FragCoord.y));\n if (u + v * textureSize(positionTex, 0).x >= count) {\n fragColor = vec4(-1);\n return;\n }\n vec4 posWorld = vec4(texelFetch(positionTex, ivec2(u, v), 0).rgb, 1.0);\n\n vec4 posView = view * posWorld;\n vec4 projected = proj * posView;\n\n vec3 clipPos = projected.xyz / projected.w;\n\n if (clipPos.x < -1.0 || clipPos.x > 1.0 || clipPos.y < -1.0 || clipPos.y > 1.0) {\n fragColor = vec4(-1);\n return;\n }\n\n vec3 uvDepth = 0.5 * clipPos + vec3(0.5);\n\n float depth = texture(depthTex, uvDepth.xy).r;\n\n if (uvDepth.z <= depth) {\n fragColor = vec4(0);\n return;\n }\n\n fragColor = vec4(linearizeDepth(depth) - linearizeDepth(uvDepth.z));\n}\n",A=c(),D=h();export{B as GPUPointOcclusionQuery};