three.js icon indicating copy to clipboard operation
three.js copied to clipboard

readRenderTargetPixels() works for WebGLRenderTarget but is all 0 for WebGL3DRenderTarget

Open hubtub2 opened this issue 1 year ago • 21 comments

Description

I am using a shader to write to a 3D render target. To debug the result I am using renderer.readRenderTargetPixels()

The result for WebGLRenderTarget is correct, the result for WebGL3DRenderTarget is all zero.

Reproduction steps

Please check the fiddle:

  1. First run as is and check the output on the console: the buffer contains 0,0,0,255
  2. Now go to line 66 and enable the line with WebGLRenderTarget and disable the line with WebGL3DRenderTarget
  3. The output now is correct: 102, 255, 15, 255

Code

See fiddle for complete example.

//-- 3D or 2D Render target
// brushTarget = new THREE.WebGLRenderTarget(32, 32) 
brushTarget = new THREE.WebGL3DRenderTarget(32, 32, 32)


var layer=0;   // Layer in 3D Texture

renderer.setRenderTarget(brushTarget, layer);
renderer.render( brushScene, brushCamera );    
    
var buffer = new Uint8Array(4); 
renderer.readRenderTargetPixels(brushTarget, 16, 16, 1, 1, buffer, layer)

console.log("Debug read brush", buffer)   // Press F12 to show chrome console

Live example

https://jsfiddle.net/92xa60g4/25/

Screenshots

No response

Version

r164

Device

Desktop

Browser

Chrome

OS

Windows

hubtub2 avatar May 27 '24 18:05 hubtub2

An alternative cause would be that RTT 3D does not work - but I do not see a reason for it.

hubtub2 avatar May 28 '24 07:05 hubtub2

I have tested with the latest version r164 and the methods seems to work as expected. Below is the result for a 3D render target (first log) and a normal render target (second log):

image

Can you try it with the latest version as well?

Side note: When calling readRenderTargetPixels(), the last parameter is only relevant for cube render targets since it defines which cube face you want to select. When setting 3D render targets via setRenderTarget(), the method always uses framebufferTextureLayer() to define what layer (depth) should be bound. By default it is zero but you can set any index between [0, depth - 1]. This part is used correctly in the fiddle and it ensures the scene is rendered in the respective layer. Since you don't alter the render target configuration, the readback selects the same layer as well.

Mugen87 avatar May 28 '24 09:05 Mugen87

Thank you for testing. The fiddle imports already the current revision 164, see image:

image

(r156 was just my dev environment - I will change it in the bug report)

