Adapt reflection and screenshot components to WebGPURenderer#5848
Adapt reflection and screenshot components to WebGPURenderer#5848vincentfretin wants to merge 3 commits into
Conversation
- Use CubeRenderTarget with WebGPURenderer (WebGLCubeRenderTarget is not exported by the three.webgpu.js build), selected at runtime like the renderer implementation in a-scene. This also removes a webpack warning when building with WEBGPU=true. - WebGPURenderer does not support RawShaderMaterial; the equirectangular cubemap-to-equirect projection is implemented with TSL nodes when THREE.TSL is available. - WebGPURenderer only supports asynchronous pixels read back, use readRenderTargetPixelsAsync when readRenderTargetPixels is not available. getCanvas() returns a Promise resolving to the canvas with WebGPURenderer; it still returns the canvas synchronously with WebGLRenderer. - Use RGBAFormat instead of RGBFormat for the cube render target; RGBFormat is not color-renderable with the WebGL 2 backend of WebGPURenderer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Testing help wanted: on this machine I could only verify gh pr checkout 5848
# or without the GitHub CLI:
# git fetch https://github.com/vincentfretin/aframe.git webgpu-reflection-screenshot && git checkout FETCH_HEAD
npm ci
npm run dist
npm run start:webgpuThen open AFRAME.scenes[0].renderer.backend.isWebGPUBackend // should be trueThings to verify:
|
| @@ -57,13 +62,18 @@ export var Component = registerComponent('screenshot', { | |||
| if (this.canvas) { return; } | |||
| var gl = el.renderer.getContext(); | |||
There was a problem hiding this comment.
Nitpick: the name gl is no longer accurate as it might be a GPUCanvasContext. Maybe ctx would be an apt alternative covering both?
| fragmentShader: FRAGMENT_SHADER, | ||
| side: THREE.DoubleSide | ||
| }); | ||
| this.cubeMapSize = gl.getParameter ? gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE) : 2048; |
There was a problem hiding this comment.
Wasn't immediately clear why 2048 would be a safe, though it appears that maxTextureDimension2D (which applies for cube map faces AFAICT) is at least 8192 and 4096 in the recent compatibility mode. Since the code later on clamps it to 2048 either way, it's fine using that value.
Ideally we'd query maxTextureDimension2D, or at the very least add a comment describing why this is safe to do.
There was a problem hiding this comment.
Done in 2a9ab7d: it now queries maxTextureDimension2D from the device limits (with a 2048 fallback if the device is somehow not available yet).
| if (this.cubeTextureNode) { | ||
| this.cubeTextureNode.value = cubeCamera.renderTarget.texture; | ||
| } else { | ||
| this.quad.material.uniforms.map.value = cubeCamera.renderTarget.texture; | ||
| } |
There was a problem hiding this comment.
Since both the uniform and TextureNode have the texture in a .value property, we can store this.cubeTextureUniform for both cases (TSL and ShaderMaterial). In fact TSL.uniformTexture is the same as TSL.texture so should be fine to change cubeTextureNode to cubeTextureUniform semantically.
There was a problem hiding this comment.
Nice, done in 2a9ab7d: this.cubeTextureUniform is now set in both branches (the map uniform for ShaderMaterial and the cubeTexture node for TSL) and setCapture has a single .value assignment.
It should be possible to enable WebGPU on Linux on most systems, see: https://github.com/gpuweb/gpuweb/wiki/Implementation-Status#chromium-chrome-edge-etc In any case, a quick test shows that both the Edit: opened a PR with a fix: #5849
The |
|
Oh I completely missed that it was working now on Linux behind additional cli flags, thank you! |
…mments - Pixels read back from WebGL are bottom-up but top-down with the WebGPU backend of WebGPURenderer, so the vertical flip is now based on the renderer coordinate system. The equirectangular projection quad renders vertically inverted so it needs the opposite flip of the perspective projection. Verified on an actual WebGPU backend (NVIDIA, Vulkan), on the WebGL 2 fallback backend and on WebGLRenderer. - Query maxTextureDimension2D from the WebGPU device limits for cubeMapSize instead of hardcoding 2048. - Rename gl to ctx in setup() since it can be a GPUCanvasContext. - Store this.cubeTextureUniform for both the ShaderMaterial uniform and the TSL cubeTexture node, both expose the texture as a value property. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@mrxz Thanks a lot for testing and for the Linux flags pointer! I got the actual WebGPU backend working locally (NVIDIA, Vulkan) with The cause: pixels read back from WebGL are bottom-up but top-down with the WebGPU backend, and the equirectangular projection quad renders vertically inverted so it needs the opposite flip of the perspective projection. The vertical flip is now based on Verified on the three configurations by probing pixels of the resulting canvas on a scene with distinct sky/box/ground colors:
Review comments also addressed in the same commit. And thanks for tracking down the keyboard shortcut regression separately in #5849. |
TSL and MeshBasicNodeMaterial only exist in the three.js build with WebGPURenderer, access them so that Webpack can't statically determine the export used, like for CubeRenderTarget. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ab0734d to
f445281
Compare
Makes the
reflectionandscreenshotcomponents work withWebGPURenderer(three.webgpu.js build, see #5749 for context).Changes
WebGLCubeRenderTargetis not exported by the three.webgpu.js build, which usesCubeRenderTargetinstead. Both components now select the class at runtime with the same trick a-scene uses to select the renderer implementation, so webpack can't statically resolve the export. This also removes theWebGLCubeRenderTargetwebpack warning when building withWEBGPU=true.THREE.CubeCameraworks unchanged with either target.WebGPURendererdoes not supportRawShaderMaterial/ShaderMaterial(not in its node library). WhenTHREE.TSLis available, the cubemap-to-equirectangular projection is built as aMeshBasicNodeMaterialwith TSL nodes implementing the same longitude/latitude math as the GLSL shaders; the cube texture is swapped per capture through the texture node's.value.WebGPURendereronly supports asynchronous read back.renderCaptureusesreadRenderTargetPixelsAsyncwhenreadRenderTargetPixelsis not available.getCanvas()still returns the canvas synchronously withWebGLRenderer(no breaking change) and returns aPromiseresolving to the canvas withWebGPURenderer(documented inscreenshot.md).capture()works on both.RGBFormat, which is not color-renderable with the WebGL 2 backend ofWebGPURenderer(incomplete framebuffer, black capture). Switched toRGBAFormat; the projection outputs alpha 1 and the readback path already assumed 4 bytes per pixel.Verification
Tested with a scene with distinct sky/box/ground colors on both builds (
npm run devandnpm run start:webgpu) driving headless Chrome, probing pixels of the resulting canvas:WebGLRendererand onWebGPURenderer(WebGL 2 fallback backend — no WebGPU adapters on Linux Chrome).reflectioncomponent sets a live cube texture asscene.environmenton both renderers without errors.Note: the actual WebGPU backend readback couldn't be tested on Linux; worth a quick check of equirect orientation in a desktop Chrome with WebGPU support.
ar-hit-test.jsuses the samereadRenderTargetPixelspattern but is WebXR-only, so it's left untouched until WebXR support lands forWebGPURenderer.🤖 Generated with Claude Code