Created
January 13, 2026 09:04
-
-
Save unitycoder/55b8f4ad960773430656154794aff9ef to your computer and use it in GitHub Desktop.
How to take a screenshot with Unity WebGPU?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // https://discussions.unity.com/t/how-to-take-a-screenshot-with-unity-webgpu/1681498/2 | |
| using System.Runtime.InteropServices; | |
| using Unity.Collections; | |
| using UnityEngine; | |
| using UnityEngine.Rendering; | |
| public sealed class AsyncCapture : MonoBehaviour | |
| { | |
| // ProcessCapture is defined in ASyncCapture.jslib | |
| [DllImport("__Internal")] | |
| private static extern void ProcessCapture(byte[] pngPtr, int pngLength); | |
| int frameCount = 0; | |
| void Update() | |
| { | |
| // Capture on the 10th frame, an arbitrarily picked frame | |
| frameCount++; | |
| if (frameCount == 10) | |
| { | |
| var (w, h) = (Screen.width, Screen.height); | |
| var (scale, offs) = (new Vector2(1, -1), new Vector2(0, 1)); | |
| var grabRT = new RenderTexture(w, h, 0); | |
| var flipRT = new RenderTexture(w, h, 0); | |
| var rtFormat = grabRT.graphicsFormat; | |
| // Capture the screen to grabRT. This will be upside down, so we'll need to flip it. | |
| ScreenCapture.CaptureScreenshotIntoRenderTexture(grabRT); | |
| // Flip grabRT by blit'ing it to flipRT with a -1 y scale | |
| Graphics.Blit(grabRT, flipRT, scale, offs); // flip Y | |
| // Read the contents of flipRT to CPU memory. WebGPU does not support synchronous | |
| // readback, so we need to use async readback. | |
| AsyncGPUReadback.Request(flipRT, 0, TextureFormat.RGBA32, (req) => | |
| { | |
| // We don't need these textures anymore. | |
| DestroyImmediate(grabRT); | |
| DestroyImmediate(flipRT); | |
| // Get the image memory we just read | |
| var imageData = req.GetData<byte>().ToArray(); | |
| // Encode the image to a PNG | |
| byte[] pngData = ImageConversion.EncodeArrayToPNG(imageData, UnityEngine.Experimental.Rendering.GraphicsFormat.R8G8B8A8_UNorm, (uint)w, (uint)h); | |
| // Send the PNG data to JavaScript to do something with it | |
| ProcessCapture(pngData, pngData.Length); | |
| }); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| mergeInto(LibraryManager.library, { | |
| ProcessCapture: function(pngPtr, pngLength) { | |
| // Get the JS view of the Wasm memory | |
| const pngBytes = new Uint8Array(Module.HEAPU8.buffer, pngPtr, pngLength); | |
| // Create a PNG Blob for the png data | |
| const imageBlob = new Blob([pngBytes], { type: 'image/png' }); | |
| // Create an Object URL from the PNG blob | |
| const imageUrl = URL.createObjectURL(imageBlob); | |
| // Create an Image element to display the PNG Object URL and add it to the page | |
| const imageElement = document.createElement('img'); | |
| imageElement.src = imageUrl; | |
| document.body.appendChild(imageElement); | |
| } | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment