Fix dependency between FilamentContext and SceneView.

Removes the DoRender and DoReadPixels functions which allowed
FilamentContext to "call" SceneView functions even though
SceneView depended on FilamentContext.

Adds a mjrf_setClearColor function so that we no longer rely
on SceneView setting the clear color.

PiperOrigin-RevId: 914253362
Change-Id: I33c1cc9dfc7cb2f4c3cc855a600cccb0c54ae31c
This commit is contained in:
Haroon Qureshi
2026-05-12 06:37:09 -07:00
committed by Copybara-Service
parent 3f3ff85a59
commit 58abf3d4ae
10 changed files with 60 additions and 89 deletions
@@ -88,6 +88,10 @@ SceneBridge::SceneBridge(mjrfContext* ctx, const mjModel* model)
mjrf_configureSceneFromModel(scene_.get(), model);
auto clear_color = ReadElement(model, "filament.clearColor",
filament::math::float4(0, 0, 0, 1));
mjrf_setClearColor(ctx_, &clear_color[0]);
default_shadow_map_size_ = ReadElement(
model, "filament.shadows.map_size", default_shadow_map_size_);
default_vsm_blur_width_ = ReadElement(
@@ -36,16 +36,12 @@
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/filament_platform_factory.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/render_target.h"
#include "experimental/filament/filament/scene_view.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco {
// Forward declarations of functions defined in scene_view.cc to prevent
// circular dependencies.
void DoRender(filament::Renderer* renderer, const mjrRenderRequest& request);
void DoReadPixels(filament::Renderer* renderer, const mjrRenderRequest& request,
const mjrReadPixelsRequest& read_request);
FilamentContext::FilamentContext(const mjrFilamentConfig* config)
: config_(*config) {
FilamentPlatformSetup setup = CreateFilamentPlatform(config_);
@@ -127,7 +123,8 @@ mjrFrameHandle FilamentContext::Render(
break;
}
if (render_began) {
DoRender(renderer_, request);
SceneView* scene_view = SceneView::downcast(request.scene);
scene_view->Render(renderer_, request);
}
} else {
if (read_requests.empty()) {
@@ -147,8 +144,11 @@ mjrFrameHandle FilamentContext::Render(
break;
}
if (render_began) {
DoRender(renderer_, request);
DoReadPixels(renderer_, request, read_request);
SceneView* scene_view = SceneView::downcast(request.scene);
scene_view->Render(renderer_, request);
RenderTarget* render_target = RenderTarget::downcast(request.target);
render_target->ReadColorPixels(renderer_, (uint8_t*)read_request.output,
read_request.num_bytes);
}
}
}
+2 -3
View File
@@ -26,7 +26,6 @@
#include <utils/EntityManager.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament_util.h"
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h"
@@ -35,8 +34,8 @@ namespace mujoco {
using filament::math::float3;
using filament::math::mat3f;
Light::Light(FilamentContext* ctx, const mjrLightParams& params)
: engine_(ctx->GetEngine()), params_(params) {
Light::Light(filament::Engine* engine, const mjrLightParams& params)
: engine_(engine), params_(params) {
// Filament treats image-based lights (IBLs) as separate objects (i.e.
// filament::IndirectLight) and so we need to handle IBLs specially.
if (params.type == mjLIGHT_IMAGE) {
+1 -2
View File
@@ -20,7 +20,6 @@
#include <math/vec3.h>
#include <utils/Entity.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco {
@@ -29,7 +28,7 @@ namespace mujoco {
// IndirectLight.
class Light : public mjrLight {
public:
Light(FilamentContext* ctx, const mjrLightParams& params);
Light(filament::Engine* engine, const mjrLightParams& params);
~Light() noexcept;
Light(const Light&) = delete;
@@ -31,7 +31,6 @@
#include <mujoco/mujoco.h>
#include "experimental/filament/filament_util.h"
#include "experimental/filament/filament/builtins.h"
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/mesh.h"
#include "experimental/filament/filament/object_manager.h"
@@ -49,8 +48,10 @@ using filament::math::mat4f;
static constexpr float kArrowScale = 1.f / 6.f;
static constexpr float kArrowHeadSize = 1.75f;
Renderable::Renderable(FilamentContext* ctx, const mjrRenderableParams& params)
: object_mgr_(ctx->GetObjectManager()), params_(params) {
Renderable::Renderable(filament::Engine* engine,
const mjrRenderableParams& params,
ObjectManager* object_mgr)
: object_mgr_(object_mgr), params_(params) {
mjr_defaultMaterial(&material_);
}
@@ -25,7 +25,6 @@
#include <utils/Entity.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament_util.h"
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/mesh.h"
#include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/render_context_filament.h"
@@ -39,7 +38,8 @@ namespace mujoco {
// on the surface).
class Renderable : public mjrRenderable {
public:
Renderable(FilamentContext* ctx, const mjrRenderableParams& params);
Renderable(filament::Engine* engine, const mjrRenderableParams& params,
ObjectManager* object_mgr);
~Renderable() noexcept;
Renderable(const Renderable&) = delete;
@@ -42,7 +42,6 @@
#include <mujoco/mujoco.h>
#include "experimental/filament/filament_util.h"
#include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/render_target.h"
#include "experimental/filament/filament/renderable.h"
@@ -122,9 +121,8 @@ static void SetupReflectionCamera(const mat4& surface_xform,
reflection_camera->setCustomProjection(oblique, near, far);
}
SceneView::SceneView(FilamentContext* ctx, const mjrSceneParams& params)
: ctx_(ctx) {
filament::Engine* engine = ctx_->GetEngine();
SceneView::SceneView(filament::Engine* engine, const mjrSceneParams& params)
: engine_(engine) {
scene_ = engine->createScene();
camera_ = engine->createCamera(utils::EntityManager::get().create());
reflect_camera_ = engine->createCamera(utils::EntityManager::get().create());
@@ -168,10 +166,9 @@ SceneView::SceneView(FilamentContext* ctx, const mjrSceneParams& params)
}
SceneView::~SceneView() {
filament::Engine* engine = ctx_->GetEngine();
if (skybox_) {
scene_->setSkybox(nullptr);
engine->destroy(skybox_);
engine_->destroy(skybox_);
}
for (auto& light : lights_) {
light->RemoveFromScene(scene_);
@@ -182,15 +179,15 @@ SceneView::~SceneView() {
lights_.clear();
renderables_.clear();
reflect_targets_.clear();
engine->destroyCameraComponent(reflect_camera_->getEntity());
engine->destroy(reflect_view_);
engine->destroyCameraComponent(camera_->getEntity());
engine_->destroyCameraComponent(reflect_camera_->getEntity());
engine_->destroy(reflect_view_);
engine_->destroyCameraComponent(camera_->getEntity());
if (color_grading_) {
engine->destroy(color_grading_);
engine_->destroy(color_grading_);
}
engine->destroy(scene_);
engine_->destroy(scene_);
for (auto& view : views_) {
engine->destroy(view);
engine_->destroy(view);
}
}
@@ -239,8 +236,11 @@ void SceneView::SetSkybox(const Texture* skybox_texture) {
}
}
void SceneView::Render(filament::Renderer* renderer,
const RenderRequest& request) {
void SceneView::Render(filament::Renderer* renderer, const mjrRenderRequest& request) {
if (request.scene != this) {
mju_error("Invalid scene for SceneView::Render.");
}
filament::Viewport viewport(request.viewport.left, request.viewport.bottom,
request.viewport.width, request.viewport.height);
for (auto& view : views_) {
@@ -258,8 +258,8 @@ void SceneView::Render(filament::Renderer* renderer,
filament::MultiSampleAntiAliasingOptions options =
view->getMultiSampleAntiAliasingOptions();
filament::RenderTarget* render_target =
request.target ? request.target->GetFilamentRenderTarget() : nullptr;
RenderTarget* render_target = RenderTarget::downcast(request.target);
if (render_target) {
// We need to disable msaa in order to render to texture.
view->setMultiSampleAntiAliasingOptions({.enabled = false});
@@ -287,7 +287,8 @@ void SceneView::Render(filament::Renderer* renderer,
}
}
view->setRenderTarget(render_target);
view->setRenderTarget(render_target ? render_target->GetFilamentRenderTarget()
: nullptr);
renderer->render(view);
view->setRenderTarget(nullptr);
@@ -308,8 +309,7 @@ void SceneView::AddReflectiveRenderable(Renderable* renderable) {
config.color_format = mjPIXEL_FORMAT_RGBA8;
config.depth_format = mjPIXEL_FORMAT_DEPTH32F;
reflect_targets_.push_back(
std::make_unique<RenderTarget>(ctx_->GetEngine(), config));
reflect_targets_.push_back(std::make_unique<RenderTarget>(engine_, config));
}
// Prepare a render target for the reflective renderable.
@@ -382,9 +382,6 @@ ColorGradingOptions SceneView::GetColorGradingOptions() const {
}
void SceneView::Configure(const mjModel* model) {
ctx_->SetClearColor(ReadElement(model, "filament.clearColor",
filament::math::float4(0, 0, 0, 1)));
filament::View* view = views_[mjDRAW_MODE_COLOR];
auto cg = color_grading_options_;
@@ -483,30 +480,4 @@ void SceneView::Configure(const mjModel* model) {
bloom.levels = ReadElement(model, "filament.bloom.levels", bloom.levels);
view->setBloomOptions(bloom);
}
void DoRender(filament::Renderer* renderer, const mjrRenderRequest& request) {
SceneView::RenderRequest scene_view_request;
scene_view_request.draw_mode = request.draw_mode;
scene_view_request.viewport = request.viewport;
scene_view_request.camera = request.camera;
SceneView* scene_view = SceneView::downcast(request.scene);
scene_view->Render(renderer, scene_view_request);
}
void DoReadPixels(filament::Renderer* renderer,
const mjrRenderRequest& request,
const mjrReadPixelsRequest& read_request) {
RenderTarget* render_target = RenderTarget::downcast(request.target);
SceneView::RenderRequest scene_view_request;
scene_view_request.draw_mode = request.draw_mode;
scene_view_request.viewport = request.viewport;
scene_view_request.camera = request.camera;
scene_view_request.target = render_target;
SceneView* scene_view = SceneView::downcast(request.scene);
scene_view->Render(renderer, scene_view_request);
render_target->ReadColorPixels(renderer, (uint8_t*)read_request.output,
read_request.num_bytes);
}
} // namespace mujoco
@@ -27,7 +27,6 @@
#include <filament/View.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/render_target.h"
@@ -43,7 +42,7 @@ namespace mujoco {
// (e.g. normal, depth, segmentation, etc.) as well as reflective surfaces.
class SceneView : public mjrScene {
public:
SceneView(FilamentContext* ctx, const mjrSceneParams& params);
SceneView(filament::Engine* engine, const mjrSceneParams& params);
~SceneView();
SceneView(const SceneView&) = delete;
@@ -56,23 +55,10 @@ class SceneView : public mjrScene {
void RemoveFromScene(Renderable* renderable);
void SetSkybox(const Texture* skybox_texture);
// Parameters for rendering the scene.
struct RenderRequest {
// The draw mode (e.g. normal, depth, segmentation) to render.
mjrDrawMode draw_mode = mjDRAW_MODE_COLOR;
// The target viewport for the rendered image.
mjrRect viewport;
// The camera from which to render the scene.
mjrCamera camera;
// An optional render target into which the scene will be rendered.
RenderTarget* target = nullptr;
};
// Renders the scene.
void Render(filament::Renderer* renderer, const RenderRequest& request);
void Render(filament::Renderer* renderer, const mjrRenderRequest& request);
// Returns the filament Engine managing the scene.
filament::Engine* GetEngine() const { return ctx_->GetEngine(); }
filament::Engine* GetEngine() const { return engine_; }
// Enables/disables shadows for the default render view.
void EnableShadows();
@@ -110,7 +96,7 @@ class SceneView : public mjrScene {
// rendered in their own passes to create the reflective texture.
void AddReflectiveRenderable(Renderable* renderable);
FilamentContext* ctx_ = nullptr;
filament::Engine* engine_ = nullptr;
filament::Scene* scene_ = nullptr;
filament::Camera* camera_ = nullptr;
filament::ColorGrading* color_grading_ = nullptr;
@@ -162,7 +162,8 @@ mjrMesh* mjrf_createMesh(mjrfContext* ctx, const mjrMeshData* data) {
void mjrf_destroyMesh(mjrMesh* mesh) { delete mujoco::Mesh::downcast(mesh); }
mjrScene* mjrf_createScene(mjrfContext* ctx, const mjrSceneParams* params) {
return new mujoco::SceneView(mujoco::FilamentContext::downcast(ctx), *params);
return new mujoco::SceneView(
mujoco::FilamentContext::downcast(ctx)->GetEngine(), *params);
}
void mjrf_destroyScene(mjrScene* scene) {
@@ -170,7 +171,8 @@ void mjrf_destroyScene(mjrScene* scene) {
}
mjrLight* mjrf_createLight(mjrfContext* ctx, const mjrLightParams* params) {
return new mujoco::Light(mujoco::FilamentContext::downcast(ctx), *params);
return new mujoco::Light(mujoco::FilamentContext::downcast(ctx)->GetEngine(),
*params);
}
void mjrf_destroyLight(mjrLight* light) {
@@ -179,8 +181,9 @@ void mjrf_destroyLight(mjrLight* light) {
mjrRenderable* mjrf_createRenderable(mjrfContext* ctx,
const mjrRenderableParams* params) {
return new mujoco::Renderable(mujoco::FilamentContext::downcast(ctx),
*params);
return new mujoco::Renderable(
mujoco::FilamentContext::downcast(ctx)->GetEngine(), *params,
mujoco::FilamentContext::downcast(ctx)->GetObjectManager());
}
void mjrf_destroyRenderable(mjrRenderable* renderable) {
@@ -346,6 +349,11 @@ void mjrf_waitForFrame(mjrfContext* ctx, mjrFrameHandle frame) {
mujoco::FilamentContext::downcast(ctx)->WaitForFrame(frame);
}
void mjrf_setClearColor(mjrfContext* ctx, const float color[3]) {
mujoco::FilamentContext::downcast(ctx)->SetClearColor(
{color[0], color[1], color[2], 1.0f});
}
void mjrf_getFrameStats(mjrfContext* ctx, mjrFrameHandle frame,
mjrFrameStats* stats_out) {
mujoco::FilamentContext::downcast(ctx)->GetFrameStats(frame, stats_out);
@@ -211,6 +211,9 @@ mjrFrameHandle mjrf_render(mjrfContext* ctx, const mjrRenderRequest* req,
// triggering any callbacks as needed.
void mjrf_waitForFrame(mjrfContext* ctx, mjrFrameHandle frame);
// Sets the clear color for the renderer.
void mjrf_setClearColor(mjrfContext* ctx, const float color[3]);
// Information about a single frame of rendering.
struct mjrFrameStats {
// The frame rate of the renderer, in frames per second.