Any idea why the output is 0,0,0 on my system? I tried the fiddle in Firefox & Chrome and on Laptop and Workstation - same result - always 0,0,0 for 3D render target :-(

hubtub2 avatar May 28 '24 10:05 hubtub2

Oh, I misunderstood your bug report. I was assuming you had issues with an older version of three.js. But since you are also having trouble with r164, this might be a system related issue.

Since you are using Chrome, do you mind typing chrome://gpu/ into the address bar, download the report and share it in this issue? Besides, what happens if you make a test with Firefox?

Mugen87 avatar May 28 '24 11:05 Mugen87

So I tried on 3 browsers on 2 systems - the output is consistent:

Firefox Notebook: image

Chrome Notebook: image

Firefox Workstation: image

Chrome Workstation: image

Edge Workstation: image

Here is the output of the chrome://gpu/ for both systems:

Notebook: about-gpu-2024-05-28T12-52-23-516Z.txt

Workstation: about-gpu-2024-05-28T12-53-45-799Z.txt

I wonder if it is a read or a write problem.

hubtub2 avatar May 28 '24 13:05 hubtub2

Is the plane in the following fiddle red or white on your systems? https://jsfiddle.net/9ecums7j/1/

The demo has two passes. The first one renders the scene into the first layer of a 3D render target. The second one uses the first layer as a texture for a plane mesh.

Mugen87 avatar May 28 '24 18:05 Mugen87

The render window is black, both computers, Chrome and Firefox.

image

No error message on the console. After clicking "run" the render window "flashes white" for an instance.

When I replace the WebGL3DRenderTarget with a WebGLRenderTarget, I see a white plane: image

hubtub2 avatar May 28 '24 19:05 hubtub2

When I replace the WebGL3DRenderTarget with a WebGLRenderTarget, I see a white plane:

Using a normal render target is incompatible with the custom shader since it uses sampler3D.

So it seems there is an issue with rendering into 3D render targets on your devices. Or there is an issue with using them as a texture. Maybe the call of gl.framebufferTextureLayer() is broken or something similar.

This is unfortunately not something we can fix in this repository. Would you mind reporting the issue at the Chromium bug tracker (https://issues.chromium.org/issues)? Please attach your Chrome GPU reports, a link to this issue and the below fiddle. I've simplified it a bit so it is focused on the most important things: https://jsfiddle.net/47donLx0/

I've also changed the color semantics. Green color means using the 3D render target as a texture works as expected.

Mugen87 avatar May 28 '24 21:05 Mugen87

BTW: Do you see any WebGL warnings in the browser console on the affected devices? Just want to be sure we do not overlook something obvious...

Mugen87 avatar May 28 '24 21:05 Mugen87

Will do. But isn't it suspicious that the behavior is the same on Firefox, which is not using Chromium? Do they have a common WebGL implementation?

hubtub2 avatar May 28 '24 21:05 hubtub2

But isn't it suspicious that the behavior is the same on Firefox, which is not using Chromium?

If it's a GPU driver issue, the used browser does not necessarily matter. If the Chromium devs conclude the root cause is driver related, they might adapt a workaround on browser level or redirect the issue to the GPU vendor.

Mugen87 avatar May 28 '24 22:05 Mugen87

An added datapoint:

I have the same issues, I came across it while implementing WebGL3DRenderTarget in the WebGPURenderer. WebGPU worked fine, WebGL failed as described above, using FF and Chrome with Intel integrated and external GPUs using D3D and Vulkan backends, which suggests this is an ANGLE problem which is also used by Firefox for WebGL, but not WebGPU in either browser.

In my tests I also noted a flash of color sometimes appearing in the developer console window which I had open as usual.

An elderly MacBook works OK for Safari and Chrome (116 - it hadn't been used for a while) and Chrome 125.

aardgoose avatar May 29 '24 08:05 aardgoose

If the problem is in ANGLE, the Chromium bug tracker is definitely the right sport to report the issue.

Mugen87 avatar May 29 '24 09:05 Mugen87

@aardgoose Out of curiosity: Does the reproduction test case also fail on your affected systems? You should see a green plane in https://jsfiddle.net/47donLx0/

Mugen87 avatar May 29 '24 09:05 Mugen87

@Mugen87 Yes, I was just using your test case, I wasn't assuming my patches worked!

aardgoose avatar May 29 '24 10:05 aardgoose

This looks like it's related to, if not a duplicate of, #25353 which shows that rendering to 3d render targets fails in D3D backends (which is used in both reported platforms here). Unfortunately there's been no movement from Chromium in well over a year:

https://issues.chromium.org/issues/40890022

gkjohnson avatar May 29 '24 15:05 gkjohnson

@gkjohnson It does look very similar. As noted I saw screen corruption (flashes of color in the developer tools console panel.

aardgoose avatar May 29 '24 21:05 aardgoose

Thanks for mentioning https://github.com/mrdoob/three.js/issues/25353. Before filing a new issue at the Chromium bug tracker, it's probably better to bump the existing one with a new comment. I'll do that later.

Besides, it's not much but maybe it would help if more devs upvote the bug at the Chromium bug tracker. This can be done here:

image

Mugen87 avatar May 30 '24 08:05 Mugen87

WebGL failed as described above, using FF and Chrome with Intel integrated and external GPUs using D3D and Vulkan backends,

@aardgoose Someone from the Chromium team tested the fiddle with different systems with Vulkan backend and couldn't reproduce, see https://issues.chromium.org/issues/40890022#comment12. Do you mind responding at the bug tracker and share a Chrome GPU report as an attachment of an affected system using Vulkan?

Mugen87 avatar Jun 01 '24 11:06 Mugen87

@aardgoose Someone from the Chromium team tested the fiddle with different systems with Vulkan backend and couldn't reproduce, see https://issues.chromium.org/issues/40890022#comment12. Do you mind responding at the bug tracker and share a Chrome GPU report as an attachment of an affected system using Vulkan?

Two follow-up questions:

  1. Which systems are using Vulkan backends for WebGL? MacOS? Then I can test later on my MacBook at home and report for the Chromium team.

  2. Can I switch the rendering backend somehow in Chrome on Windows to make this work for now?

Thx

hubtub2 avatar Jun 03 '24 16:06 hubtub2

Which systems are using Vulkan backends for WebGL? MacOS?

AFAIK, mostly Linux systems. Recent Apple devices use Metal. You can check this by opening chrome://gpu/ and then look at the GL_RENDERER value of the report. On my system it says ANGLE (Apple, ANGLE Metal Renderer: Apple M2 Pro, Version 14.4.1 (Build 23E224)) which means it uses a Metal backend.

Can I switch the rendering backend somehow in Chrome on Windows to make this work for now?

You can force a backend when starting the browser via console. However, it is no lasting setting and the selected backend might not be supported on your system. For macOS, it looks like so using Chrome Canary.

Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --user-data-dir=/tmp/c1 --use-angle=vulkan

Mugen87 avatar Jun 07 '24 09:06 Mugen87