11import {
2+ BINDGROUP_MESH , BINDGROUP_MESH_UB , BINDGROUP_VIEW ,
23 BLENDEQUATION_ADD , BLENDMODE_SRC_ALPHA , BLENDMODE_ONE_MINUS_SRC_ALPHA , BLENDMODE_ONE ,
34 BUFFER_STATIC ,
45 BUFFER_STREAM ,
@@ -12,13 +13,14 @@ import {
1213import { Debug } from '../../core/debug.js' ;
1314import { DepthState } from '../../platform/graphics/depth-state.js' ;
1415import { BlendState } from '../../platform/graphics/blend-state.js' ;
15- import { GraphNode } from '../../scene/graph-node.js' ;
16- import { MeshInstance } from '../../scene/mesh-instance.js' ;
17- import { Mesh } from '../../scene/mesh.js' ;
16+ import { BindGroup , DynamicBindGroup } from '../../platform/graphics/bind-group.js' ;
1817import { IndexBuffer } from '../../platform/graphics/index-buffer.js' ;
18+ import { RenderPass } from '../../platform/graphics/render-pass.js' ;
19+ import { ShaderProcessorOptions } from '../../platform/graphics/shader-processor-options.js' ;
20+ import { UniformBuffer } from '../../platform/graphics/uniform-buffer.js' ;
1921import { VertexBuffer } from '../../platform/graphics/vertex-buffer.js' ;
2022import { VertexFormat } from '../../platform/graphics/vertex-format.js' ;
21- import { ShaderMaterial } from '../../scene/materials /shader-material .js' ;
23+ import { ShaderUtils } from '../../scene/shader-lib /shader-utils .js' ;
2224
2325// Graph colors for MiniStats
2426const graphColorDefault = '1.0, 0.412, 0.380' ; // Pastel Red
@@ -154,6 +156,26 @@ const fragmentShaderWGSL = /* wgsl */ `
154156 }
155157` ;
156158
159+ const dynamicBindGroup = new DynamicBindGroup ( ) ;
160+
161+ // render pass drawing the overlay quads directly to the backbuffer, after the frame has rendered.
162+ // This makes the overlay independent of cameras and layers, with a full-canvas viewport.
163+ class RenderPassMiniStats extends RenderPass {
164+ constructor ( device , render2d ) {
165+ super ( device ) ;
166+ this . render2d = render2d ;
167+
168+ // render to the backbuffer, preserving its content
169+ this . init ( null ) ;
170+ this . colorOps . clear = false ;
171+ this . depthStencilOps . clearDepth = false ;
172+ }
173+
174+ execute ( ) {
175+ this . render2d . _draw ( ) ;
176+ }
177+ }
178+
157179// render 2d textured quads
158180class Render2d {
159181 constructor ( device , maxQuads = 2048 ) {
@@ -189,30 +211,33 @@ class Render2d {
189211 } ;
190212 this . quads = 0 ;
191213
192- this . mesh = new Mesh ( device ) ;
193- this . mesh . vertexBuffer = this . buffer ;
194- this . mesh . indexBuffer [ 0 ] = this . indexBuffer ;
195- this . mesh . primitive = [ this . prim ] ;
196-
197- const material = new ShaderMaterial ( {
214+ let shader = ShaderUtils . createShader ( device , {
198215 uniqueName : 'MiniStats' ,
199- vertexGLSL : vertexShaderGLSL ,
200- fragmentGLSL : fragmentShaderGLSL ,
201- vertexWGSL : vertexShaderWGSL ,
202- fragmentWGSL : fragmentShaderWGSL ,
203216 attributes : {
204217 vertex_position : SEMANTIC_POSITION ,
205218 vertex_texCoord0 : SEMANTIC_TEXCOORD0
206- }
219+ } ,
220+ vertexGLSL : vertexShaderGLSL ,
221+ fragmentGLSL : fragmentShaderGLSL ,
222+ vertexWGSL : vertexShaderWGSL ,
223+ fragmentWGSL : fragmentShaderWGSL
207224 } ) ;
208- this . material = material ;
209- material . cull = CULLFACE_NONE ;
210- material . depthState = DepthState . NODEPTH ;
211- material . blendState = new BlendState ( true , BLENDEQUATION_ADD , BLENDMODE_SRC_ALPHA , BLENDMODE_ONE_MINUS_SRC_ALPHA ,
225+
226+ // devices using uniform buffers need the shader processed and bind groups set up
227+ if ( device . supportsUniformBuffers ) {
228+ shader = ShaderUtils . processShader ( shader , new ShaderProcessorOptions ( ) ) ;
229+ const ubFormat = shader . meshUniformBufferFormat ;
230+ if ( ubFormat ) {
231+ this . uniformBuffer = new UniformBuffer ( device , ubFormat , false ) ;
232+ }
233+ this . bindGroup = new BindGroup ( device , shader . meshBindGroupFormat ) ;
234+ }
235+ this . shader = shader ;
236+
237+ this . blendState = new BlendState ( true , BLENDEQUATION_ADD , BLENDMODE_SRC_ALPHA , BLENDMODE_ONE_MINUS_SRC_ALPHA ,
212238 BLENDEQUATION_ADD , BLENDMODE_ONE , BLENDMODE_ONE ) ;
213- material . update ( ) ;
214239
215- this . meshInstance = new MeshInstance ( this . mesh , material , new GraphNode ( 'MiniStatsMesh' ) ) ;
240+ this . renderPass = new RenderPassMiniStats ( device , this ) ;
216241
217242 this . uniforms = {
218243 clr : new Float32Array ( 4 )
@@ -224,6 +249,14 @@ class Render2d {
224249 } ;
225250 }
226251
252+ destroy ( ) {
253+ this . renderPass . destroy ( ) ;
254+ this . uniformBuffer ?. destroy ( ) ;
255+ this . bindGroup ?. destroy ( ) ;
256+ this . buffer . destroy ( ) ;
257+ this . indexBuffer . destroy ( ) ;
258+ }
259+
227260 quad ( x , y , w , h , u , v , uw , uh , texture , wordFlag = 0 ) {
228261 // bounds check to prevent buffer overflow
229262 if ( this . quads >= this . maxQuads ) {
@@ -264,19 +297,54 @@ class Render2d {
264297 this . targetSize . height = this . device . canvas . scrollHeight ;
265298 }
266299
267- render ( app , layer , graphTexture , wordsTexture , clr , height ) {
300+ render ( graphTexture , wordsTexture , clr ) {
268301
269302 // set vertex data (swap storage)
270303 this . buffer . setData ( this . data . buffer ) ;
271304
272305 this . uniforms . clr . set ( clr , 0 ) ;
306+ this . graphTexture = graphTexture ;
307+ this . wordsTexture = wordsTexture ;
308+ }
309+
310+ // called by the render pass to draw the prepared quads
311+ _draw ( ) {
312+ const { device, prim } = this ;
313+ if ( ! prim . count ) {
314+ return ;
315+ }
273316
274- // material params
275- this . material . setParameter ( 'clr' , this . uniforms . clr ) ;
276- this . material . setParameter ( 'graphTex' , graphTexture ) ;
277- this . material . setParameter ( 'wordsTex' , wordsTexture ) ;
317+ // full backbuffer viewport, as a viewport of a previous camera can be active when the
318+ // frame graph merges this pass into the previous one
319+ const { width, height } = device ;
320+ device . setViewport ( 0 , 0 , width , height ) ;
321+ device . setScissor ( 0 , 0 , width , height ) ;
322+
323+ device . setDrawStates ( this . blendState , DepthState . NODEPTH , CULLFACE_NONE ) ;
324+
325+ const scope = device . scope ;
326+ scope . resolve ( 'clr' ) . setValue ( this . uniforms . clr ) ;
327+ scope . resolve ( 'graphTex' ) . setValue ( this . graphTexture ) ;
328+ scope . resolve ( 'wordsTex' ) . setValue ( this . wordsTexture ) ;
329+
330+ device . setVertexBuffer ( this . buffer ) ;
331+ device . setShader ( this . shader ) ;
332+
333+ if ( device . supportsUniformBuffers ) {
334+ device . setBindGroup ( BINDGROUP_VIEW , device . emptyBindGroup ) ;
335+
336+ this . bindGroup . update ( ) ;
337+ device . setBindGroup ( BINDGROUP_MESH , this . bindGroup ) ;
338+
339+ if ( this . uniformBuffer ) {
340+ this . uniformBuffer . update ( dynamicBindGroup ) ;
341+ device . setBindGroup ( BINDGROUP_MESH_UB , dynamicBindGroup . bindGroup , dynamicBindGroup . offsets ) ;
342+ } else {
343+ device . setBindGroup ( BINDGROUP_MESH_UB , device . emptyBindGroup ) ;
344+ }
345+ }
278346
279- app . drawMeshInstance ( this . meshInstance , layer ) ;
347+ device . draw ( prim , this . indexBuffer ) ;
280348 }
281349}
282350
0 commit comments