Move some scene settings into render request struct.

Reflections, shadows, and post-processing can be specified per render
request rather than per scene.

PiperOrigin-RevId: 915910030
Change-Id: I8ce773b42870aa76a2d8219347ca1cafaec1a97b
This commit is contained in:
Haroon Qureshi
2026-05-15 03:22:47 -07:00
committed by Copybara-Service
parent 0ad77f1ddf
commit 766f519576
9 changed files with 63 additions and 96 deletions
@@ -36,9 +36,6 @@ using filament::math::mat3f;
ImguiBridge::ImguiBridge(mjrfContext* ctx) : ctx_(ctx) {
mjrSceneParams params;
mjr_defaultSceneParams(&params);
params.enable_post_processing = false;
params.enable_reflections = false;
params.enable_shadows = false;
scene_ = CreateScene(ctx_, params);
}
@@ -16,6 +16,7 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <mujoco/mjmodel.h>
@@ -42,6 +43,7 @@ void MjrFilamentRenderer::Init(const mjModel* model) {
void MjrFilamentRenderer::Render(const mjrRect& viewport,
const mjvScene* scene) {
scene_bridge_->Update(viewport, scene);
std::memcpy(render_flags_, scene->flags, mjNRNDFLAG * sizeof(mjtByte));
// Update the UX renderable entity after processing the scene in case there
// are any elements in the scene which generate UX draw calls (e.g. labels).
if (mode_ != FrameBufferMode::OffScreen) {
@@ -52,15 +54,26 @@ void MjrFilamentRenderer::Render(const mjrRect& viewport,
mjrRenderRequest reqs[2];
mjr_defaultRenderRequest(&reqs[0]);
reqs[0].scene = scene_bridge_->GetScene();
reqs[0].draw_mode = scene_bridge_->GetDrawMode();
reqs[0].draw_mode = mjDRAW_MODE_COLOR;
if (render_flags_[mjRND_SEGMENT]) {
reqs[0].draw_mode = mjDRAW_MODE_SEGMENTATION;
} else if (render_flags_[mjRND_DEPTH]) {
reqs[0].draw_mode = mjDRAW_MODE_DEPTH;
}
reqs[0].camera = scene_bridge_->GetCamera();
reqs[0].viewport = viewport;
reqs[0].enable_shadows = render_flags_[mjRND_SHADOW];
reqs[0].enable_reflections = render_flags_[mjRND_REFLECTION];
mjr_defaultRenderRequest(&reqs[1]);
reqs[1].scene = imgui_bridge_->GetScene();
reqs[1].draw_mode = mjDRAW_MODE_COLOR;
reqs[1].camera = imgui_bridge_->GetCamera(viewport.width, viewport.height);
reqs[1].viewport = viewport;
reqs[1].enable_shadows = false;
reqs[1].enable_reflections = false;
reqs[1].enable_post_processing = false;
filament_context_->Render(reqs);
}
}
@@ -91,15 +104,25 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb,
mjr_defaultRenderRequest(&reqs[0]);
reqs[0].scene = scene_bridge_->GetScene();
reqs[0].draw_mode = scene_bridge_->GetDrawMode();
reqs[0].draw_mode = mjDRAW_MODE_COLOR;
if (render_flags_[mjRND_SEGMENT]) {
reqs[0].draw_mode = mjDRAW_MODE_SEGMENTATION;
} else if (render_flags_[mjRND_DEPTH]) {
reqs[0].draw_mode = mjDRAW_MODE_DEPTH;
}
reqs[0].camera = scene_bridge_->GetCamera();
reqs[0].viewport = viewport;
reqs[0].enable_shadows = render_flags_[mjRND_SHADOW];
reqs[0].enable_reflections = render_flags_[mjRND_REFLECTION];
mjr_defaultRenderRequest(&reqs[1]);
reqs[1].scene = imgui_bridge_->GetScene();
reqs[1].draw_mode = mjDRAW_MODE_COLOR;
reqs[1].camera = imgui_bridge_->GetCamera(viewport.width, viewport.height);
reqs[1].viewport = viewport;
reqs[1].enable_shadows = false;
reqs[1].enable_reflections = false;
reqs[1].enable_post_processing = false;
if (rgb) {
mjrRenderTargetConfig config;
@@ -20,6 +20,7 @@
#include <mujoco/mjmodel.h>
#include <mujoco/mjrender.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjvisualize.h>
#include "experimental/filament/compat/imgui_bridge.h"
#include "experimental/filament/compat/scene_bridge.h"
@@ -81,6 +82,7 @@ class MjrFilamentRenderer {
std::unique_ptr<SceneBridge> scene_bridge_;
std::unique_ptr<ImguiBridge> imgui_bridge_;
FrameBufferMode mode_ = FrameBufferMode::Window;
mjtByte render_flags_[mjNRNDFLAG];
};
} // namespace mujoco
@@ -261,16 +261,6 @@ mat4 CalculateClipFromWorld(const mjrRect& viewport, const mjrCamera& cam) {
}
void SceneBridge::Update(const mjrRect& viewport, const mjvScene* scene) {
mjrf_setSceneShadowsEnabled(scene_.get(), scene->flags[mjRND_SHADOW]);
mjrf_setSceneReflectionsEnabled(scene_.get(), scene->flags[mjRND_REFLECTION]);
if (scene->flags[mjRND_SEGMENT]) {
draw_mode_ = mjDRAW_MODE_SEGMENTATION;
} else if (scene->flags[mjRND_DEPTH]) {
draw_mode_ = mjDRAW_MODE_DEPTH;
} else {
draw_mode_ = mjDRAW_MODE_COLOR;
}
mjtNum hpos[3], hfwd[3];
float headpos[3], gazedir[3];
mjv_cameraInModel(hpos, hfwd, nullptr, scene);
@@ -356,6 +346,4 @@ mjrScene* SceneBridge::GetScene() const { return scene_.get(); }
mjrCamera SceneBridge::GetCamera() const { return camera_; }
mjrDrawMode SceneBridge::GetDrawMode() const { return draw_mode_; }
} // namespace mujoco
@@ -52,7 +52,6 @@ class SceneBridge {
// Returns the managed scene.
mjrScene* GetScene() const;
mjrCamera GetCamera() const;
mjrDrawMode GetDrawMode() const;
SceneBridge(const SceneBridge&) = delete;
SceneBridge& operator=(const SceneBridge&) = delete;
@@ -68,7 +67,6 @@ class SceneBridge {
mjrfContext* ctx_ = nullptr;
std::unique_ptr<ModelObjects> model_objects_;
mjrCamera camera_;
mjrDrawMode draw_mode_ = mjDRAW_MODE_COLOR;
DrawTextAtFn draw_text_callback_;
UniquePtr<mjrScene> scene_{nullptr, nullptr};
UniquePtr<mjrLight> fallback_ibl_{nullptr, nullptr};
@@ -153,16 +153,6 @@ SceneView::SceneView(filament::Engine* engine, const mjrSceneParams& params)
tm.create(fog);
tm.setTransform(tm.getInstance(fog),
mat4::rotation(filament::math::f::PI / 2, float3{-1, 0, 0}));
if (!params.enable_post_processing) {
DisablePostProcessing();
}
if (!params.enable_reflections) {
DisableReflections();
}
if (!params.enable_shadows) {
DisableShadows();
}
}
SceneView::~SceneView() {
@@ -241,6 +231,13 @@ void SceneView::Render(filament::Renderer* renderer, const mjrRenderRequest& req
mju_error("Invalid scene for SceneView::Render.");
}
if (request.enable_reflections) {
EnableReflections();
} else {
DisableReflections();
}
filament::Viewport viewport(request.viewport.left, request.viewport.bottom,
request.viewport.width, request.viewport.height);
for (auto& view : views_) {
@@ -255,10 +252,12 @@ void SceneView::Render(filament::Renderer* renderer, const mjrRenderRequest& req
}
filament::View* view = views_[static_cast<int>(request.draw_mode)];
view->setShadowingEnabled(request.enable_shadows);
view->setPostProcessingEnabled(request.enable_post_processing);
filament::MultiSampleAntiAliasingOptions options =
view->getMultiSampleAntiAliasingOptions();
RenderTarget* render_target = RenderTarget::downcast(request.target);
if (render_target) {
// We need to disable msaa in order to render to texture.
@@ -337,17 +336,12 @@ void SceneView::SetColorGradingOptions(const ColorGradingOptions& opts) {
color_grading_options_ = opts;
}
void SceneView::EnableShadows() {
views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(true);
}
void SceneView::DisableShadows() {
views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(false);
}
void SceneView::EnableReflections() {
reflections_enabled_ = true;
if (reflections_enabled_) {
return;
}
reflections_enabled_ = true;
for (int i = 0; i < reflectives_.size(); ++i) {
Renderable* renderable = reflectives_[i];
mjrMaterial material = renderable->GetMaterial();
@@ -357,6 +351,10 @@ void SceneView::EnableReflections() {
}
void SceneView::DisableReflections() {
if (!reflections_enabled_) {
return;
}
reflections_enabled_ = false;
for (Renderable* renderable : reflectives_) {
mjrMaterial material = renderable->GetMaterial();
@@ -365,14 +363,6 @@ void SceneView::DisableReflections() {
}
}
void SceneView::EnablePostProcessing() {
views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(true);
}
void SceneView::DisablePostProcessing() {
views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(false);
}
filament::View* SceneView::GetDefaultRenderView() {
return views_[mjDRAW_MODE_COLOR];
}
@@ -60,18 +60,6 @@ class SceneView : public mjrScene {
// Returns the filament Engine managing the scene.
filament::Engine* GetEngine() const { return engine_; }
// Enables/disables shadows for the default render view.
void EnableShadows();
void DisableShadows();
// Enables/disables reflections for the default render view.
void EnableReflections();
void DisableReflections();
// Enables/disables post processing for the default render view.
void EnablePostProcessing();
void DisablePostProcessing();
// Returns the underlying filament View that is used for normal rendering.
// Callers can update rendering settings (e.g. post processing) directly.
filament::View* GetDefaultRenderView();
@@ -92,6 +80,9 @@ class SceneView : public mjrScene {
}
private:
void EnableReflections();
void DisableReflections();
// Marks a renderable as reflective. Reflective renderables have to be
// rendered in their own passes to create the reflective texture.
void AddReflectiveRenderable(Renderable* renderable);
@@ -74,9 +74,6 @@ void mjr_defaultMeshData(mjrMeshData* data) {
void mjr_defaultSceneParams(mjrSceneParams* params) {
memset(params, 0, sizeof(mjrSceneParams));
params->enable_post_processing = true;
params->enable_reflections = true;
params->enable_shadows = true;
params->layer_mask = 0xff;
params->reflection_layer_mask = 0xff;
}
@@ -126,6 +123,9 @@ void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config) {
void mjr_defaultRenderRequest(mjrRenderRequest* request) {
memset(request, 0, sizeof(mjrRenderRequest));
request->enable_post_processing = true;
request->enable_reflections = true;
request->enable_shadows = true;
}
void mjr_defaultReadPixelsRequest(mjrReadPixelsRequest* request) {
@@ -317,22 +317,6 @@ void mjrf_setSceneSkybox(mjrScene* scene, const mjrTexture* texture) {
mujoco::Texture::downcast(texture));
}
void mjrf_setSceneShadowsEnabled(mjrScene* scene, mjtByte enabled) {
if (enabled) {
mujoco::SceneView::downcast(scene)->EnableShadows();
} else {
mujoco::SceneView::downcast(scene)->DisableShadows();
}
}
void mjrf_setSceneReflectionsEnabled(mjrScene* scene, mjtByte enabled) {
if (enabled) {
mujoco::SceneView::downcast(scene)->EnableReflections();
} else {
mujoco::SceneView::downcast(scene)->DisableReflections();
}
}
void mjrf_configureSceneFromModel(mjrScene* scene, const mjModel* model) {
mujoco::SceneView::downcast(scene)->Configure(model);
}
@@ -150,9 +150,6 @@ struct mjrRenderRequest {
// The camera from which to render the scene.
mjrCamera camera;
// The method (e.g. Color, Depth, Segmentation, etc.) to use for rendering.
mjrDrawMode draw_mode;
// The viewport into which to render the image.
mjrRect viewport;
@@ -160,6 +157,18 @@ struct mjrRenderRequest {
// will be rendered to the window (as previously configured in
// mjrFilamentConfig::native_window).
mjrRenderTarget* target;
// The method (e.g. Color, Depth, Segmentation, etc.) to use for rendering.
mjrDrawMode draw_mode;
// Whether or not to enable post processing; enabled by default.
mjtByte enable_post_processing;
// Whether or not to enable reflections; enabled by default.
mjtByte enable_reflections;
// Whether or not to enable shadows; enabled by default.
mjtByte enable_shadows;
};
// Initializes the mjrRenderRequest to default values.
@@ -449,15 +458,6 @@ void mjrf_destroyMesh(mjrMesh* mesh);
// Configuration parameters for a Scene.
struct mjrSceneParams {
// Whether or not to enable post processing; enabled by default.
mjtByte enable_post_processing;
// Whether or not to enable reflections; enabled by default.
mjtByte enable_reflections;
// Whether or not to enable shadows; enabled by default.
mjtByte enable_shadows;
// This mask, in conjunction with the layer mask in the Renderable, determines
// which Renderables to render within the Scene.
uint8_t layer_mask;
@@ -490,12 +490,6 @@ void mjrf_removeRenderableFromScene(mjrScene* scene, mjrRenderable* renderable);
// Sets the skybox (cube texture) for the scene.
void mjrf_setSceneSkybox(mjrScene* scene, const mjrTexture* texture);
// Enables (or disables) shadows in the scene.
void mjrf_setSceneShadowsEnabled(mjrScene* scene, mjtByte enabled);
// Enables (or disables) reflections in the scene.
void mjrf_setSceneReflectionsEnabled(mjrScene* scene, mjtByte enabled);
// Configures the scene based on the parameters in an mjModel.
void mjrf_configureSceneFromModel(mjrScene* scene, const mjModel* model);