Skip to content

WebGPURenderer - Better packing with MRT #32252

@FarazzShaikh

Description

@FarazzShaikh

Description

I have a usecase where I use a bunch of PostProcessing effects which require a lot of scene passes. I use setMRT to generate these passes.

const scenePass = TSL.pass(scene, camera);
scenePass.setMRT(
      TSL.mrt({
        output: TSL.output,
        normal: TSL.directionToColor(TSL.normalView),
        diffuse: TSL.diffuseColor,
        metalRough: TSL.vec2(TSL.metalness, TSL.roughness),
      })
);

However, this is not enough. I need to add an additional velocity pass. Doing so results in the total color attachment bytes exceeding its default maximum value of 32 bytes.

ERROR: Total color attachment bytes per sample (40) exceeds maximum (32) with formats...

I am already using UnsignedByteType for all of my passes.

outputTexture.type = THREE.UnsignedByteType;
...

Check out this fiddle with the error illustrated:

https://jsfiddle.net/farazshaikh/ztxdy6s4/14/

Solution

The solution here is to pack the passes more efficiently. However, packing the roughness/metalness into the alpha channels of the diffuseColor or normal results in unwanted alpha blending of transparent: true objects.

This is demonstrated in the following minimal Fiddle:

https://jsfiddle.net/farazshaikh/37c5uefh/2/

I am opening this issue to request an API for more efficient packing stratigies using MRT as suggested by Mugan87 here: https://discourse.threejs.org/t/webgpurenderer-postprocessing-cant-swap-beteween-results-from-2-differnet-mrt-passes/88047/5

Alternatives

The alternate solution is to set requiredLimits.maxColorAttachmentBytesPerSample in the WebGPURenderer constructor to higher than 32 bytes. But this is not scalable to all hardware.

Another alternative is to use multiple MRT passes, however, this seems to be broken as illustrated by this Fiddle: https://jsfiddle.net/farazshaikh/9dy7buqh/ . In this fiddle, I am unable to swap the MRT outputs attached to outputNode if the newly attached texture is from a different MRT pass.

I am unsure if this is a bug in ThreeJS or if I am misusing MRT.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions