Planes should not receive shadows when rendered from behind.

Also refactors Renderables a bit to allow for additional use-cases.

PiperOrigin-RevId: 885527587
Change-Id: I4b17e097256de0356151a6d087bc01f11e3071b7
This commit is contained in:
Haroon Qureshi
2026-03-18 05:04:06 -07:00
committed by Copybara-Service
parent 3f77daa27a
commit b0c48ba846
4 changed files with 74 additions and 47 deletions
@@ -88,7 +88,8 @@ static bool IsBehind(const mjtNum* headpos, const float* pos, const float* mat)
Drawable::Drawable(ObjectManager* object_mgr, const mjvGeom& geom) Drawable::Drawable(ObjectManager* object_mgr, const mjvGeom& geom)
: material_(object_mgr), renderables_(object_mgr->GetEngine()) { : material_(object_mgr), renderables_(object_mgr->GetEngine()) {
if (geom.category == mjCAT_DECOR) { if (geom.category == mjCAT_DECOR) {
renderables_.DisableShadows(); renderables_.SetCastShadows(false);
renderables_.SetReceiveShadows(false);
} }
switch ((mjtGeom)geom.type) { switch ((mjtGeom)geom.type) {
@@ -346,8 +347,13 @@ void Drawable::UpdateMaterial(const mjvGeom& geom, bool use_segid_color,
const mjModel* model = object_mgr->GetModel(); const mjModel* model = object_mgr->GetModel();
float4 color = ReadFloat4(geom.rgba); float4 color = ReadFloat4(geom.rgba);
if (geom.type == mjGEOM_PLANE && IsBehind(headpos, geom.pos, geom.mat)) { if (geom.type == mjGEOM_PLANE) {
color[3] *= 0.3; if (IsBehind(headpos, geom.pos, geom.mat)) {
color[3] *= 0.3;
renderables_.SetReceiveShadows(false);
} else {
renderables_.SetReceiveShadows(true);
}
} }
Material::Textures textures; Material::Textures textures;
@@ -51,7 +51,6 @@ class Drawable {
// beginFrame/endFrame. // beginFrame/endFrame.
void SetDrawMode(Material::DrawMode mode); void SetDrawMode(Material::DrawMode mode);
private: private:
void AddMesh(int data_id); void AddMesh(int data_id);
void AddHeightField(int hfield_id); void AddHeightField(int hfield_id);
@@ -14,6 +14,7 @@
#include "experimental/filament/filament/renderables.h" #include "experimental/filament/filament/renderables.h"
#include <cstdint>
#include <optional> #include <optional>
#include <filament/Engine.h> #include <filament/Engine.h>
@@ -107,8 +108,9 @@ utils::Entity Renderables::CreateEntity(const FilamentBuffers& buffers) {
builder.boundingBox(buffers.bounds) builder.boundingBox(buffers.bounds)
.culling(false) .culling(false)
.castShadows(cast_shadows_) .castShadows(cast_shadows_)
.receiveShadows(true) .receiveShadows(receive_shadows_)
.layerMask(1, visible_ ? 1 : 0) .layerMask(0xff, layer_mask_)
.priority(priority_)
.screenSpaceContactShadows(true); .screenSpaceContactShadows(true);
builder.build(*engine_, entity); builder.build(*engine_, entity);
@@ -180,23 +182,47 @@ void Renderables::SetMaterialInstance(
} }
} }
void Renderables::Hide() { void Renderables::SetLayerMask(std::uint8_t mask) {
if (visible_) { if (mask != layer_mask_) {
layer_mask_ = mask;
filament::RenderableManager& rm = engine_->getRenderableManager(); filament::RenderableManager& rm = engine_->getRenderableManager();
for (utils::Entity& entity : entities_) { for (utils::Entity& entity : entities_) {
rm.setLayerMask(rm.getInstance(entity), 1, 0); rm.setLayerMask(rm.getInstance(entity), 0xff, layer_mask_);
} }
visible_ = false;
} }
} }
void Renderables::Show() { void Renderables::SetPriority(std::uint8_t priority) {
if (!visible_) { if (priority != priority_) {
priority_ = priority;
filament::RenderableManager& rm = engine_->getRenderableManager(); filament::RenderableManager& rm = engine_->getRenderableManager();
for (utils::Entity& entity : entities_) { for (utils::Entity& entity : entities_) {
rm.setLayerMask(rm.getInstance(entity), 1, 1); rm.setPriority(rm.getInstance(entity), priority_);
}
}
}
void Renderables::SetCastShadows(bool cast_shadows) {
if (cast_shadows_ != cast_shadows) {
cast_shadows_ = cast_shadows;
filament::RenderableManager& rm = engine_->getRenderableManager();
for (utils::Entity& entity : entities_) {
rm.setCastShadows(rm.getInstance(entity), cast_shadows_);
}
}
}
void Renderables::SetReceiveShadows(bool receive_shadows) {
if (receive_shadows_ != receive_shadows) {
receive_shadows_ = receive_shadows;
filament::RenderableManager& rm = engine_->getRenderableManager();
for (utils::Entity& entity : entities_) {
rm.setReceiveShadows(rm.getInstance(entity), receive_shadows_);
} }
visible_ = true;
} }
} }
@@ -204,29 +230,19 @@ void Renderables::SetWireframe(bool wireframe) {
static constexpr auto kWireframeType = static constexpr auto kWireframeType =
filament::RenderableManager::PrimitiveType::LINES; filament::RenderableManager::PrimitiveType::LINES;
if (wireframe == wireframe_) { if (wireframe != wireframe_) {
return; wireframe_ = wireframe;
}
wireframe_ = wireframe;
filament::RenderableManager& rm = engine_->getRenderableManager(); filament::RenderableManager& rm = engine_->getRenderableManager();
for (int i = 0; i < entities_.size(); ++i) { for (int i = 0; i < entities_.size(); ++i) {
utils::Entity& entity = entities_[i]; utils::Entity& entity = entities_[i];
FilamentBuffers& buffers = owned_buffers_[i].buffers; FilamentBuffers& buffers = owned_buffers_[i].buffers;
rm.setGeometryAt(rm.getInstance(entity), 0, rm.setGeometryAt(rm.getInstance(entity), 0,
wireframe ? kWireframeType : buffers.type, wireframe_ ? kWireframeType : buffers.type,
buffers.vertex_buffer, buffers.index_buffer, 0, buffers.vertex_buffer, buffers.index_buffer, 0,
buffers.index_buffer->getIndexCount()); buffers.index_buffer->getIndexCount());
}
} }
} }
void Renderables::DisableShadows() {
filament::RenderableManager& rm = engine_->getRenderableManager();
for (utils::Entity& entity : entities_) {
rm.setCastShadows(rm.getInstance(entity), false);
}
cast_shadows_ = false;
}
} // namespace mujoco } // namespace mujoco
@@ -15,8 +15,8 @@
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_ #ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_RENDERABLES_H_
#include <cstdint>
#include <optional> #include <optional>
#include <span>
#include <vector> #include <vector>
#include <filament/Engine.h> #include <filament/Engine.h>
@@ -29,6 +29,10 @@ namespace mujoco {
// Manages a collection of related filament Renderable Entities. // Manages a collection of related filament Renderable Entities.
class Renderables { class Renderables {
public: public:
// Default filament values for priority and layer mask.
static constexpr std::uint8_t kDefaultPriority = 4;
static constexpr std::uint8_t kDefaultLayerMask = 0x01;
Renderables(filament::Engine* engine); Renderables(filament::Engine* engine);
~Renderables() noexcept; ~Renderables() noexcept;
@@ -53,16 +57,19 @@ class Renderables {
int GetNumEntities() const { return entities_.size(); } int GetNumEntities() const { return entities_.size(); }
// Hides all managed entities. // Hides all managed entities.
void Hide(); void SetLayerMask(std::uint8_t mask);
// Shows all managed entities. // Sets the priority of all managed entities.
void Show(); void SetPriority(std::uint8_t priority);
// Returns true if the entities are visible.
bool IsVisible() const { return visible_; }
// Disables the renderables from casting shadows. // Disables the renderables from casting shadows.
void DisableShadows(); void SetCastShadows(bool cast_shadows);
// Disables the renderables from receiving shadows.
void SetReceiveShadows(bool receive_shadows);
// If true, forces all entities to be rendered as lines.
void SetWireframe(bool wireframe);
// Adds all managed entities to the given filament Scene. // Adds all managed entities to the given filament Scene.
void AddToScene(filament::Scene* scene); void AddToScene(filament::Scene* scene);
@@ -73,9 +80,6 @@ class Renderables {
// Sets the material instance for all managed entities. // Sets the material instance for all managed entities.
void SetMaterialInstance(filament::MaterialInstance* material_instance); void SetMaterialInstance(filament::MaterialInstance* material_instance);
// If true, forces all entities to be rendered as lines.
void SetWireframe(bool wireframe);
// Returns the filament Engine managing the entities in this collection. // Returns the filament Engine managing the entities in this collection.
filament::Engine* GetEngine() { return engine_; } filament::Engine* GetEngine() { return engine_; }
@@ -96,9 +100,11 @@ class Renderables {
filament::MaterialInstance* material_instance_ = nullptr; filament::MaterialInstance* material_instance_ = nullptr;
std::vector<utils::Entity> entities_; std::vector<utils::Entity> entities_;
std::vector<OwnedBuffers> owned_buffers_; std::vector<OwnedBuffers> owned_buffers_;
bool visible_ = true; std::uint8_t priority_ = kDefaultPriority;
std::uint8_t layer_mask_ = kDefaultLayerMask;
bool wireframe_ = false; bool wireframe_ = false;
bool cast_shadows_ = true; bool cast_shadows_ = true;
bool receive_shadows_ = true;
}; };
} // namespace mujoco } // namespace mujoco