Initial pass at exposing the new mjr APIs.

Moves all internal types and structs to the "public"
render_context_filament.h header file.

PiperOrigin-RevId: 906929736
Change-Id: I7e7c315fb99a3601b09841073eaeec795718b999
This commit is contained in:
Haroon Qureshi
2026-04-28 05:59:15 -07:00
committed by Copybara-Service
parent 647af382c1
commit 5751b09ff6
22 changed files with 468 additions and 475 deletions
@@ -25,7 +25,6 @@
#include "experimental/filament/compat/imgui_bridge.h" #include "experimental/filament/compat/imgui_bridge.h"
#include "experimental/filament/compat/imgui_editor.h" #include "experimental/filament/compat/imgui_editor.h"
#include "experimental/filament/compat/scene_bridge.h" #include "experimental/filament/compat/scene_bridge.h"
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/filament_context.h" #include "experimental/filament/filament/filament_context.h"
#include "experimental/filament/filament/model_util.h" #include "experimental/filament/filament/model_util.h"
#include "experimental/filament/filament/render_target.h" #include "experimental/filament/filament/render_target.h"
@@ -42,11 +41,14 @@ void MjrFilamentRenderer::Init(const mjModel* model) {
scene_bridge_ = std::make_unique<SceneBridge>(GetObjectManager(), model); scene_bridge_ = std::make_unique<SceneBridge>(GetObjectManager(), model);
imgui_bridge_ = std::make_unique<ImguiBridge>(GetObjectManager()); imgui_bridge_ = std::make_unique<ImguiBridge>(GetObjectManager());
mjr_defaultRenderRequest(&render_requests_[0]);
mjr_defaultRenderRequest(&render_requests_[1]);
render_requests_[0].scene = scene_bridge_->GetSceneView(); render_requests_[0].scene = scene_bridge_->GetSceneView();
render_requests_[0].draw_mode = DrawMode::Color; render_requests_[0].draw_mode = mjDRAW_MODE_COLOR;
render_requests_[1].scene = imgui_bridge_->GetSceneView(); render_requests_[1].scene = imgui_bridge_->GetSceneView();
render_requests_[1].draw_mode = DrawMode::Color; render_requests_[1].draw_mode = mjDRAW_MODE_COLOR;
// The UX camera is a fixed orthographic camera. We only need to change the // The UX camera is a fixed orthographic camera. We only need to change the
// width/height based on the viewport per frame. // width/height based on the viewport per frame.
@@ -78,11 +80,11 @@ void MjrFilamentRenderer::Render(const mjrRect& viewport, const mjvScene* scene)
} }
if (scene->flags[mjRND_SEGMENT]) { if (scene->flags[mjRND_SEGMENT]) {
render_requests_[0].draw_mode = DrawMode::Segmentation; render_requests_[0].draw_mode = mjDRAW_MODE_SEGMENTATION;
} else if (scene->flags[mjRND_DEPTH]) { } else if (scene->flags[mjRND_DEPTH]) {
render_requests_[0].draw_mode = DrawMode::Depth; render_requests_[0].draw_mode = mjDRAW_MODE_DEPTH;
} else { } else {
render_requests_[0].draw_mode = DrawMode::Color; render_requests_[0].draw_mode = mjDRAW_MODE_COLOR;
} }
render_requests_[0].width = viewport.width; render_requests_[0].width = viewport.width;
@@ -142,10 +144,11 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb,
const size_t num_requests = const size_t num_requests =
(mode_ == FrameBufferMode::OffScreenWithGui) ? 2 : 1; (mode_ == FrameBufferMode::OffScreenWithGui) ? 2 : 1;
ReadPixelsRequest read_request; mjrReadPixelsRequest read_request;
mjr_defaultReadPixelsRequest(&read_request);
read_request.output = rgb; read_request.output = rgb;
read_request.num_bytes = viewport.width * viewport.height * 3; read_request.num_bytes = viewport.width * viewport.height * 3;
const FrameHandle frame = FilamentContext::Render( const mjrFrameHandle frame = FilamentContext::Render(
{&render_requests_[0], num_requests}, {&read_request, 1}); {&render_requests_[0], num_requests}, {&read_request, 1});
FilamentContext::WaitForFrame(frame); FilamentContext::WaitForFrame(frame);
@@ -163,13 +166,14 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb,
render_requests_[0].target = target.get(); render_requests_[0].target = target.get();
render_requests_[1].target = target.get(); render_requests_[1].target = target.get();
DrawMode last_draw_mode = render_requests_[0].draw_mode; mjrDrawMode last_draw_mode = render_requests_[0].draw_mode;
render_requests_[0].draw_mode = DrawMode::Depth; render_requests_[0].draw_mode = mjDRAW_MODE_DEPTH;
ReadPixelsRequest read_request; mjrReadPixelsRequest read_request;
mjr_defaultReadPixelsRequest(&read_request);
read_request.output = reinterpret_cast<uint8_t*>(depth); read_request.output = reinterpret_cast<uint8_t*>(depth);
read_request.num_bytes = viewport.width * viewport.height * sizeof(float); read_request.num_bytes = viewport.width * viewport.height * sizeof(float);
const FrameHandle frame = const mjrFrameHandle frame =
FilamentContext::Render({&render_requests_[0], 1}, {&read_request, 1}); FilamentContext::Render({&render_requests_[0], 1}, {&read_request, 1});
FilamentContext::WaitForFrame(frame); FilamentContext::WaitForFrame(frame);
@@ -76,7 +76,7 @@ class MjrFilamentRenderer : public FilamentContext {
}; };
FrameBufferMode mode_ = FrameBufferMode::Window; FrameBufferMode mode_ = FrameBufferMode::Window;
RenderRequest render_requests_[2]; mjrRenderRequest render_requests_[2];
std::unique_ptr<SceneBridge> scene_bridge_; std::unique_ptr<SceneBridge> scene_bridge_;
std::unique_ptr<ImguiBridge> imgui_bridge_; std::unique_ptr<ImguiBridge> imgui_bridge_;
}; };
@@ -30,12 +30,12 @@
#include <mujoco/mjvisualize.h> #include <mujoco/mjvisualize.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/compat/model_objects.h" #include "experimental/filament/compat/model_objects.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/mesh.h"
#include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
@@ -424,7 +424,7 @@ static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom,
// the programmatic UVs. // the programmatic UVs.
if (textures.color) { if (textures.color) {
if (textures.color->GetFilamentTexture()->getTarget() == if (Texture::downcast(textures.color)->GetFilamentTexture()->getTarget() ==
filament::Texture::Sampler::SAMPLER_2D) { filament::Texture::Sampler::SAMPLER_2D) {
// For 2D textures, `tex_repeat` specifies how many times the texture // For 2D textures, `tex_repeat` specifies how many times the texture
// image is repeated. The `tex_uniform` flag determines if the repetition // image is repeated. The `tex_uniform` flag determines if the repetition
@@ -1,36 +0,0 @@
// Copyright 2026 DeepMind Technologies Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAW_MODE_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAW_MODE_H_
namespace mujoco {
// The different modes that can be used to render the scene.
enum class DrawMode {
// Render the scene with "normal" colors and lighting.
Color,
// Render the scene as a grayscale depth map.
Depth,
// Render each object with a unique, uniform (flat) color regardless of
// lighting and texture.
Segmentation,
};
static constexpr int kNumDrawModes = 3;
} // namespace mujoco
#endif // MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_DRAW_MODE_H_
@@ -79,16 +79,16 @@ FilamentContext::~FilamentContext() {
filament::Engine::destroy(engine_); filament::Engine::destroy(engine_);
} }
FilamentContext::FrameHandle FilamentContext::Render( mjrFrameHandle FilamentContext::Render(
std::span<const RenderRequest> requests, std::span<const mjrRenderRequest> requests,
std::span<const ReadPixelsRequest> read_requests) { std::span<const mjrReadPixelsRequest> read_requests) {
if (read_requests.size() > 1) { if (read_requests.size() > 1) {
mju_error("Only one read request is supported for now."); mju_error("Only one read request is supported for now.");
} }
bool render_began = false; bool render_began = false;
mjrRenderTarget* current_target = nullptr; mjrRenderTarget* current_target = nullptr;
for (const RenderRequest& request : requests) { for (const mjrRenderRequest& request : requests) {
if (request.target != current_target && render_began) { if (request.target != current_target && render_began) {
renderer_->endFrame(); renderer_->endFrame();
render_began = false; render_began = false;
@@ -135,7 +135,7 @@ FilamentContext::FrameHandle FilamentContext::Render(
"Rendering to a render target without a read request is pointless."); "Rendering to a render target without a read request is pointless.");
} }
const ReadPixelsRequest& read_request = read_requests[0]; const mjrReadPixelsRequest& read_request = read_requests[0];
if (read_request.num_bytes == 0) { if (read_request.num_bytes == 0) {
mju_error("Output buffer size is zero."); mju_error("Output buffer size is zero.");
} }
@@ -156,7 +156,7 @@ FilamentContext::FrameHandle FilamentContext::Render(
scene_view_request.target = render_target; scene_view_request.target = render_target;
SceneView* scene_view = SceneView::downcast(request.scene); SceneView* scene_view = SceneView::downcast(request.scene);
scene_view->Render(renderer_, scene_view_request); scene_view->Render(renderer_, scene_view_request);
render_target->ReadColorPixels(renderer_, read_request.output, render_target->ReadColorPixels(renderer_, (uint8_t*)read_request.output,
read_request.num_bytes); read_request.num_bytes);
} }
} }
@@ -179,7 +179,7 @@ FilamentContext::FrameHandle FilamentContext::Render(
return ++frame_counter_; return ++frame_counter_;
} }
void FilamentContext::WaitForFrame(FrameHandle frame_handle) { void FilamentContext::WaitForFrame(mjrFrameHandle frame_handle) {
if (frame_counter_ < frame_handle) { if (frame_counter_ < frame_handle) {
engine_->flushAndWait(); engine_->flushAndWait();
} }
@@ -15,7 +15,6 @@
#ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_ #ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <span> #include <span>
#include <memory> #include <memory>
@@ -25,11 +24,7 @@
#include <filament/Renderer.h> #include <filament/Renderer.h>
#include <filament/SwapChain.h> #include <filament/SwapChain.h>
#include <math/vec4.h> #include <math/vec4.h>
#include <mujoco/mjvisualize.h>
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/scene_view.h"
#include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/render_target.h"
#include "experimental/filament/render_context_filament.h" #include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
@@ -43,62 +38,16 @@ class FilamentContext : public mjrfContext {
FilamentContext(const FilamentContext&) = delete; FilamentContext(const FilamentContext&) = delete;
FilamentContext& operator=(const FilamentContext&) = delete; FilamentContext& operator=(const FilamentContext&) = delete;
// Information needed to render a single image of a scene.
struct RenderRequest {
// The scene to render.
mjrScene* scene = nullptr;
// The method (e.g. Color, Depth, Segmentation, etc.) to use for rendering.
DrawMode draw_mode = DrawMode::Color;
// The camera from which to render the scene.
mjvGLCamera camera;
// The dimensions of the output image.
int width = 0;
int height = 0;
// The render target into which to render the image. If nullptr, the image
// will be rendered to the window (as previously configured in
// mjrFilamentConfig::native_window).
mjrRenderTarget* target = nullptr;
};
// Information needed to read pixels from a render target.
struct ReadPixelsRequest {
mjrRenderTarget* target = nullptr;
// The buffer into which the read pixels will be written.
uint8_t* output = nullptr;
// The number of bytes in the output buffer. This should match the size of
// the render target texture.
std::size_t num_bytes = 0;
// Callback when the read pixels operation is complete. This will be called
// during WaitForFrame() or in a subsequent call to Render(). This function
// can optionally be used to free the output buffer if needed.
void (*read_completed_callback)(void* user_data) = nullptr;
// User data to pass to the completion callback.
void* user_data = nullptr;
};
// Rendering is asynchronous by nature. Each render request is assigned a
// unique Handle which can be used to query the status of the request. The
// Handle can also be used to block until the request is completed.
using FrameHandle = std::uint64_t;
// Queues the given render requests for rendering. This function copies the // Queues the given render requests for rendering. This function copies the
// necessary data from the requests into the renderer thread and returns // necessary data from the requests into the renderer thread and returns
// immediately afterwards. The renderer thread will then perform the actual // immediately afterwards. The renderer thread will then perform the actual
// rendering on the GPU. Callers can use WaitForFrame to block until the // rendering on the GPU. Callers can use WaitForFrame to block until the
// rendering is complete. // rendering is complete.
FrameHandle Render(std::span<const RenderRequest> render_requests, mjrFrameHandle Render(std::span<const mjrRenderRequest> render_requests,
std::span<const ReadPixelsRequest> read_requests = {}); std::span<const mjrReadPixelsRequest> read_requests = {});
// Blocks until the given frame has completed rendering. // Blocks until the given frame has completed rendering.
void WaitForFrame(FrameHandle frame_handle); void WaitForFrame(mjrFrameHandle frame_handle);
// Sets the clear color for the renderer. // Sets the clear color for the renderer.
void SetClearColor(const filament::math::float4& color); void SetClearColor(const filament::math::float4& color);
+1 -15
View File
@@ -27,27 +27,13 @@
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
using filament::math::float3; using filament::math::float3;
using filament::math::mat3f; using filament::math::mat3f;
void mjr_defaultLightParams(mjrLightParams* params) {
params->type = mjLIGHT_POINT;
params->texture = nullptr;
params->color[0] = 0;
params->color[1] = 0;
params->color[2] = 0;
params->intensity = 0.0f;
params->cast_shadows = true;
params->range = 10.0f;
params->spot_cone_angle = 180.f;
params->bulb_radius = 0.0f;
params->shadow_map_size = 2048;
params->vsm_blur_width = 0.0f;
}
Light::Light(filament::Engine* engine, const mjrLightParams& params) Light::Light(filament::Engine* engine, const mjrLightParams& params)
: engine_(engine), params_(params) { : engine_(engine), params_(params) {
// Filament treats image-based lights (IBLs) as separate objects (i.e. // Filament treats image-based lights (IBLs) as separate objects (i.e.
@@ -20,39 +20,10 @@
#include <math/vec3.h> #include <math/vec3.h>
#include <utils/Entity.h> #include <utils/Entity.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h" #include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
typedef mjtLightType mjrLightType;
// Configuration parameters for a light.
struct mjrLightParams {
// The type of light (e.g. spot, point, directional, etc.)
mjrLightType type;
// The texture to use for image lights.
const mjrTexture* texture;
// The color of the light.
float color[3];
// The intensity of the light, in candela.
float intensity;
// Whether or not the light casts shadows.
mjtByte cast_shadows;
// The range/distance in which the light is effective, in meters.
float range;
// The angle of the spot light cone, in degrees.
float spot_cone_angle;
// The radius of the bulb used for soft shadows.
float bulb_radius;
// The size of the shadow map.
int shadow_map_size;
// Blur width for EL VSM.
float vsm_blur_width;
};
void mjr_defaultLightParams(mjrLightParams* params);
// Manages the filament Entities for a single mjvLight. // Manages the filament Entities for a single mjvLight.
class Light : public mjrLight { class Light : public mjrLight {
public: public:
+4 -40
View File
@@ -14,8 +14,6 @@
#include "experimental/filament/filament/material.h" #include "experimental/filament/filament/material.h"
#include <array>
#include <filament/Color.h> #include <filament/Color.h>
#include <filament/Material.h> #include <filament/Material.h>
#include <filament/MaterialInstance.h> #include <filament/MaterialInstance.h>
@@ -25,45 +23,10 @@
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/texture.h"
#include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
template <int N>
static void setf(float (&arr)[N], const std::array<float, N>& values) {
for (int i = 0; i < N; ++i) {
arr[i] = values[i];
}
}
void mjr_defaultMaterialTextures(mjrMaterialTextures* textures) {
textures->color = nullptr;
textures->normal = nullptr;
textures->metallic = nullptr;
textures->roughness = nullptr;
textures->occlusion = nullptr;
textures->orm = nullptr;
textures->emissive = nullptr;
textures->reflection = nullptr;
}
void mjr_defaultMaterialParams(mjrMaterialParams* params) {
setf(params->color, {1.f, 1.f, 1.f, 1.f});
setf(params->segmentation_color, {1, 1, 1, 1});
setf(params->uv_scale, {1, 1, 1});
setf(params->uv_offset, {0, 0, 0});
setf(params->scissor, {0, 0, 0, 0});
params->emissive = -1.0f;
params->specular = -1.0f;
params->glossiness = -1.0f;
params->metallic = -1.0f;
params->roughness = -1.0f;
params->reflectance = 0.0f;
params->tex_uniform = false;
params->reflective = false;
}
void UpdateMaterialInstance(filament::MaterialInstance* instance, void UpdateMaterialInstance(filament::MaterialInstance* instance,
const mjrMaterialParams& params, const mjrMaterialParams& params,
const mjrMaterialTextures& textures, const mjrMaterialTextures& textures,
@@ -118,11 +81,12 @@ void UpdateMaterialInstance(filament::MaterialInstance* instance,
sampler.setMinFilter( sampler.setMinFilter(
filament::TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR); filament::TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR);
auto TrySetTexture = [&](const char* name, const Texture* texture, auto TrySetTexture = [&](const char* name, const mjrTexture* texture,
mjtTextureRole role) { mjtTextureRole role) {
if (material->hasParameter(name)) { if (material->hasParameter(name)) {
if (texture != nullptr) { if (texture != nullptr) {
instance->setParameter(name, texture->GetFilamentTexture(), sampler); instance->setParameter(
name, Texture::downcast(texture)->GetFilamentTexture(), sampler);
} else { } else {
instance->setParameter(name, object_mgr->GetFallbackTexture(role), instance->setParameter(name, object_mgr->GetFallbackTexture(role),
sampler); sampler);
+1 -36
View File
@@ -17,46 +17,11 @@
#include <filament/Engine.h> #include <filament/Engine.h>
#include <filament/MaterialInstance.h> #include <filament/MaterialInstance.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/filament/texture.h"
#include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
// The textures that can be assigned to the drawable's material.
struct mjrMaterialTextures {
const Texture* color;
const Texture* normal;
const Texture* metallic;
const Texture* roughness;
const Texture* occlusion;
const Texture* orm;
const Texture* emissive;
const Texture* reflection;
};
void mjr_defaultMaterialTextures(mjrMaterialTextures* textures);
// The parameters that can be applied to the drawable's material.
struct mjrMaterialParams {
float color[4];
float segmentation_color[4];
float tex_repeat[2];
float uv_scale[3];
float uv_offset[3];
float scissor[4];
float specular;
float glossiness;
float metallic;
float roughness;
float emissive;
float reflectance;
mjtByte tex_uniform;
mjtByte reflective;
};
void mjr_defaultMaterialParams(mjrMaterialParams* params);
// Updates the material instances based on the currently set parameters and // Updates the material instances based on the currently set parameters and
// textures. // textures.
void UpdateMaterialInstance(filament::MaterialInstance* instance, void UpdateMaterialInstance(filament::MaterialInstance* instance,
+1 -5
View File
@@ -33,6 +33,7 @@
#include <math/vec4.h> #include <math/vec4.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
@@ -101,11 +102,6 @@ int FillSequence(std::byte* buffer, std::size_t num_bytes) {
return num; return num;
} }
// Initializes the mjrMeshData to default values.
void mjr_defaultMeshData(mjrMeshData* data) {
std::memset(data, 0, sizeof(mjrMeshData));
}
Mesh::Mesh(filament::Engine* engine, const mjrMeshData& data) Mesh::Mesh(filament::Engine* engine, const mjrMeshData& data)
: engine_(engine), shared_state_(std::make_shared<SharedState>()) { : engine_(engine), shared_state_(std::make_shared<SharedState>()) {
type_ = data.primitive_type == mjMESH_PRIMITIVE_TYPE_TRIANGLES type_ = data.primitive_type == mjMESH_PRIMITIVE_TYPE_TRIANGLES
-104
View File
@@ -16,7 +16,6 @@
#define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MESH_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MESH_H_
#include <array> #include <array>
#include <cstddef>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@@ -30,114 +29,11 @@
#include <filament/RenderableManager.h> #include <filament/RenderableManager.h>
#include <filament/VertexBuffer.h> #include <filament/VertexBuffer.h>
#include <math/vec4.h> #include <math/vec4.h>
#include <mujoco/mujoco.h>
#include "experimental/filament/render_context_filament.h" #include "experimental/filament/render_context_filament.h"
// Functions for creating filament vertex and index buffers. // Functions for creating filament vertex and index buffers.
namespace mujoco { namespace mujoco {
// The type of data stored in an index buffer.
typedef enum mjrIndexType_ {
mjINDEX_TYPE_U16 = 0,
mjINDEX_TYPE_U32 = 1,
} mjrIndexType;
// The type of primitive to be drawn by vertex data.
typedef enum mjrMeshPrimitiveType_ {
mjMESH_PRIMITIVE_TYPE_TRIANGLES = 0,
mjMESH_PRIMITIVE_TYPE_LINES = 1,
} mjrMeshPrimitiveType;
// The usage/purpose of an attribute of a vertex.
typedef enum mjrVertexAttributeUsage_ {
mjVERTEX_ATTRIBUTE_USAGE_POSITION = 0,
mjVERTEX_ATTRIBUTE_USAGE_NORMAL = 1,
mjVERTEX_ATTRIBUTE_USAGE_TANGENTS = 2,
mjVERTEX_ATTRIBUTE_USAGE_UV = 3,
mjVERTEX_ATTRIBUTE_USAGE_COLOR = 4,
} mjrVertexAttributeUsage;
// The data format of an attribute of a vertex.
typedef enum mjrVertexAttributeType_ {
mjVERTEX_ATTRIBUTE_TYPE_FLOAT2 = 0,
mjVERTEX_ATTRIBUTE_TYPE_FLOAT3 = 1,
mjVERTEX_ATTRIBUTE_TYPE_FLOAT4 = 2,
mjVERTEX_ATTRIBUTE_TYPE_UBYTE4 = 3,
} mjrVertexAttributeType;
// Maximum number of vertex attributes that can be used by a mesh.
enum { mjMAX_VERTEX_ATTRIBUTES = 16 };
// Information about a single attribute of a vertex.
struct mjrVertexAttribute {
// The data for the attribute.
const void* bytes;
// The usage/purpose of the attribute.
mjrVertexAttributeUsage usage;
// The data format of the attribute.
mjrVertexAttributeType type;
};
// The binary contents of a mesh.
struct mjrMeshData {
// The number of vertices in the mesh. Each of the vertex arrays below is
// assumed to have this number of elements.
mjtSize nvertices;
// The number of attributes for each vertex in the mesh.
int nattributes;
// Information about each attribute of a vertex in the mesh. See `interleaved`
// for more details.
mjrVertexAttribute attributes[mjMAX_VERTEX_ATTRIBUTES];
// Whether the vertex attributes are interleaved or not.
//
// If true, assumes that the attributes are packed in the order specified in
// the attributes array, with no padding in-between. Additionally, the
// `data` pointer for each attribute is assumed to point to the first element
// of that type.
//
// If false, assume each attribute is stored in a separate array as defined
// by the `data` field of the attribute.
mjtByte interleaved;
// The number of indices in the mesh. The indices array is assumed to have
// this number of elements.
mjtSize nindices;
// The indices of the mesh, stored as either ushort or uint depending on the
// index type.
const void* indices;
// The type of data stored in the indices array.
mjrIndexType index_type;
// The type of primitive to be drawn by vertex data.
mjrMeshPrimitiveType primitive_type;
// Whether to compute the bounds of the mesh using the vertex positions.
mjtByte compute_bounds;
// The bounds of the mesh. If bounds_min == bounds_max, then we assume that
// that the bounds are not set (i.e. the bounds is empty).
float bounds_min[3];
float bounds_max[3];
// Because rendering may be multithreaded, we cannot make assumptions about
// when the mesh data will finish uploading to the GPU. As such, we will use
// this callback to notify callers when it is safe to free the mesh data.
void (*release_callback)(void* user_data);
// User data to pass to the release callback.
void* user_data;
};
// Initializes the MeshData to default values.
void mjr_defaultMeshData(mjrMeshData* data);
// Owns a Vertex and Index buffer representing a geometry mesh. // Owns a Vertex and Index buffer representing a geometry mesh.
class Mesh : public mjrMesh { class Mesh : public mjrMesh {
public: public:
@@ -30,11 +30,6 @@
namespace mujoco { namespace mujoco {
void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config) {
config->color_format = mjPIXEL_FORMAT_RGBA8;
config->depth_format = mjPIXEL_FORMAT_DEPTH32F;
}
RenderTarget::RenderTarget(filament::Engine* engine, RenderTarget::RenderTarget(filament::Engine* engine,
const mjrRenderTargetConfig& config) const mjrRenderTargetConfig& config)
: engine_(engine), config_(config) {} : engine_(engine), config_(config) {}
@@ -26,15 +26,6 @@
namespace mujoco { namespace mujoco {
// Defines the basic properties of a render target.
struct mjrRenderTargetConfig {
mjrPixelFormat color_format;
mjrPixelFormat depth_format;
};
// Initializes the RenderTargetConfig to default values.
void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config);
// Manages a filament RenderTarget and the textures which are bound to it. // Manages a filament RenderTarget and the textures which are bound to it.
class RenderTarget : public mjrRenderTarget { class RenderTarget : public mjrRenderTarget {
public: public:
@@ -26,20 +26,17 @@
#include <math/mat4.h> #include <math/mat4.h>
#include <utils/EntityManager.h> #include <utils/EntityManager.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/material.h" #include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/mesh.h"
#include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/object_manager.h"
#include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
using filament::math::mat4f; using filament::math::mat4f;
void mjr_defaultRenderableParams(mjrRenderableParams* params) {
params->shading_model = mjSHADING_MODEL_SCENE_OBJECT;
}
Renderable::Renderable(ObjectManager* object_mgr, const mjrRenderableParams& params) Renderable::Renderable(ObjectManager* object_mgr, const mjrRenderableParams& params)
: object_mgr_(object_mgr), params_(params) { : object_mgr_(object_mgr), params_(params) {
mjr_defaultMaterialParams(&material_params_); mjr_defaultMaterialParams(&material_params_);
@@ -57,7 +54,7 @@ Renderable::~Renderable() noexcept {
engine->destroy(part.entity); engine->destroy(part.entity);
em.destroy(part.entity); em.destroy(part.entity);
} }
for (int i = 0; i < kNumDrawModes; ++i) { for (int i = 0; i < mjNUM_DRAW_MODES; ++i) {
if (instances_[i] != nullptr) { if (instances_[i] != nullptr) {
engine->destroy(instances_[i]); engine->destroy(instances_[i]);
instances_[i] = nullptr; instances_[i] = nullptr;
@@ -206,13 +203,13 @@ void Renderable::UpdateMaterial(const mjrMaterialParams& params,
material_params_ = params; material_params_ = params;
material_textures_ = textures; material_textures_ = textures;
AssignMaterial(DrawMode::Color, GetColorMaterialType()); AssignMaterial(mjDRAW_MODE_COLOR, GetColorMaterialType());
if (params_.shading_model == mjSHADING_MODEL_SCENE_OBJECT) { if (params_.shading_model == mjSHADING_MODEL_SCENE_OBJECT) {
AssignMaterial(DrawMode::Depth, ObjectManager::kUnlitDepth); AssignMaterial(mjDRAW_MODE_DEPTH, ObjectManager::kUnlitDepth);
AssignMaterial(DrawMode::Segmentation, ObjectManager::kUnlitSegmentation); AssignMaterial(mjDRAW_MODE_SEGMENTATION, ObjectManager::kUnlitSegmentation);
} }
for (int i = 0; i < kNumDrawModes; ++i) { for (int i = 0; i < mjNUM_DRAW_MODES; ++i) {
if (instances_[i]) { if (instances_[i]) {
UpdateMaterialInstance(instances_[i], material_params_, UpdateMaterialInstance(instances_[i], material_params_,
material_textures_, object_mgr_); material_textures_, object_mgr_);
@@ -221,7 +218,7 @@ void Renderable::UpdateMaterial(const mjrMaterialParams& params,
SetDrawMode(draw_mode_); SetDrawMode(draw_mode_);
} }
void Renderable::AssignMaterial(DrawMode mode, void Renderable::AssignMaterial(mjrDrawMode mode,
ObjectManager::MaterialType material_type) { ObjectManager::MaterialType material_type) {
const int index = static_cast<int>(mode); const int index = static_cast<int>(mode);
@@ -248,10 +245,10 @@ const mjrMaterialTextures& Renderable::GetMaterialTextures() const {
return material_textures_; return material_textures_;
} }
void Renderable::SetDrawMode(DrawMode mode) { void Renderable::SetDrawMode(mjrDrawMode mode) {
// Only SceneObjects support non-color draw modes. // Only SceneObjects support non-color draw modes.
if (params_.shading_model != mjSHADING_MODEL_SCENE_OBJECT) { if (params_.shading_model != mjSHADING_MODEL_SCENE_OBJECT) {
mode = DrawMode::Color; mode = mjDRAW_MODE_COLOR;
} }
filament::MaterialInstance* instance = instances_[static_cast<int>(mode)]; filament::MaterialInstance* instance = instances_[static_cast<int>(mode)];
@@ -369,6 +366,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const {
// geometry) and `mesh_texcoordadr` stores the address of the mesh uvs if // geometry) and `mesh_texcoordadr` stores the address of the mesh uvs if
// it has them. // it has them.
bool has_texcoords = false; bool has_texcoords = false;
const Texture* color_texture = Texture::downcast(material_textures_.color);
if (!parts_.empty()) { if (!parts_.empty()) {
const auto attribs = parts_[0].mesh->GetVertexAttributes(); const auto attribs = parts_[0].mesh->GetVertexAttributes();
auto it = std::find(attribs.begin(), attribs.end(), auto it = std::find(attribs.begin(), attribs.end(),
@@ -376,7 +374,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const {
has_texcoords = (it != attribs.end()); has_texcoords = (it != attribs.end());
} }
if (material_textures_.color == nullptr) { if (color_texture == nullptr) {
if (material_params_.color[3] < 1.0f) { if (material_params_.color[3] < 1.0f) {
return ObjectManager::kPhongColorFade; return ObjectManager::kPhongColorFade;
} else if (material_params_.reflective) { } else if (material_params_.reflective) {
@@ -384,7 +382,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const {
} else { } else {
return ObjectManager::kPhongColor; return ObjectManager::kPhongColor;
} }
} else if (material_textures_.color->GetFilamentTexture()->getTarget() == } else if (color_texture->GetFilamentTexture()->getTarget() ==
filament::Texture::Sampler::SAMPLER_CUBEMAP) { filament::Texture::Sampler::SAMPLER_CUBEMAP) {
if (material_params_.color[3] < 1.0f) { if (material_params_.color[3] < 1.0f) {
return ObjectManager::kPhongCubeFade; return ObjectManager::kPhongCubeFade;
@@ -24,7 +24,6 @@
#include <filament/Scene.h> #include <filament/Scene.h>
#include <math/mat4.h> #include <math/mat4.h>
#include <utils/Entity.h> #include <utils/Entity.h>
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/material.h" #include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/mesh.h"
@@ -33,21 +32,6 @@
namespace mujoco { namespace mujoco {
// The shading model (material) for a Renderable.
typedef enum mjrShadingModel_ {
mjSHADING_MODEL_SCENE_OBJECT,
mjSHADING_MODEL_DECOR,
mjSHADING_MODEL_DECOR_LINES,
mjSHADING_MODEL_UX,
} mjrShadingModel;
// Configuration parameters for a Renderable.
struct mjrRenderableParams {
mjrShadingModel shading_model;
};
void mjr_defaultRenderableParams(mjrRenderableParams* params);
// A Renderable is effectively two things: a mesh and a material. // A Renderable is effectively two things: a mesh and a material.
// //
// The mesh describes the surface geometry of the object and the material // The mesh describes the surface geometry of the object and the material
@@ -125,7 +109,7 @@ class Renderable : public mjrRenderable {
// Further defines the material of the renderable. Only applies to renderables // Further defines the material of the renderable. Only applies to renderables
// with a SceneObject shading model. // with a SceneObject shading model.
void SetDrawMode(DrawMode mode); void SetDrawMode(mjrDrawMode mode);
// Updates the parameters for the material. // Updates the parameters for the material.
void UpdateMaterial(const mjrMaterialParams& params, void UpdateMaterial(const mjrMaterialParams& params,
@@ -157,16 +141,16 @@ class Renderable : public mjrRenderable {
void InitPartEntity(Part& part); void InitPartEntity(Part& part);
void AssignMaterial(DrawMode mode, ObjectManager::MaterialType material_type); void AssignMaterial(mjrDrawMode mode, ObjectManager::MaterialType material_type);
ObjectManager::MaterialType GetColorMaterialType() const; ObjectManager::MaterialType GetColorMaterialType() const;
ObjectManager* object_mgr_; ObjectManager* object_mgr_;
mjrRenderableParams params_; mjrRenderableParams params_;
filament::MaterialInstance* instances_[kNumDrawModes] = {nullptr}; filament::MaterialInstance* instances_[mjNUM_DRAW_MODES] = {nullptr};
mjrMaterialParams material_params_; mjrMaterialParams material_params_;
mjrMaterialTextures material_textures_; mjrMaterialTextures material_textures_;
DrawMode draw_mode_ = DrawMode::Color; mjrDrawMode draw_mode_ = mjDRAW_MODE_COLOR;
filament::Scene* assigned_scene_ = nullptr; filament::Scene* assigned_scene_ = nullptr;
std::vector<Part> parts_; std::vector<Part> parts_;
filament::math::mat4f transform_; filament::math::mat4f transform_;
@@ -40,13 +40,12 @@
#include <utils/EntityManager.h> #include <utils/EntityManager.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h" #include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/light.h" #include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/material.h"
#include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/math_util.h"
#include "experimental/filament/filament/render_target.h" #include "experimental/filament/filament/render_target.h"
#include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/texture.h"
#include "experimental/filament/render_context_filament.h"
namespace mujoco { namespace mujoco {
@@ -54,10 +53,6 @@ using filament::math::float3;
using filament::math::float4; using filament::math::float4;
using filament::math::mat4; using filament::math::mat4;
static constexpr int kNormalIndex = static_cast<int>(DrawMode::Color);
static constexpr int kDepthIndex = static_cast<int>(DrawMode::Depth);
static constexpr int kSegmentIndex = static_cast<int>(DrawMode::Segmentation);
static filament::ColorGrading::Builder ToBuilder( static filament::ColorGrading::Builder ToBuilder(
const ColorGradingOptions& opts) { const ColorGradingOptions& opts) {
return filament::ColorGrading::Builder() return filament::ColorGrading::Builder()
@@ -146,11 +141,11 @@ SceneView::SceneView(filament::Engine* engine) : engine_(engine) {
// Disable post processing for the depth and segmentation views to preserve // Disable post processing for the depth and segmentation views to preserve
// the values. // the values.
views_[kDepthIndex]->setPostProcessingEnabled(false); views_[mjDRAW_MODE_DEPTH]->setPostProcessingEnabled(false);
views_[kSegmentIndex]->setPostProcessingEnabled(false); views_[mjDRAW_MODE_SEGMENTATION]->setPostProcessingEnabled(false);
// Rotate the fog to align with mujoco's +Z up space. // Rotate the fog to align with mujoco's +Z up space.
auto fog = views_[kNormalIndex]->getFogEntity(); auto fog = views_[mjDRAW_MODE_COLOR]->getFogEntity();
auto& tm = engine->getTransformManager(); auto& tm = engine->getTransformManager();
tm.create(fog); tm.create(fog);
tm.setTransform(tm.getInstance(fog), tm.setTransform(tm.getInstance(fog),
@@ -255,7 +250,7 @@ void SceneView::Render(filament::Renderer* renderer,
} }
// Render reflection passes. // Render reflection passes.
if (request.draw_mode == DrawMode::Color && reflections_enabled_) { if (request.draw_mode == mjDRAW_MODE_COLOR && reflections_enabled_) {
for (size_t i = 0; i < reflectives_.size(); ++i) { for (size_t i = 0; i < reflectives_.size(); ++i) {
Renderable* renderable = reflectives_[i]; Renderable* renderable = reflectives_[i];
@@ -317,7 +312,7 @@ void SceneView::SetColorGradingOptions(const ColorGradingOptions& opts) {
auto color_grading = ToBuilder(color_grading_options_) auto color_grading = ToBuilder(color_grading_options_)
.toneMapper(tone_mapper.get()) .toneMapper(tone_mapper.get())
.build(*engine_); .build(*engine_);
views_[kNormalIndex]->setColorGrading(color_grading); views_[mjDRAW_MODE_COLOR]->setColorGrading(color_grading);
if (color_grading_) { if (color_grading_) {
engine_->destroy(color_grading_); engine_->destroy(color_grading_);
} }
@@ -326,11 +321,11 @@ void SceneView::SetColorGradingOptions(const ColorGradingOptions& opts) {
} }
void SceneView::EnableShadows() { void SceneView::EnableShadows() {
views_[kNormalIndex]->setShadowingEnabled(true); views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(true);
} }
void SceneView::DisableShadows() { void SceneView::DisableShadows() {
views_[kNormalIndex]->setShadowingEnabled(false); views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(false);
} }
void SceneView::EnableReflections() { void SceneView::EnableReflections() {
@@ -351,19 +346,18 @@ void SceneView::DisableReflections() {
textures.reflection = nullptr; textures.reflection = nullptr;
renderable->UpdateMaterial(renderable->GetMaterialParams(), textures); renderable->UpdateMaterial(renderable->GetMaterialParams(), textures);
} }
} }
void SceneView::EnablePostProcessing() { void SceneView::EnablePostProcessing() {
views_[kNormalIndex]->setPostProcessingEnabled(true); views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(true);
} }
void SceneView::DisablePostProcessing() { void SceneView::DisablePostProcessing() {
views_[kNormalIndex]->setPostProcessingEnabled(false); views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(false);
} }
filament::View* SceneView::GetDefaultRenderView() { filament::View* SceneView::GetDefaultRenderView() {
return views_[kNormalIndex]; return views_[mjDRAW_MODE_COLOR];
} }
ColorGradingOptions SceneView::GetColorGradingOptions() const { ColorGradingOptions SceneView::GetColorGradingOptions() const {
@@ -27,7 +27,6 @@
#include <filament/View.h> #include <filament/View.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "experimental/filament/filament/color_grading_options.h" #include "experimental/filament/filament/color_grading_options.h"
#include "experimental/filament/filament/draw_mode.h"
#include "experimental/filament/filament/light.h" #include "experimental/filament/filament/light.h"
#include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/renderable.h"
#include "experimental/filament/filament/render_target.h" #include "experimental/filament/filament/render_target.h"
@@ -59,7 +58,7 @@ class SceneView : public mjrScene {
// Parameters for rendering the scene. // Parameters for rendering the scene.
struct RenderRequest { struct RenderRequest {
// The draw mode (e.g. normal, depth, segmentation) to render. // The draw mode (e.g. normal, depth, segmentation) to render.
DrawMode draw_mode = DrawMode::Color; mjrDrawMode draw_mode = mjDRAW_MODE_COLOR;
// The target viewport for the rendered image. // The target viewport for the rendered image.
mjrRect viewport; mjrRect viewport;
// The camera from which to render the scene. // The camera from which to render the scene.
@@ -111,7 +110,7 @@ class SceneView : public mjrScene {
filament::Camera* camera_ = nullptr; filament::Camera* camera_ = nullptr;
filament::ColorGrading* color_grading_ = nullptr; filament::ColorGrading* color_grading_ = nullptr;
ColorGradingOptions color_grading_options_; ColorGradingOptions color_grading_options_;
std::array<filament::View*, kNumDrawModes> views_; std::array<filament::View*, mjNUM_DRAW_MODES> views_;
// Scene objects. // Scene objects.
std::unordered_set<Light*> lights_; std::unordered_set<Light*> lights_;
@@ -110,14 +110,6 @@ static filament::Texture::InternalFormat GetTextureInternalFormat(
} }
} }
void mjr_defaultTextureData(mjrTextureData* data) {
std::memset(data, 0, sizeof(mjrTextureData));
}
void mjr_defaultTextureConfig(mjrTextureConfig* config) {
std::memset(config, 0, sizeof(mjrTextureConfig));
}
Texture::Texture(filament::Engine* engine, const mjrTextureConfig& config, Texture::Texture(filament::Engine* engine, const mjrTextureConfig& config,
InternalFlags flags) InternalFlags flags)
: engine_(engine), config_(config) { : engine_(engine), config_(config) {
@@ -25,63 +25,6 @@
// Functions for creating filament textures. // Functions for creating filament textures.
namespace mujoco { namespace mujoco {
// Pixel formats for textures.
typedef enum mjrPixelFormat_ {
mjPIXEL_FORMAT_UNKNOWN = 0,
mjPIXEL_FORMAT_R8,
mjPIXEL_FORMAT_RGB8,
mjPIXEL_FORMAT_RGBA8,
mjPIXEL_FORMAT_R32F,
mjPIXEL_FORMAT_DEPTH32F,
mjPIXEL_FORMAT_KTX,
} mjrPixelFormat;
typedef mjtTexture mjrTextureTarget;
typedef mjtColorSpace mjrColorSpace;
// The binary contents of a texture.
struct mjrTextureData {
// Pointer to the image data. If null, an empty texture will be created.
const void* bytes;
// The number of bytes in the image data.
mjtSize nbytes;
// Because rendering may be multithreaded, we cannot make assumptions about
// when the image data will finish uploading to the GPU. As such, we will use
// this callback to notify callers when it is safe to free the image data.
void (*release_callback)(void* user_data);
// User data to pass to the release callback.
void* user_data;
};
// Initializes the TextureData to default values.
void mjr_defaultTextureData(mjrTextureData* data);
// Defines the basic properties of a texture.
struct mjrTextureConfig {
// The width of the texture. For compressed textures (e.g. KTX), this is the
// number of bytes in the compressed data.
int width;
// The height of the texture. For compressed textures (e.g. KTX), this should
// be 0.
int height;
// The target of the texture (e.g. 2D, cube, etc.)
mjrTextureTarget target;
// The format of the pixels in the texture (e.g. RGB8, RGBA8, KTX, etc.)
mjrPixelFormat format;
// The color space of the texture (e.g. LINEAR, sRGB, etc.)
mjrColorSpace color_space;
};
// Initializes the TextureConfig to default values.
void mjr_defaultTextureConfig(mjrTextureConfig* config);
// Wrapper around a filament::Texture. // Wrapper around a filament::Texture.
class Texture : public mjrTexture { class Texture : public mjrTexture {
public: public:
@@ -14,6 +14,7 @@
#include "experimental/filament/render_context_filament.h" #include "experimental/filament/render_context_filament.h"
#include <array>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
@@ -36,12 +37,91 @@ static void CheckFilamentContext() {
} }
} }
template <int N>
static void setf(float (&arr)[N], const std::array<float, N>& values) {
for (int i = 0; i < N; ++i) {
arr[i] = values[i];
}
}
extern "C" { extern "C" {
void mjrf_defaultFilamentConfig(mjrFilamentConfig* config) { void mjrf_defaultFilamentConfig(mjrFilamentConfig* config) {
memset(config, 0, sizeof(mjrFilamentConfig)); memset(config, 0, sizeof(mjrFilamentConfig));
} }
void mjr_defaultTextureData(mjrTextureData* data) {
memset(data, 0, sizeof(mjrTextureData));
}
void mjr_defaultTextureConfig(mjrTextureConfig* config) {
memset(config, 0, sizeof(mjrTextureConfig));
}
void mjr_defaultMeshData(mjrMeshData* data) {
std::memset(data, 0, sizeof(mjrMeshData));
}
void mjr_defaultLightParams(mjrLightParams* params) {
params->type = mjLIGHT_POINT;
params->texture = nullptr;
params->color[0] = 0;
params->color[1] = 0;
params->color[2] = 0;
params->intensity = 0.0f;
params->cast_shadows = true;
params->range = 10.0f;
params->spot_cone_angle = 180.f;
params->bulb_radius = 0.0f;
params->shadow_map_size = 2048;
params->vsm_blur_width = 0.0f;
}
void mjr_defaultMaterialTextures(mjrMaterialTextures* textures) {
textures->color = nullptr;
textures->normal = nullptr;
textures->metallic = nullptr;
textures->roughness = nullptr;
textures->occlusion = nullptr;
textures->orm = nullptr;
textures->emissive = nullptr;
textures->reflection = nullptr;
}
void mjr_defaultMaterialParams(mjrMaterialParams* params) {
setf(params->color, {1.f, 1.f, 1.f, 1.f});
setf(params->segmentation_color, {1, 1, 1, 1});
setf(params->uv_scale, {1, 1, 1});
setf(params->uv_offset, {0, 0, 0});
setf(params->scissor, {0, 0, 0, 0});
params->emissive = -1.0f;
params->specular = -1.0f;
params->glossiness = -1.0f;
params->metallic = -1.0f;
params->roughness = -1.0f;
params->reflectance = 0.0f;
params->tex_uniform = false;
params->reflective = false;
}
void mjr_defaultRenderableParams(mjrRenderableParams* params) {
params->shading_model = mjSHADING_MODEL_SCENE_OBJECT;
}
void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config) {
config->color_format = mjPIXEL_FORMAT_RGBA8;
config->depth_format = mjPIXEL_FORMAT_DEPTH32F;
}
void mjr_defaultRenderRequest(mjrRenderRequest* request) {
memset(request, 0, sizeof(mjrRenderRequest));
}
void mjr_defaultReadPixelsRequest(mjrReadPixelsRequest* request) {
memset(request, 0, sizeof(mjrReadPixelsRequest));
}
void mjrf_makeFilamentContext(const mjModel* m, mjrContext* con, void mjrf_makeFilamentContext(const mjModel* m, mjrContext* con,
const mjrFilamentConfig* config) { const mjrFilamentConfig* config) {
// TODO: Support multiple contexts and multiple threads. For now, we'll just // TODO: Support multiple contexts and multiple threads. For now, we'll just
@@ -40,12 +40,334 @@ struct mjrRenderTarget {};
// Opaque type for the filament rendering context. // Opaque type for the filament rendering context.
struct mjrfContext {}; struct mjrfContext {};
// The different modes that can be used to render a scene.
typedef enum mjrDrawMode_ {
// Render the scene with "normal" colors and lighting.
mjDRAW_MODE_COLOR,
// Render the scene as a grayscale depth map.
mjDRAW_MODE_DEPTH,
// Render each object with a unique, uniform (flat) color regardless of
// lighting and texture.
mjDRAW_MODE_SEGMENTATION,
} mjrDrawMode;
enum { mjNUM_DRAW_MODES = 3 };
// The shading model (material) for a Renderable.
typedef enum mjrShadingModel_ {
// For renderables in the main 3D scene.
mjSHADING_MODEL_SCENE_OBJECT = 0,
// For UX renderables.
mjSHADING_MODEL_UX,
// For decorative elements in a Scene (e.g. contact points, force vectors,
// etc.). These objects will not be affected by lighting.
mjSHADING_MODEL_DECOR,
// As above, but uses a line primitives for drawing.
mjSHADING_MODEL_DECOR_LINES,
} mjrShadingModel;
// The type of data stored in an index buffer.
typedef enum mjrIndexType_ {
mjINDEX_TYPE_U16 = 0,
mjINDEX_TYPE_U32,
} mjrIndexType;
// The type of primitive to be drawn by vertex data.
typedef enum mjrMeshPrimitiveType_ {
mjMESH_PRIMITIVE_TYPE_TRIANGLES = 0,
mjMESH_PRIMITIVE_TYPE_LINES,
} mjrMeshPrimitiveType;
// The usage/purpose of an attribute of a vertex.
typedef enum mjrVertexAttributeUsage_ {
mjVERTEX_ATTRIBUTE_USAGE_POSITION = 0,
mjVERTEX_ATTRIBUTE_USAGE_NORMAL,
mjVERTEX_ATTRIBUTE_USAGE_TANGENTS,
mjVERTEX_ATTRIBUTE_USAGE_UV,
mjVERTEX_ATTRIBUTE_USAGE_COLOR,
} mjrVertexAttributeUsage;
// The data format of an attribute of a vertex.
typedef enum mjrVertexAttributeType_ {
mjVERTEX_ATTRIBUTE_TYPE_FLOAT2 = 0,
mjVERTEX_ATTRIBUTE_TYPE_FLOAT3,
mjVERTEX_ATTRIBUTE_TYPE_FLOAT4,
mjVERTEX_ATTRIBUTE_TYPE_UBYTE4,
} mjrVertexAttributeType;
// Pixel formats for textures.
typedef enum mjrPixelFormat_ {
mjPIXEL_FORMAT_UNKNOWN = 0,
mjPIXEL_FORMAT_R8,
mjPIXEL_FORMAT_RGB8,
mjPIXEL_FORMAT_RGBA8,
mjPIXEL_FORMAT_R32F,
mjPIXEL_FORMAT_DEPTH32F,
mjPIXEL_FORMAT_KTX,
} mjrPixelFormat;
typedef enum mjrGraphicsApi_ { // backend graphics API to use typedef enum mjrGraphicsApi_ { // backend graphics API to use
mjGRAPHICS_API_DEFAULT = 0, // default based on platform mjGRAPHICS_API_DEFAULT = 0, // default based on platform
mjGRAPHICS_API_OPENGL, // OpenGL (desktop) / WebGL mjGRAPHICS_API_OPENGL, // OpenGL (desktop) / WebGL
mjGRAPHICS_API_VULKAN // Vulkan mjGRAPHICS_API_VULKAN // Vulkan
} mjrGraphicsApi; } mjrGraphicsApi;
// Rendering is asynchronous by nature. Each render request is assigned a
// unique Handle which can be used to query the status of the request. The
// Handle can also be used to block until the request is completed.
typedef std::uint64_t mjrFrameHandle;
// Bring some legacy mjt types into the mjr namespace.
typedef mjtTexture mjrTextureTarget;
typedef mjtColorSpace mjrColorSpace;
typedef mjtLightType mjrLightType;
// The textures that can be assigned to the drawable's material.
struct mjrMaterialTextures {
const mjrTexture* color;
const mjrTexture* normal;
const mjrTexture* metallic;
const mjrTexture* roughness;
const mjrTexture* occlusion;
const mjrTexture* orm;
const mjrTexture* emissive;
const mjrTexture* reflection;
};
// Initializes the mjrMaterialTextures to default values.
void mjr_defaultMaterialTextures(mjrMaterialTextures* textures);
// The parameters that can be applied to the drawable's material.
struct mjrMaterialParams {
float color[4];
float segmentation_color[4];
float tex_repeat[2];
float uv_scale[3];
float uv_offset[3];
float scissor[4];
float specular;
float glossiness;
float metallic;
float roughness;
float emissive;
float reflectance;
mjtByte tex_uniform;
mjtByte reflective;
};
// Initializes the mjrMaterialParams to default values.
void mjr_defaultMaterialParams(mjrMaterialParams* params);
// The binary contents of a texture.
struct mjrTextureData {
// Pointer to the image data. If null, an empty texture will be created.
const void* bytes;
// The number of bytes in the image data.
mjtSize nbytes;
// Because rendering may be multithreaded, we cannot make assumptions about
// when the image data will finish uploading to the GPU. As such, we will use
// this callback to notify callers when it is safe to free the image data.
void (*release_callback)(void* user_data);
// User data to pass to the release callback.
void* user_data;
};
// Initializes the mjrTextureData to default values.
void mjr_defaultTextureData(mjrTextureData* data);
// Defines the basic properties of a texture.
struct mjrTextureConfig {
// The width of the texture. For compressed textures (e.g. KTX), this is the
// number of bytes in the compressed data.
int width;
// The height of the texture. For compressed textures (e.g. KTX), this should
// be 0.
int height;
// The target of the texture (e.g. 2D, cube, etc.)
mjrTextureTarget target;
// The format of the pixels in the texture (e.g. RGB8, RGBA8, KTX, etc.)
mjrPixelFormat format;
// The color space of the texture (e.g. LINEAR, sRGB, etc.)
mjrColorSpace color_space;
};
// Initializes the mjrTextureConfig to default values.
void mjr_defaultTextureConfig(mjrTextureConfig* config);
// Configuration parameters for a Renderable.
struct mjrRenderableParams {
// The shading model to use for the Renderable.
mjrShadingModel shading_model;
};
// Initializes the mjrRenderableParams to default values.
void mjr_defaultRenderableParams(mjrRenderableParams* params);
// Information about a single attribute of a vertex.
struct mjrVertexAttribute {
// The data for the attribute.
const void* bytes;
// The usage/purpose of the attribute.
mjrVertexAttributeUsage usage;
// The data format of the attribute.
mjrVertexAttributeType type;
};
// Maximum number of vertex attributes in a mesh.
enum { mjMAX_VERTEX_ATTRIBUTES = 16 };
// The binary contents of a mesh.
struct mjrMeshData {
// The number of vertices in the mesh. Each of the vertex arrays below is
// assumed to have this number of elements.
mjtSize nvertices;
// The number of attributes for each vertex in the mesh.
int nattributes;
// Information about each attribute of a vertex in the mesh. See `interleaved`
// for more details.
mjrVertexAttribute attributes[mjMAX_VERTEX_ATTRIBUTES];
// Whether the vertex attributes are interleaved or not.
//
// If true, assumes that the attributes are packed in the order specified in
// the attributes array, with no padding in-between. Additionally, the
// `data` pointer for each attribute is assumed to point to the first element
// of that type.
//
// If false, assume each attribute is stored in a separate array as defined
// by the `data` field of the attribute.
mjtByte interleaved;
// The number of indices in the mesh. The indices array is assumed to have
// this number of elements.
mjtSize nindices;
// The indices of the mesh, stored as either ushort or uint depending on the
// index type.
const void* indices;
// The type of data stored in the indices array.
mjrIndexType index_type;
// The type of primitive to be drawn by vertex data.
mjrMeshPrimitiveType primitive_type;
// Whether to compute the bounds of the mesh using the vertex positions.
mjtByte compute_bounds;
// The bounds of the mesh. If bounds_min == bounds_max, then we assume that
// that the bounds are not set (i.e. the bounds is empty).
float bounds_min[3];
float bounds_max[3];
// Because rendering may be multithreaded, we cannot make assumptions about
// when the mesh data will finish uploading to the GPU. As such, we will use
// this callback to notify callers when it is safe to free the mesh data.
void (*release_callback)(void* user_data);
// User data to pass to the release callback.
void* user_data;
};
// Initializes the mjrMeshData to default values.
void mjr_defaultMeshData(mjrMeshData* data);
// Configuration parameters for a light.
struct mjrLightParams {
// The type of light (e.g. spot, point, directional, etc.)
mjrLightType type;
// The texture to use for image lights.
const mjrTexture* texture;
// The color of the light.
float color[3];
// The intensity of the light, in candela.
float intensity;
// Whether or not the light casts shadows.
mjtByte cast_shadows;
// The range/distance in which the light is effective, in meters.
float range;
// The angle of the spot light cone, in degrees.
float spot_cone_angle;
// The radius of the bulb used for soft shadows.
float bulb_radius;
// The size of the shadow map.
int shadow_map_size;
// Blur width for EL VSM.
float vsm_blur_width;
};
// Initializes the mjrLightParams to default values.
void mjr_defaultLightParams(mjrLightParams* params);
// Defines the basic properties of a render target.
struct mjrRenderTargetConfig {
mjrPixelFormat color_format;
mjrPixelFormat depth_format;
};
// Initializes the RenderTargetConfig to default values.
void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config);
// Information needed to render a single image of a scene.
struct mjrRenderRequest {
// The scene to render.
mjrScene* scene;
// The method (e.g. Color, Depth, Segmentation, etc.) to use for rendering.
mjrDrawMode draw_mode;
// The camera from which to render the scene.
mjvGLCamera camera;
// The dimensions of the output image.
int width;
int height;
// The render target into which to render the image. If nullptr, the image
// will be rendered to the window (as previously configured in
// mjrFilamentConfig::native_window).
mjrRenderTarget* target;
};
// Initializes the mjrRenderRequest to default values.
void mjr_defaultRenderRequest(mjrRenderRequest* request);
// Information needed to read pixels from a render target.
struct mjrReadPixelsRequest {
mjrRenderTarget* target;
// The buffer into which the read pixels will be written.
void* output;
// The number of bytes in the output buffer. This should match the size of
// the render target texture.
mjtSize num_bytes;
// Callback when the read pixels operation is complete. This will be called
// during WaitForFrame() or in a subsequent call to Render(). This function
// can optionally be used to free the output buffer if needed.
void (*read_completed_callback)(void* user_data);
// User data to pass to the completion callback.
void* user_data;
};
// Initializes the mjrReadPixelsRequest to default values.
void mjr_defaultReadPixelsRequest(mjrReadPixelsRequest* request);
// Configuration parameters for the filament rendering context.
struct mjrFilamentConfig { struct mjrFilamentConfig {
// The native window handle into which we can render directly. // The native window handle into which we can render directly.
void* native_window; void* native_window;