Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable mrt on array texture and texture3d render targets #30151

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

wizgrav
Copy link
Contributor

@wizgrav wizgrav commented Dec 17, 2024

turns out that 3d and array textures can be drawn with MRT without any change in the renderer and this way is as flexible as you want it to be. I've updated the example for reference and uploaded using vanilla three on github pages,

here's the relevant snippet

function renderTo3DTexture() {

    // this sets layer 0 to COLOR_ATTACHMENT0 
    renderer.setRenderTarget( renderTarget );
    
    const gl = renderer.getContext();
    const drawBuffersArray = [ gl.COLOR_ATTACHMENT0 ];
    const glTexture = renderer.properties.get( renderTarget.texture ).__webglTexture;
    
    // set the rest of the layers to the corresponding attachments
    for ( let i = 1; i < 4; i ++ ) {
    
	    gl.framebufferTextureLayer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, glTexture, 0, i );
    
	    drawBuffersArray.push( gl.COLOR_ATTACHMENT0 + i );
    
    }
    
    // set draw buffers state for MRT
    gl.drawBuffers( drawBuffersArray );
    
    renderer.render( postProcessScene, postProcessCamera );
    
    // restore draw buffers state
    gl.drawBuffers( [ gl.COLOR_ATTACHMENT0 ] );
    
    renderer.setRenderTarget( null );
  
  }

Copy link

github-actions bot commented Dec 17, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 339.49
79.09
339.6
79.13
+112 B
+36 B
WebGPU 489.81
135.9
489.81
135.9
+0 B
+0 B
WebGPU Nodes 489.28
135.78
489.28
135.78
+0 B
+0 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 465.35
112.14
465.46
112.17
+112 B
+33 B
WebGPU 559.29
151.38
559.29
151.38
+0 B
+0 B
WebGPU Nodes 515.37
141.16
515.37
141.16
+0 B
+0 B


for ( let i = 0; i < renderTarget.textures.length; i ++ ) {

_gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, textureProperties.__webglTexture, activeMipmapLevel || 0, layer + i );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't layer + i be layer here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without the "+ i" it would attach the same layer of the texture to all COLOR_ATTACHMENTs. This way it will attach layer on ATTACHMENT0, layer + 1 on ATTACHMENT1 etc

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's not so intuitive to implicitly offset the bound layer for each MRT-attached 3d texture. I think this should be set to layer as Renaud has suggested under the assumption that each MRT texture is different.

And if there's a strong use case that requires binding different layers of the same 3d texture with MRT then that should be discussed in a separate issue so each layer is user-configurable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gkjohnson this was the only way that it would work with no changes/additions to the three api. We could have explicit assignment of layers to attachments by also allowing an array of indices as the layer argument. I can do the change but is this something that would be acceptable for the WebGLRenderer @Mugen87 ?

@wizgrav
Copy link
Contributor Author

wizgrav commented Jan 5, 2025

@gkjohnson turns out that 3d and array textures can be drawn with MRT without any change in the renderer at all. This way is as flexible as you want it to be. I've updated the example for reference, here's the snippet

function renderTo3DTexture() {

    // this sets layer 0 to COLOR_ATTACHMENT0 
    renderer.setRenderTarget( renderTarget );
    
    const gl = renderer.getContext();
    const drawBuffersArray = [ gl.COLOR_ATTACHMENT0 ];
    const glTexture = renderer.properties.get( renderTarget.texture ).__webglTexture;
    
    // set the rest of the layers to the corresponding attachments
    for ( let i = 1; i < 4; i ++ ) {
    
	    gl.framebufferTextureLayer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, glTexture, 0, i );
    
	    drawBuffersArray.push( gl.COLOR_ATTACHMENT0 + i );
    
    }
    
    // set draw buffers state for MRT
    gl.drawBuffers( drawBuffersArray );
    
    renderer.render( postProcessScene, postProcessCamera );
    
    // restore draw buffers state
    gl.drawBuffers( [ gl.COLOR_ATTACHMENT0 ] );
    
    renderer.setRenderTarget( null );
  
  }

@gkjohnson
Copy link
Collaborator

This may work but generally the project shouldn't be promoting directly setting gl state separately from the renderer since it can result in state conflicts. As mentioned in #30151 (comment) I think we can adjust 3d textures so MRT is supported in alignment with the existing three.js APIs. And then a more practical use case for binding separate 3d texture layers for MRT should be described either here or in another issue so we can discuss what an API for binding different layers might look like. The demo added in this PR feels more like a toy demonstration so I'm curious to how this would be used in a real world use case.

@wizgrav
Copy link
Contributor Author

wizgrav commented Jan 8, 2025

@gkjohnson the state will be fine as long as you restore it when done rendering. The demo is indeed a toy because I based it on the existing single layer example which doesn't make sense in the first place, it's just meant to showcase. The practical use case is GPGPU and I'm working on something delicious

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants