readRenderTargetPixels() works for WebGLRenderTarget but is all 0 for WebGL3DRenderTarget
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:
- First run as is and check the output on the console: the buffer contains 0,0,0,255
- Now go to line 66 and enable the line with WebGLRenderTarget and disable the line with WebGL3DRenderTarget
- 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
An alternative cause would be that RTT 3D does not work - but I do not see a reason for it.
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):
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.
Thank you for testing. The fiddle imports already the current revision 164, see 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 :-(
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?
So I tried on 3 browsers on 2 systems - the output is consistent:
Firefox Notebook:
Chrome Notebook:
Firefox Workstation:
Chrome Workstation:
Edge Workstation:
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.
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.
The render window is black, both computers, Chrome and Firefox.
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:
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.
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...
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?
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.
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.
If the problem is in ANGLE, the Chromium bug tracker is definitely the right sport to report the issue.
@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 Yes, I was just using your test case, I wasn't assuming my patches worked!
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 It does look very similar. As noted I saw screen corruption (flashes of color in the developer tools console panel.
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:
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?
@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:
-
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.
-
Can I switch the rendering backend somehow in Chrome on Windows to make this work for now?
Thx
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