mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.86k stars 35.32k forks source link

I wish an example for the outputStruct node #28180

Closed Spiri0 closed 5 months ago

Spiri0 commented 5 months ago

Description

I looked in the examples and asked in the forum but so far only Berthur and I have had anything to do with the outputStruct. Therefore I would like a simple example that demonstrates the outputStruct with two shaders whose shaders can be stored in textures with a renderTarget.

Something like that:

renderTarget = new THREE.RenderTarget(window.innerWidth * dpr, window.innerHeight * dpr, {count: 2});

const fragmentShader1 = wgslFn(`
  fn main1(
  ) -> vec4<f32> {
    return vec4<f32>(1, 0, 0, 1);
  }
`);

const fragmentShader2 = wgslFn(`
  fn main2(
  ) -> vec4<f32> {
    return vec4<f32>(0, 1, 0, 1);
  }
`);

const material = new MeshBasicNodeMaterial();
material.outputNode = outputStruct(
  fragmentShader1(),
  fragmentShader2(),
);

quad = new QuadMesh(material);

//in the render loop
quad.render(renderer);

renderer.setRenderTarget( renderTarget );
renderer.render( scene, camera );
renderer.setRenderTarget( null );

https://discourse.threejs.org/t/use-of-multiple-fragmentshaders-with-outputstruct-and-rendertarget/64287

I looked at the RenderTarget code in threejs. A lot seems to have happened over the last few releases. The RenderTarget class also seems to be designed to process multiple textures because I see an array for textures in it. But I admit that I don't yet understand the renderTarget class well enough to be able to derive an example from it.

Solution

The solution would be a simple example code as described in the description

Alternatives

The alternative would be a documentation, but in the end this would contain the same thing as a simple example and an example is the nicer solution

Additional context

No response

Mugen87 commented 5 months ago

The RenderTarget class also seems to be designed to process multiple textures because I see an array for textures in it.

This is for MRT. Could the following example help? webgpu_multiple_rendertargets

Spiri0 commented 5 months ago

Thanks for the example, I hadn't associated it with the outputStruct. I looked at it extensively and tested it with shaders. This works so far, very nice. The issue was still worth it because a tiny expansion is necessary. Since I need this functionality in conjunction with the "readRenderTargetPixelsAsync", I tested it straight away and noticed that the function "readRenderTargetPixelsAsync" only accepts a renderTarget but has no index to be able to select the texture in the renderTarget. Then I just changed the following function:

In ...jsm/renderers/common/Renderer

readRenderTargetPixelsAsync( renderTarget, x, y, width, height ) {

    return this.backend.copyTextureToBuffer( renderTarget.texture, x, y, width, height );

}

to:

readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0 ) {

    return this.backend.copyTextureToBuffer( renderTarget.textures[index], x, y, width, height );

}

This means you can then work as usual without having to assign an index, but you can choose to select the second texture if necessary or any texture if there is one. This works, I tested it. But I didn't want to change anything in the renderer without talk about.

Mugen87 commented 5 months ago

In this case, this issue can then be merged into #22403.

We can cover WebGPURenderer in #22403 as well.