diff --git a/src/experimental/filament/compat/mjr_filament_renderer.cc b/src/experimental/filament/compat/mjr_filament_renderer.cc index 48242258..8953e2a2 100644 --- a/src/experimental/filament/compat/mjr_filament_renderer.cc +++ b/src/experimental/filament/compat/mjr_filament_renderer.cc @@ -25,7 +25,6 @@ #include "experimental/filament/compat/imgui_bridge.h" #include "experimental/filament/compat/imgui_editor.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/model_util.h" #include "experimental/filament/filament/render_target.h" @@ -42,11 +41,14 @@ void MjrFilamentRenderer::Init(const mjModel* model) { scene_bridge_ = std::make_unique(GetObjectManager(), model); imgui_bridge_ = std::make_unique(GetObjectManager()); + mjr_defaultRenderRequest(&render_requests_[0]); + mjr_defaultRenderRequest(&render_requests_[1]); + 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].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 // 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]) { - render_requests_[0].draw_mode = DrawMode::Segmentation; + render_requests_[0].draw_mode = mjDRAW_MODE_SEGMENTATION; } else if (scene->flags[mjRND_DEPTH]) { - render_requests_[0].draw_mode = DrawMode::Depth; + render_requests_[0].draw_mode = mjDRAW_MODE_DEPTH; } else { - render_requests_[0].draw_mode = DrawMode::Color; + render_requests_[0].draw_mode = mjDRAW_MODE_COLOR; } render_requests_[0].width = viewport.width; @@ -142,10 +144,11 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb, const size_t num_requests = (mode_ == FrameBufferMode::OffScreenWithGui) ? 2 : 1; - ReadPixelsRequest read_request; + mjrReadPixelsRequest read_request; + mjr_defaultReadPixelsRequest(&read_request); read_request.output = rgb; 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}); FilamentContext::WaitForFrame(frame); @@ -163,13 +166,14 @@ void MjrFilamentRenderer::ReadPixels(mjrRect viewport, unsigned char* rgb, render_requests_[0].target = target.get(); render_requests_[1].target = target.get(); - DrawMode last_draw_mode = render_requests_[0].draw_mode; - render_requests_[0].draw_mode = DrawMode::Depth; + mjrDrawMode last_draw_mode = render_requests_[0].draw_mode; + render_requests_[0].draw_mode = mjDRAW_MODE_DEPTH; - ReadPixelsRequest read_request; + mjrReadPixelsRequest read_request; + mjr_defaultReadPixelsRequest(&read_request); read_request.output = reinterpret_cast(depth); 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::WaitForFrame(frame); diff --git a/src/experimental/filament/compat/mjr_filament_renderer.h b/src/experimental/filament/compat/mjr_filament_renderer.h index a1c97edc..3d87e624 100644 --- a/src/experimental/filament/compat/mjr_filament_renderer.h +++ b/src/experimental/filament/compat/mjr_filament_renderer.h @@ -76,7 +76,7 @@ class MjrFilamentRenderer : public FilamentContext { }; FrameBufferMode mode_ = FrameBufferMode::Window; - RenderRequest render_requests_[2]; + mjrRenderRequest render_requests_[2]; std::unique_ptr scene_bridge_; std::unique_ptr imgui_bridge_; }; diff --git a/src/experimental/filament/compat/scene_geom_util.cc b/src/experimental/filament/compat/scene_geom_util.cc index 527fe56f..ddc85bee 100644 --- a/src/experimental/filament/compat/scene_geom_util.cc +++ b/src/experimental/filament/compat/scene_geom_util.cc @@ -30,12 +30,12 @@ #include #include #include "experimental/filament/compat/model_objects.h" -#include "experimental/filament/filament/material.h" #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/object_manager.h" #include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -424,7 +424,7 @@ static void UpdateGeomMaterial(Renderable& renderable, const mjvGeom& geom, // the programmatic UVs. if (textures.color) { - if (textures.color->GetFilamentTexture()->getTarget() == + if (Texture::downcast(textures.color)->GetFilamentTexture()->getTarget() == filament::Texture::Sampler::SAMPLER_2D) { // For 2D textures, `tex_repeat` specifies how many times the texture // image is repeated. The `tex_uniform` flag determines if the repetition diff --git a/src/experimental/filament/filament/draw_mode.h b/src/experimental/filament/filament/draw_mode.h deleted file mode 100644 index 15bb2bca..00000000 --- a/src/experimental/filament/filament/draw_mode.h +++ /dev/null @@ -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_ diff --git a/src/experimental/filament/filament/filament_context.cc b/src/experimental/filament/filament/filament_context.cc index 906c32e3..4149559c 100644 --- a/src/experimental/filament/filament/filament_context.cc +++ b/src/experimental/filament/filament/filament_context.cc @@ -79,16 +79,16 @@ FilamentContext::~FilamentContext() { filament::Engine::destroy(engine_); } -FilamentContext::FrameHandle FilamentContext::Render( - std::span requests, - std::span read_requests) { +mjrFrameHandle FilamentContext::Render( + std::span requests, + std::span read_requests) { if (read_requests.size() > 1) { mju_error("Only one read request is supported for now."); } bool render_began = false; mjrRenderTarget* current_target = nullptr; - for (const RenderRequest& request : requests) { + for (const mjrRenderRequest& request : requests) { if (request.target != current_target && render_began) { renderer_->endFrame(); render_began = false; @@ -135,7 +135,7 @@ FilamentContext::FrameHandle FilamentContext::Render( "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) { mju_error("Output buffer size is zero."); } @@ -156,7 +156,7 @@ FilamentContext::FrameHandle FilamentContext::Render( scene_view_request.target = render_target; SceneView* scene_view = SceneView::downcast(request.scene); 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); } } @@ -179,7 +179,7 @@ FilamentContext::FrameHandle FilamentContext::Render( return ++frame_counter_; } -void FilamentContext::WaitForFrame(FrameHandle frame_handle) { +void FilamentContext::WaitForFrame(mjrFrameHandle frame_handle) { if (frame_counter_ < frame_handle) { engine_->flushAndWait(); } diff --git a/src/experimental/filament/filament/filament_context.h b/src/experimental/filament/filament/filament_context.h index 2e98acaf..732229e0 100644 --- a/src/experimental/filament/filament/filament_context.h +++ b/src/experimental/filament/filament/filament_context.h @@ -15,7 +15,6 @@ #ifndef MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_FILAMENT_CONTEXT_H_ -#include #include #include #include @@ -25,11 +24,7 @@ #include #include #include -#include -#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/render_target.h" #include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -43,62 +38,16 @@ class FilamentContext : public mjrfContext { FilamentContext(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 // necessary data from the requests into the renderer thread and returns // immediately afterwards. The renderer thread will then perform the actual // rendering on the GPU. Callers can use WaitForFrame to block until the // rendering is complete. - FrameHandle Render(std::span render_requests, - std::span read_requests = {}); + mjrFrameHandle Render(std::span render_requests, + std::span read_requests = {}); // 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. void SetClearColor(const filament::math::float4& color); diff --git a/src/experimental/filament/filament/light.cc b/src/experimental/filament/filament/light.cc index d79a1551..2918f0a0 100644 --- a/src/experimental/filament/filament/light.cc +++ b/src/experimental/filament/filament/light.cc @@ -27,27 +27,13 @@ #include #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { using filament::math::float3; 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) : engine_(engine), params_(params) { // Filament treats image-based lights (IBLs) as separate objects (i.e. diff --git a/src/experimental/filament/filament/light.h b/src/experimental/filament/filament/light.h index d58dbdd0..d0b6a884 100644 --- a/src/experimental/filament/filament/light.h +++ b/src/experimental/filament/filament/light.h @@ -20,39 +20,10 @@ #include #include #include -#include "experimental/filament/filament/texture.h" #include "experimental/filament/render_context_filament.h" 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. class Light : public mjrLight { public: diff --git a/src/experimental/filament/filament/material.cc b/src/experimental/filament/filament/material.cc index fcdc54fa..925e88fb 100644 --- a/src/experimental/filament/filament/material.cc +++ b/src/experimental/filament/filament/material.cc @@ -14,8 +14,6 @@ #include "experimental/filament/filament/material.h" -#include - #include #include #include @@ -25,45 +23,10 @@ #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/object_manager.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { -template -static void setf(float (&arr)[N], const std::array& 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, const mjrMaterialParams& params, const mjrMaterialTextures& textures, @@ -118,11 +81,12 @@ void UpdateMaterialInstance(filament::MaterialInstance* instance, sampler.setMinFilter( filament::TextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR); - auto TrySetTexture = [&](const char* name, const Texture* texture, + auto TrySetTexture = [&](const char* name, const mjrTexture* texture, mjtTextureRole role) { if (material->hasParameter(name)) { if (texture != nullptr) { - instance->setParameter(name, texture->GetFilamentTexture(), sampler); + instance->setParameter( + name, Texture::downcast(texture)->GetFilamentTexture(), sampler); } else { instance->setParameter(name, object_mgr->GetFallbackTexture(role), sampler); diff --git a/src/experimental/filament/filament/material.h b/src/experimental/filament/filament/material.h index 630f4844..abc0f9a1 100644 --- a/src/experimental/filament/filament/material.h +++ b/src/experimental/filament/filament/material.h @@ -17,46 +17,11 @@ #include #include -#include -#include "experimental/filament/filament/texture.h" #include "experimental/filament/filament/object_manager.h" +#include "experimental/filament/render_context_filament.h" 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 // textures. void UpdateMaterialInstance(filament::MaterialInstance* instance, diff --git a/src/experimental/filament/filament/mesh.cc b/src/experimental/filament/filament/mesh.cc index 2d7a74b7..9c06cfc7 100644 --- a/src/experimental/filament/filament/mesh.cc +++ b/src/experimental/filament/filament/mesh.cc @@ -33,6 +33,7 @@ #include #include #include "experimental/filament/filament/math_util.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -101,11 +102,6 @@ int FillSequence(std::byte* buffer, std::size_t num_bytes) { 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) : engine_(engine), shared_state_(std::make_shared()) { type_ = data.primitive_type == mjMESH_PRIMITIVE_TYPE_TRIANGLES diff --git a/src/experimental/filament/filament/mesh.h b/src/experimental/filament/filament/mesh.h index 9746e4ab..206aa27d 100644 --- a/src/experimental/filament/filament/mesh.h +++ b/src/experimental/filament/filament/mesh.h @@ -16,7 +16,6 @@ #define MUJOCO_SRC_EXPERIMENTAL_FILAMENT_FILAMENT_MESH_H_ #include -#include #include #include #include @@ -30,114 +29,11 @@ #include #include #include -#include #include "experimental/filament/render_context_filament.h" // Functions for creating filament vertex and index buffers. 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. class Mesh : public mjrMesh { public: diff --git a/src/experimental/filament/filament/render_target.cc b/src/experimental/filament/filament/render_target.cc index 3e53ac51..4c083136 100644 --- a/src/experimental/filament/filament/render_target.cc +++ b/src/experimental/filament/filament/render_target.cc @@ -30,11 +30,6 @@ namespace mujoco { -void mjr_defaultRenderTargetConfig(mjrRenderTargetConfig* config) { - config->color_format = mjPIXEL_FORMAT_RGBA8; - config->depth_format = mjPIXEL_FORMAT_DEPTH32F; -} - RenderTarget::RenderTarget(filament::Engine* engine, const mjrRenderTargetConfig& config) : engine_(engine), config_(config) {} diff --git a/src/experimental/filament/filament/render_target.h b/src/experimental/filament/filament/render_target.h index 9e5aed68..92e221b3 100644 --- a/src/experimental/filament/filament/render_target.h +++ b/src/experimental/filament/filament/render_target.h @@ -26,15 +26,6 @@ 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. class RenderTarget : public mjrRenderTarget { public: diff --git a/src/experimental/filament/filament/renderable.cc b/src/experimental/filament/filament/renderable.cc index 4381cbd4..47c48849 100644 --- a/src/experimental/filament/filament/renderable.cc +++ b/src/experimental/filament/filament/renderable.cc @@ -26,20 +26,17 @@ #include #include #include -#include "experimental/filament/filament/draw_mode.h" #include "experimental/filament/filament/material.h" #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/mesh.h" #include "experimental/filament/filament/object_manager.h" +#include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { using filament::math::mat4f; -void mjr_defaultRenderableParams(mjrRenderableParams* params) { - params->shading_model = mjSHADING_MODEL_SCENE_OBJECT; -} - Renderable::Renderable(ObjectManager* object_mgr, const mjrRenderableParams& params) : object_mgr_(object_mgr), params_(params) { mjr_defaultMaterialParams(&material_params_); @@ -57,7 +54,7 @@ Renderable::~Renderable() noexcept { engine->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) { engine->destroy(instances_[i]); instances_[i] = nullptr; @@ -206,13 +203,13 @@ void Renderable::UpdateMaterial(const mjrMaterialParams& params, material_params_ = params; material_textures_ = textures; - AssignMaterial(DrawMode::Color, GetColorMaterialType()); + AssignMaterial(mjDRAW_MODE_COLOR, GetColorMaterialType()); if (params_.shading_model == mjSHADING_MODEL_SCENE_OBJECT) { - AssignMaterial(DrawMode::Depth, ObjectManager::kUnlitDepth); - AssignMaterial(DrawMode::Segmentation, ObjectManager::kUnlitSegmentation); + AssignMaterial(mjDRAW_MODE_DEPTH, ObjectManager::kUnlitDepth); + 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]) { UpdateMaterialInstance(instances_[i], material_params_, material_textures_, object_mgr_); @@ -221,7 +218,7 @@ void Renderable::UpdateMaterial(const mjrMaterialParams& params, SetDrawMode(draw_mode_); } -void Renderable::AssignMaterial(DrawMode mode, +void Renderable::AssignMaterial(mjrDrawMode mode, ObjectManager::MaterialType material_type) { const int index = static_cast(mode); @@ -248,10 +245,10 @@ const mjrMaterialTextures& Renderable::GetMaterialTextures() const { return material_textures_; } -void Renderable::SetDrawMode(DrawMode mode) { +void Renderable::SetDrawMode(mjrDrawMode mode) { // Only SceneObjects support non-color draw modes. if (params_.shading_model != mjSHADING_MODEL_SCENE_OBJECT) { - mode = DrawMode::Color; + mode = mjDRAW_MODE_COLOR; } filament::MaterialInstance* instance = instances_[static_cast(mode)]; @@ -369,6 +366,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const { // geometry) and `mesh_texcoordadr` stores the address of the mesh uvs if // it has them. bool has_texcoords = false; + const Texture* color_texture = Texture::downcast(material_textures_.color); if (!parts_.empty()) { const auto attribs = parts_[0].mesh->GetVertexAttributes(); auto it = std::find(attribs.begin(), attribs.end(), @@ -376,7 +374,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const { has_texcoords = (it != attribs.end()); } - if (material_textures_.color == nullptr) { + if (color_texture == nullptr) { if (material_params_.color[3] < 1.0f) { return ObjectManager::kPhongColorFade; } else if (material_params_.reflective) { @@ -384,7 +382,7 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const { } else { return ObjectManager::kPhongColor; } - } else if (material_textures_.color->GetFilamentTexture()->getTarget() == + } else if (color_texture->GetFilamentTexture()->getTarget() == filament::Texture::Sampler::SAMPLER_CUBEMAP) { if (material_params_.color[3] < 1.0f) { return ObjectManager::kPhongCubeFade; diff --git a/src/experimental/filament/filament/renderable.h b/src/experimental/filament/filament/renderable.h index 35f9028a..9a740a19 100644 --- a/src/experimental/filament/filament/renderable.h +++ b/src/experimental/filament/filament/renderable.h @@ -24,7 +24,6 @@ #include #include #include -#include "experimental/filament/filament/draw_mode.h" #include "experimental/filament/filament/material.h" #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/mesh.h" @@ -33,21 +32,6 @@ 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. // // 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 // with a SceneObject shading model. - void SetDrawMode(DrawMode mode); + void SetDrawMode(mjrDrawMode mode); // Updates the parameters for the material. void UpdateMaterial(const mjrMaterialParams& params, @@ -157,16 +141,16 @@ class Renderable : public mjrRenderable { 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* object_mgr_; mjrRenderableParams params_; - filament::MaterialInstance* instances_[kNumDrawModes] = {nullptr}; + filament::MaterialInstance* instances_[mjNUM_DRAW_MODES] = {nullptr}; mjrMaterialParams material_params_; mjrMaterialTextures material_textures_; - DrawMode draw_mode_ = DrawMode::Color; + mjrDrawMode draw_mode_ = mjDRAW_MODE_COLOR; filament::Scene* assigned_scene_ = nullptr; std::vector parts_; filament::math::mat4f transform_; diff --git a/src/experimental/filament/filament/scene_view.cc b/src/experimental/filament/filament/scene_view.cc index d11edc13..d361fc53 100644 --- a/src/experimental/filament/filament/scene_view.cc +++ b/src/experimental/filament/filament/scene_view.cc @@ -40,13 +40,12 @@ #include #include #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/material.h" #include "experimental/filament/filament/math_util.h" #include "experimental/filament/filament/render_target.h" #include "experimental/filament/filament/renderable.h" #include "experimental/filament/filament/texture.h" +#include "experimental/filament/render_context_filament.h" namespace mujoco { @@ -54,10 +53,6 @@ using filament::math::float3; using filament::math::float4; using filament::math::mat4; -static constexpr int kNormalIndex = static_cast(DrawMode::Color); -static constexpr int kDepthIndex = static_cast(DrawMode::Depth); -static constexpr int kSegmentIndex = static_cast(DrawMode::Segmentation); - static filament::ColorGrading::Builder ToBuilder( const ColorGradingOptions& opts) { 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 // the values. - views_[kDepthIndex]->setPostProcessingEnabled(false); - views_[kSegmentIndex]->setPostProcessingEnabled(false); + views_[mjDRAW_MODE_DEPTH]->setPostProcessingEnabled(false); + views_[mjDRAW_MODE_SEGMENTATION]->setPostProcessingEnabled(false); // 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(); tm.create(fog); tm.setTransform(tm.getInstance(fog), @@ -255,7 +250,7 @@ void SceneView::Render(filament::Renderer* renderer, } // 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) { Renderable* renderable = reflectives_[i]; @@ -317,7 +312,7 @@ void SceneView::SetColorGradingOptions(const ColorGradingOptions& opts) { auto color_grading = ToBuilder(color_grading_options_) .toneMapper(tone_mapper.get()) .build(*engine_); - views_[kNormalIndex]->setColorGrading(color_grading); + views_[mjDRAW_MODE_COLOR]->setColorGrading(color_grading); if (color_grading_) { engine_->destroy(color_grading_); } @@ -326,11 +321,11 @@ void SceneView::SetColorGradingOptions(const ColorGradingOptions& opts) { } void SceneView::EnableShadows() { - views_[kNormalIndex]->setShadowingEnabled(true); + views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(true); } void SceneView::DisableShadows() { - views_[kNormalIndex]->setShadowingEnabled(false); + views_[mjDRAW_MODE_COLOR]->setShadowingEnabled(false); } void SceneView::EnableReflections() { @@ -351,19 +346,18 @@ void SceneView::DisableReflections() { textures.reflection = nullptr; renderable->UpdateMaterial(renderable->GetMaterialParams(), textures); } - } void SceneView::EnablePostProcessing() { - views_[kNormalIndex]->setPostProcessingEnabled(true); + views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(true); } void SceneView::DisablePostProcessing() { - views_[kNormalIndex]->setPostProcessingEnabled(false); + views_[mjDRAW_MODE_COLOR]->setPostProcessingEnabled(false); } filament::View* SceneView::GetDefaultRenderView() { - return views_[kNormalIndex]; + return views_[mjDRAW_MODE_COLOR]; } ColorGradingOptions SceneView::GetColorGradingOptions() const { diff --git a/src/experimental/filament/filament/scene_view.h b/src/experimental/filament/filament/scene_view.h index f35110f8..d23a6ab2 100644 --- a/src/experimental/filament/filament/scene_view.h +++ b/src/experimental/filament/filament/scene_view.h @@ -27,7 +27,6 @@ #include #include #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/renderable.h" #include "experimental/filament/filament/render_target.h" @@ -59,7 +58,7 @@ class SceneView : public mjrScene { // Parameters for rendering the scene. struct RenderRequest { // 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. mjrRect viewport; // The camera from which to render the scene. @@ -111,7 +110,7 @@ class SceneView : public mjrScene { filament::Camera* camera_ = nullptr; filament::ColorGrading* color_grading_ = nullptr; ColorGradingOptions color_grading_options_; - std::array views_; + std::array views_; // Scene objects. std::unordered_set lights_; diff --git a/src/experimental/filament/filament/texture.cc b/src/experimental/filament/filament/texture.cc index 81b37448..f27b89a6 100644 --- a/src/experimental/filament/filament/texture.cc +++ b/src/experimental/filament/filament/texture.cc @@ -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, InternalFlags flags) : engine_(engine), config_(config) { diff --git a/src/experimental/filament/filament/texture.h b/src/experimental/filament/filament/texture.h index 764ae911..e5b7f305 100644 --- a/src/experimental/filament/filament/texture.h +++ b/src/experimental/filament/filament/texture.h @@ -25,63 +25,6 @@ // Functions for creating filament textures. 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. class Texture : public mjrTexture { public: diff --git a/src/experimental/filament/render_context_filament.cc b/src/experimental/filament/render_context_filament.cc index 65b4086a..30891f5a 100644 --- a/src/experimental/filament/render_context_filament.cc +++ b/src/experimental/filament/render_context_filament.cc @@ -14,6 +14,7 @@ #include "experimental/filament/render_context_filament.h" +#include #include #include @@ -36,12 +37,91 @@ static void CheckFilamentContext() { } } +template +static void setf(float (&arr)[N], const std::array& values) { + for (int i = 0; i < N; ++i) { + arr[i] = values[i]; + } +} + + extern "C" { void mjrf_defaultFilamentConfig(mjrFilamentConfig* config) { 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, const mjrFilamentConfig* config) { // TODO: Support multiple contexts and multiple threads. For now, we'll just diff --git a/src/experimental/filament/render_context_filament.h b/src/experimental/filament/render_context_filament.h index ef6f88ea..e338a55c 100644 --- a/src/experimental/filament/render_context_filament.h +++ b/src/experimental/filament/render_context_filament.h @@ -40,12 +40,334 @@ struct mjrRenderTarget {}; // Opaque type for the filament rendering context. 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 mjGRAPHICS_API_DEFAULT = 0, // default based on platform mjGRAPHICS_API_OPENGL, // OpenGL (desktop) / WebGL mjGRAPHICS_API_VULKAN // Vulkan } 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 { // The native window handle into which we can render directly. void* native_window;