HOW TO...Get screenshot/texture from 2d Scene Capture Comp at runtime - C++

It took me a while but here is some code to get a still image as a texture at runtime (as of UE5.03). Note that I have made the function async to avoid GPU bottlenecks and because I don’t need the resulting texture immediately. Consider trade-offs when using:

	AsyncTask(ENamedThreads::GameThread, [this, Camera]()
		{
                        // "Camera" = 2D Scene Capture Component
			if (Camera)
			{
                                // define image resolution
				Camera->TextureTarget = UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(this, UCanvasRenderTarget2D::StaticClass(), 512, 512);
				Camera->CaptureScene();
				// Creates Texture2D to store TextureRenderTarget content
				UTexture2D* Texture = UTexture2D::CreateTransient(Camera->TextureTarget->SizeX, Camera->TextureTarget->SizeY);
#if WITH_EDITORONLY_DATA
				Texture->MipGenSettings = TMGS_NoMipmaps;
#endif
				Texture->SRGB = false;
				Texture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;

				// Read the pixels from the RenderTarget and store them in a FColor array
				TArray<FColor> SurfData;
				FRenderTarget* RenderTarget = Camera->TextureTarget->GameThread_GetRenderTargetResource();
				RenderTarget->ReadPixels(SurfData);
				// some alpha channels are set to 0 by default, make sure all pixels opaque
				for (auto& Pixel : SurfData)
				{
					Pixel.A = 255.f;
				}

				// Lock and copies the data between the textures
				void* TextureData = Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
				const int32 TextureDataSize = SurfData.Num() * 4;
				FMemory::Memcpy(TextureData, SurfData.GetData(), TextureDataSize);
				Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
				// Apply Texture changes to GPU memory
				Texture->UpdateResource();
				// Do something with texture
			}
		});

Hope this saves someone a few hours of research :slight_smile:

2 Likes