From d913e0b1e9e4eaf67c27a0148062bf0f6100211a Mon Sep 17 00:00:00 2001 From: Haroon Qureshi Date: Wed, 15 Apr 2026 01:39:25 -0700 Subject: [PATCH] Add ReadPixels function to RenderTarget. PiperOrigin-RevId: 900017779 Change-Id: I0632b66124632558ea19157e4ca319e4b0d10617 --- .../filament/filament/filament_context.cc | 28 ++----------- .../filament/filament/render_target.cc | 40 ++++++++++++++++++- .../filament/filament/render_target.h | 11 +++-- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/experimental/filament/filament/filament_context.cc b/src/experimental/filament/filament/filament_context.cc index cbc79c24..c01a95b2 100644 --- a/src/experimental/filament/filament/filament_context.cc +++ b/src/experimental/filament/filament/filament_context.cc @@ -209,28 +209,6 @@ void FilamentContext::DestroyRenderTargets() { color_target_.reset(); } -static void ReadColorPixels(filament::Renderer* renderer, - RenderTarget* target, mjrRect viewport, - unsigned char* buffer, size_t num_bytes) { - filament::backend::PixelBufferDescriptor descriptor( - buffer, num_bytes, filament::backend::PixelDataFormat::RGB, - filament::backend::PixelDataType::UBYTE); - renderer->readPixels(target->GetFilamentRenderTarget(), viewport.left, - viewport.bottom, viewport.width, viewport.height, - std::move(descriptor)); -} - -static void ReadDepthPixels(filament::Renderer* renderer, - RenderTarget* target, mjrRect viewport, - float* buffer, size_t num_bytes) { - filament::backend::PixelBufferDescriptor descriptor( - buffer, num_bytes, filament::backend::PixelDataFormat::R, - filament::backend::PixelDataType::FLOAT); - renderer->readPixels(target->GetFilamentRenderTarget(), viewport.left, - viewport.bottom, viewport.width, viewport.height, - std::move(descriptor)); -} - void FilamentContext::ReadPixels(mjrRect viewport, unsigned char* rgb, float* depth) { if (scene_swap_chain_target_ != kOffscreenSwapChain) { @@ -261,7 +239,7 @@ void FilamentContext::ReadPixels(mjrRect viewport, unsigned char* rgb, } const size_t num_bytes = viewport.width * viewport.height * 3; - ReadColorPixels(renderer_, color_target_.get(), viewport, rgb, num_bytes); + color_target_->ReadColorPixels(renderer_, rgb, num_bytes); renderer_->endFrame(); } @@ -277,8 +255,8 @@ void FilamentContext::ReadPixels(mjrRect viewport, unsigned char* rgb, scene_view_->Render(renderer_, request); const size_t num_bytes = viewport.width * viewport.height * sizeof(float); - ReadDepthPixels(renderer_, depth_target_.get(), viewport, depth, - num_bytes); + depth_target_->ReadColorPixels( + renderer_, reinterpret_cast(depth), num_bytes); renderer_->endFrame(); } diff --git a/src/experimental/filament/filament/render_target.cc b/src/experimental/filament/filament/render_target.cc index dec68a82..eb2d3490 100644 --- a/src/experimental/filament/filament/render_target.cc +++ b/src/experimental/filament/filament/render_target.cc @@ -14,18 +14,25 @@ #include "experimental/filament/filament/render_target.h" +#include +#include #include +#include +#include +#include #include +#include #include #include +#include #include "experimental/filament/filament/texture.h" namespace mujoco { RenderTarget::RenderTarget(filament::Engine* engine, - RenderTargetTextureType color, - RenderTargetTextureType depth) + RenderTargetTextureType color, + RenderTargetTextureType depth) : engine_(engine), color_type_(color), depth_type_(depth) {} RenderTarget::~RenderTarget() noexcept { @@ -53,6 +60,35 @@ void RenderTarget::Prepare(int width, int height) { render_target_ = builder.build(*engine_); } +void RenderTarget::ReadColorPixels(filament::Renderer* renderer, uint8_t* bytes, + size_t num_bytes) { + filament::backend::PixelDataFormat format; + filament::backend::PixelDataType type; + size_t expected_num_bytes = 0; + switch (color_type_) { + case RenderTargetTextureType::kColor: + format = filament::backend::PixelDataFormat::RGB; + type = filament::backend::PixelDataType::UBYTE; + expected_num_bytes = width_ * height_ * 3; + break; + case RenderTargetTextureType::kDepthColor: + format = filament::backend::PixelDataFormat::R; + type = filament::backend::PixelDataType::FLOAT; + expected_num_bytes = width_ * height_ * sizeof(float); + break; + default: + mju_error("Unsupported pixel format: %d", color_type_); + return; + } + if (num_bytes != expected_num_bytes) { + mju_error("Invalid number of bytes."); + return; + } + + filament::backend::PixelBufferDescriptor desc(bytes, num_bytes, format, type); + renderer->readPixels(render_target_, 0, 0, width_, height_, std::move(desc)); +} + void RenderTarget::Destroy() { if (render_target_) { engine_->destroy(render_target_); diff --git a/src/experimental/filament/filament/render_target.h b/src/experimental/filament/filament/render_target.h index 3e5530cc..ee033de9 100644 --- a/src/experimental/filament/filament/render_target.h +++ b/src/experimental/filament/filament/render_target.h @@ -15,6 +15,8 @@ #ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDER_TARGET_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDER_TARGET_H_ +#include +#include #include #include @@ -28,9 +30,8 @@ class RenderTarget { public: // Defines the types of textures to create for the color and depth // attachments. - RenderTarget(filament::Engine* engine, - RenderTargetTextureType color, - RenderTargetTextureType depth); + RenderTarget(filament::Engine* engine, RenderTargetTextureType color, + RenderTargetTextureType depth); ~RenderTarget() noexcept; RenderTarget(const RenderTarget&) = delete; @@ -40,6 +41,10 @@ class RenderTarget { // the last time the render target was prepared. void Prepare(int width, int height); + // Reads the pixels from the render target texture. + void ReadColorPixels(filament::Renderer* renderer, uint8_t* bytes, + size_t num_bytes); + // Returns the color texture. Texture* GetColorTexture() const;