Simplify materials.

Merge shading model, material params, and material textures into a
single "mjrMaterial" type.

Remove redundant decor_line material.

PiperOrigin-RevId: 911960222
Change-Id: Icce3772a8ea48467dfd610799c0c2f2ba752323e
This commit is contained in:
Haroon Qureshi
2026-05-07 07:50:30 -07:00
committed by Copybara-Service
parent d5c5a989f2
commit abea65b0be
14 changed files with 228 additions and 285 deletions
-1
View File
@@ -117,7 +117,6 @@ set(MATERIAL_FILES
phong_cube_reflect.mat phong_cube_reflect.mat
unlit_decor.mat unlit_decor.mat
unlit_depth.mat unlit_depth.mat
unlit_line.mat
unlit_segmentation.mat unlit_segmentation.mat
unlit_ui.mat unlit_ui.mat
) )
@@ -1,29 +0,0 @@
// Copyright 2025 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.
material {
name : unlit_segmentation,
shadingModel : unlit,
culling: none,
parameters : [
{ type : float4, name : BaseColorFactor }
]
}
fragment {
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = materialParams.BaseColorFactor;
}
}
@@ -253,26 +253,25 @@ void ImguiBridge::Update() {
mjrf_setRenderableMesh(renderable.get(), mesh, index_offset, mjrf_setRenderableMesh(renderable.get(), mesh, index_offset,
command.ElemCount); command.ElemCount);
mjrMaterialTextures textures; mjrMaterial material;
mjr_defaultMaterialTextures(&textures); mjr_defaultMaterial(&material);
textures.color = GetTexture(command.GetTexID()); material.color_texture = GetTexture(command.GetTexID());
mjrMaterialParams properties; material.decor_ux = true;
mjr_defaultMaterialParams(&properties); material.scissor[0] = command.ClipRect.x;
properties.scissor[0] = command.ClipRect.x; material.scissor[1] = height - command.ClipRect.w;
properties.scissor[1] = height - command.ClipRect.w; material.scissor[2] = command.ClipRect.z - command.ClipRect.x;
properties.scissor[2] = command.ClipRect.z - command.ClipRect.x; material.scissor[3] = command.ClipRect.w - command.ClipRect.y;
properties.scissor[3] = command.ClipRect.w - command.ClipRect.y;
// Modal dialogs try to cover the whole window, but also a little outside // Modal dialogs try to cover the whole window, but also a little outside
// of it. This doesn't work well with filament's scissor test, so we clip // of it. This doesn't work well with filament's scissor test, so we clip
// them to the window. // them to the window.
if (properties.scissor[0] < 0 || properties.scissor[1] < 0) { if (material.scissor[0] < 0 || material.scissor[1] < 0) {
properties.scissor[0] = 0; material.scissor[0] = 0;
properties.scissor[1] = 0; material.scissor[1] = 0;
properties.scissor[2] = width; material.scissor[2] = width;
properties.scissor[3] = height; material.scissor[3] = height;
} }
mjrf_setRenderableMaterial(renderable.get(), &properties, &textures); mjrf_setRenderableMaterial(renderable.get(), &material);
const float position[] = {0, 0, 0}; const float position[] = {0, 0, 0};
const float rotation[] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; const float rotation[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
@@ -289,7 +288,6 @@ void ImguiBridge::PrepareRenderables(int count) {
while (renderables_.size() < count) { while (renderables_.size() < count) {
mjrRenderableParams params; mjrRenderableParams params;
mjr_defaultRenderableParams(&params); mjr_defaultRenderableParams(&params);
params.shading_model = mjSHADING_MODEL_UX;
params.cast_shadows = false; params.cast_shadows = false;
params.receive_shadows = false; params.receive_shadows = false;
params.blend_order = static_cast<std::uint16_t>(renderables_.size() + 1); params.blend_order = static_cast<std::uint16_t>(renderables_.size() + 1);
@@ -183,20 +183,25 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
const mjModel* model = model_objs->GetModel(); const mjModel* model = model_objs->GetModel();
const bool use_segid_color = scene->flags[mjRND_IDCOLOR]; const bool use_segid_color = scene->flags[mjRND_IDCOLOR];
mjrMaterialParams params; mjrMaterial material;
mjr_defaultMaterialParams(&params); mjr_defaultMaterial(&material);
params.color[0] = geom.rgba[0];
params.color[1] = geom.rgba[1]; if (geom.category == mjCAT_DECOR) {
params.color[2] = geom.rgba[2]; material.decor_ux = true;
params.color[3] = geom.rgba[3]; }
material.color[0] = geom.rgba[0];
material.color[1] = geom.rgba[1];
material.color[2] = geom.rgba[2];
material.color[3] = geom.rgba[3];
if (geom.type == mjGEOM_PLANE) { if (geom.type == mjGEOM_PLANE) {
if (IsBehind(headpos, geom.pos, geom.mat)) { if (IsBehind(headpos, geom.pos, geom.mat)) {
params.color[3] *= 0.3; material.color[3] *= 0.3;
mjrf_setRenderableReceiveShadows(renderable, false); mjrf_setRenderableReceiveShadows(renderable, false);
params.reflective = false; material.reflective = false;
} else { } else {
mjrf_setRenderableReceiveShadows(renderable, true); mjrf_setRenderableReceiveShadows(renderable, true);
params.reflective = geom.reflectance > 0 && params.color[3] == 1.0f; material.reflective = geom.reflectance > 0 && material.color[3] == 1.0f;
} }
} }
mjrf_setRenderableLayerMask(renderable, geom.category); mjrf_setRenderableLayerMask(renderable, geom.category);
@@ -207,30 +212,28 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
mjrf_setRenderableWireframe(renderable, scene->flags[mjRND_WIREFRAME]); mjrf_setRenderableWireframe(renderable, scene->flags[mjRND_WIREFRAME]);
} }
mjrMaterialTextures textures;
mjr_defaultMaterialTextures(&textures);
if (geom.matid >= 0) { if (geom.matid >= 0) {
textures.color = model_objs->GetTexture(geom.matid, mjTEXROLE_RGB); material.color_texture = model_objs->GetTexture(geom.matid, mjTEXROLE_RGB);
textures.normal = model_objs->GetTexture(geom.matid, mjTEXROLE_NORMAL); material.normal_texture =
textures.emissive = model_objs->GetTexture(geom.matid, mjTEXROLE_EMISSIVE); model_objs->GetTexture(geom.matid, mjTEXROLE_NORMAL);
textures.orm = model_objs->GetTexture(geom.matid, mjTEXROLE_ORM); material.emissive_texture =
textures.metallic = model_objs->GetTexture(geom.matid, mjTEXROLE_METALLIC); model_objs->GetTexture(geom.matid, mjTEXROLE_EMISSIVE);
textures.roughness = material.orm_texture = model_objs->GetTexture(geom.matid, mjTEXROLE_ORM);
material.metallic_texture =
model_objs->GetTexture(geom.matid, mjTEXROLE_METALLIC);
material.roughness_texture =
model_objs->GetTexture(geom.matid, mjTEXROLE_ROUGHNESS); model_objs->GetTexture(geom.matid, mjTEXROLE_ROUGHNESS);
textures.occlusion = material.occlusion_texture =
model_objs->GetTexture(geom.matid, mjTEXROLE_OCCLUSION); model_objs->GetTexture(geom.matid, mjTEXROLE_OCCLUSION);
} }
params.reflectance = geom.reflectance; material.reflectance = geom.reflectance;
params.emissive = geom.emission; material.emissive = geom.emission;
params.specular = geom.specular; material.specular = geom.specular;
params.glossiness = geom.shininess; material.glossiness = geom.shininess;
if (geom.matid >= 0) { if (geom.matid >= 0) {
params.metallic = model->mat_metallic[geom.matid]; material.metallic = model->mat_metallic[geom.matid];
params.roughness = model->mat_roughness[geom.matid]; material.roughness = model->mat_roughness[geom.matid];
params.tex_uniform = model->mat_texuniform[geom.matid];
params.tex_repeat[0] = model->mat_texrepeat[(geom.matid * 2) + 0];
params.tex_repeat[1] = model->mat_texrepeat[(geom.matid * 2) + 1];
} }
if (geom.segid >= 0) { if (geom.segid >= 0) {
@@ -246,9 +249,9 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
const uint8_t red = (segmentation_color >> 0) & 0xff; const uint8_t red = (segmentation_color >> 0) & 0xff;
const uint8_t green = (segmentation_color >> 8) & 0xff; const uint8_t green = (segmentation_color >> 8) & 0xff;
const uint8_t blue = (segmentation_color >> 16) & 0xff; const uint8_t blue = (segmentation_color >> 16) & 0xff;
params.segmentation_color[0] = static_cast<float>(red) / 255.0f; material.segmentation_color[0] = static_cast<float>(red) / 255.0f;
params.segmentation_color[1] = static_cast<float>(green) / 255.0f; material.segmentation_color[1] = static_cast<float>(green) / 255.0f;
params.segmentation_color[2] = static_cast<float>(blue) / 255.0f; material.segmentation_color[2] = static_cast<float>(blue) / 255.0f;
} }
// UvScale only applies to objects that don't have explicit UV coordinates // UvScale only applies to objects that don't have explicit UV coordinates
@@ -258,28 +261,33 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
// The material's `texuniform` and `texrepeat` parameters allow us to scale // The material's `texuniform` and `texrepeat` parameters allow us to scale
// the programmatic UVs. // the programmatic UVs.
if (textures.color) { if (material.color_texture) {
if (mjrf_getSamplerType(textures.color) == mjTEXTURE_2D) { const bool tex_uniform = model->mat_texuniform[geom.matid];
if (mjrf_getSamplerType(material.color_texture) == mjTEXTURE_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
// is applied at in object space (false) or in world space (true). // is applied at in object space (false) or in world space (true).
params.uv_scale[0] = params.tex_repeat[0]; float tex_repeat[2];
params.uv_scale[1] = params.tex_repeat[1]; tex_repeat[0] = model->mat_texrepeat[(geom.matid * 2) + 0];
tex_repeat[1] = model->mat_texrepeat[(geom.matid * 2) + 1];
material.uv_scale[0] = tex_repeat[0];
material.uv_scale[1] = tex_repeat[1];
if (geom.dataid >= 0 && geom.type != mjGEOM_PLANE) { if (geom.dataid >= 0 && geom.type != mjGEOM_PLANE) {
if (geom.size[0] > mjMINVAL) { if (geom.size[0] > mjMINVAL) {
params.uv_scale[0] /= geom.size[0]; material.uv_scale[0] /= geom.size[0];
} }
if (geom.size[1] > mjMINVAL) { if (geom.size[1] > mjMINVAL) {
params.uv_scale[1] /= geom.size[1]; material.uv_scale[1] /= geom.size[1];
} }
} }
if (params.tex_uniform) {
if (tex_uniform) {
if (geom.size[0] > 0) { if (geom.size[0] > 0) {
params.uv_scale[0] *= geom.size[0]; material.uv_scale[0] *= geom.size[0];
} }
if (geom.size[1] > 0) { if (geom.size[1] > 0) {
params.uv_scale[1] *= geom.size[1]; material.uv_scale[1] *= geom.size[1];
} }
} }
const bool is_infinite_plane = const bool is_infinite_plane =
@@ -289,11 +297,11 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
// re-centering in engine_vis_visualize.c. // re-centering in engine_vis_visualize.c.
const float plane_scale = static_cast<float>(mjMAXPLANEGRID) / 2.0f; const float plane_scale = static_cast<float>(mjMAXPLANEGRID) / 2.0f;
const float tile_size_x = const float tile_size_x =
GetPlaneTileSize(model, geom.matid, params.tex_repeat[0]); GetPlaneTileSize(model, geom.matid, tex_repeat[0]);
const float tile_size_y = const float tile_size_y =
GetPlaneTileSize(model, geom.matid, params.tex_repeat[1]); GetPlaneTileSize(model, geom.matid, tex_repeat[1]);
params.uv_scale[0] = 2.0f * plane_scale / tile_size_x; material.uv_scale[0] = 2.0f * plane_scale / tile_size_x;
params.uv_scale[1] = 2.0f * plane_scale / tile_size_y; material.uv_scale[1] = 2.0f * plane_scale / tile_size_y;
} }
// We want to do the equivalent of: // We want to do the equivalent of:
@@ -301,42 +309,34 @@ static void UpdateGeomMaterial(mjrRenderable* renderable, const mjvGeom& geom,
// mjr_setf4(tplane, 0, -0.5 * scl.y, 0, -0.5); // mjr_setf4(tplane, 0, -0.5 * scl.y, 0, -0.5);
// glTexGenfv(GL_S, GL_OBJECT_PLANE, splane); // glTexGenfv(GL_S, GL_OBJECT_PLANE, splane);
// glTexGenfv(GL_T, GL_OBJECT_PLANE, tplane); // glTexGenfv(GL_T, GL_OBJECT_PLANE, tplane);
params.uv_scale[0] = 0.5f * params.uv_scale[0]; material.uv_scale[0] = 0.5f * material.uv_scale[0];
params.uv_scale[1] = -0.5f * params.uv_scale[1]; material.uv_scale[1] = -0.5f * material.uv_scale[1];
params.uv_offset[0] = -0.5f; material.uv_offset[0] = -0.5f;
params.uv_offset[1] = -0.5f; material.uv_offset[1] = -0.5f;
} else { } else {
// For cube maps, if `tex_uniform` is true, then scale the texture so that // For cube maps, if `tex_uniform` is true, then scale the texture so that
// it covers a 1x1 area of world space rather than the area of the object. // it covers a 1x1 area of world space rather than the area of the object.
if (params.tex_uniform) { if (tex_uniform) {
params.uv_scale[0] = 1.0f / (geom.size[0] ? geom.size[0] : 1.0f); material.uv_scale[0] = 1.0f / (geom.size[0] ? geom.size[0] : 1.0f);
params.uv_scale[1] = 1.0f / (geom.size[1] ? geom.size[1] : 1.0f); material.uv_scale[1] = 1.0f / (geom.size[1] ? geom.size[1] : 1.0f);
params.uv_scale[2] = 1.0f / (geom.size[2] ? geom.size[2] : 1.0f); material.uv_scale[2] = 1.0f / (geom.size[2] ? geom.size[2] : 1.0f);
} }
} }
} }
// Apply material multipliers from the model. // Apply material multipliers from the model.
params.emissive *= model_objs->GetEmissiveMultiplier(); material.emissive *= model_objs->GetEmissiveMultiplier();
params.specular *= model_objs->GetSpecularMultiplier(); material.specular *= model_objs->GetSpecularMultiplier();
params.glossiness *= model_objs->GetShininessMultiplier(); material.glossiness *= model_objs->GetShininessMultiplier();
mjrf_setRenderableMaterial(renderable, &params, &textures); mjrf_setRenderableMaterial(renderable, &material);
} }
UniquePtr<mjrRenderable> CreateGeomRenderable( UniquePtr<mjrRenderable> CreateGeomRenderable(
const mjvGeom& geom, const mjvScene* scene, mjrfContext* ctx, const mjvGeom& geom, const mjvScene* scene, mjrfContext* ctx,
ModelObjects* model_objs, const float headpos[3]) { ModelObjects* model_objs, const float headpos[3]) {
mjrShadingModel shading_model = mjSHADING_MODEL_SCENE_OBJECT;
if (geom.type == mjGEOM_LINE || geom.type == mjGEOM_LINEBOX) {
shading_model = mjSHADING_MODEL_DECOR_LINES;
} else if (geom.category == mjCAT_DECOR) {
shading_model = mjSHADING_MODEL_DECOR;
}
mjrRenderableParams params; mjrRenderableParams params;
mjr_defaultRenderableParams(&params); mjr_defaultRenderableParams(&params);
params.shading_model = shading_model;
auto renderable = CreateRenderable(ctx, params); auto renderable = CreateRenderable(ctx, params);
PrepareGeomMeshes(renderable.get(), geom, scene, model_objs); PrepareGeomMeshes(renderable.get(), geom, scene, model_objs);
UpdateGeomMaterial(renderable.get(), geom, scene, model_objs, headpos); UpdateGeomMaterial(renderable.get(), geom, scene, model_objs, headpos);
+34 -35
View File
@@ -28,48 +28,47 @@
namespace mujoco { namespace mujoco {
void UpdateMaterialInstance(filament::MaterialInstance* instance, void UpdateMaterialInstance(filament::MaterialInstance* instance,
const mjrMaterialParams& params, const mjrMaterial& material,
const mjrMaterialTextures& textures,
ObjectManager* object_mgr) { ObjectManager* object_mgr) {
if (params.scissor[2] != 0 && params.scissor[3] != 0) { if (material.scissor[2] != 0 && material.scissor[3] != 0) {
instance->setScissor(params.scissor[0], params.scissor[1], instance->setScissor(material.scissor[0], material.scissor[1],
params.scissor[2], params.scissor[3]); material.scissor[2], material.scissor[3]);
} }
const filament::Material* material = instance->getMaterial(); const filament::Material* fmaterial = instance->getMaterial();
if (material->hasParameter("BaseColorFactor")) { if (fmaterial->hasParameter("BaseColorFactor")) {
instance->setParameter("BaseColorFactor", filament::RgbaType::sRGB, instance->setParameter("BaseColorFactor", filament::RgbaType::sRGB,
ReadFloat4(params.color)); ReadFloat4(material.color));
} }
if (material->hasParameter("SegmentationColor")) { if (fmaterial->hasParameter("SegmentationColor")) {
instance->setParameter("SegmentationColor", filament::RgbaType::LINEAR, instance->setParameter("SegmentationColor", filament::RgbaType::LINEAR,
ReadFloat4(params.segmentation_color)); ReadFloat4(material.segmentation_color));
} }
if (material->hasParameter("EmissiveFactor")) { if (fmaterial->hasParameter("EmissiveFactor")) {
instance->setParameter("EmissiveFactor", params.emissive); instance->setParameter("EmissiveFactor", material.emissive);
} }
if (material->hasParameter("SpecularFactor")) { if (fmaterial->hasParameter("SpecularFactor")) {
instance->setParameter("SpecularFactor", params.specular); instance->setParameter("SpecularFactor", material.specular);
} }
if (material->hasParameter("GlossinessFactor")) { if (fmaterial->hasParameter("GlossinessFactor")) {
instance->setParameter("GlossinessFactor", params.glossiness); instance->setParameter("GlossinessFactor", material.glossiness);
} }
if (material->hasParameter("MetallicFactor")) { if (fmaterial->hasParameter("MetallicFactor")) {
instance->setParameter("MetallicFactor", instance->setParameter("MetallicFactor",
params.metallic >= 0 ? params.metallic : 1.0f); material.metallic >= 0 ? material.metallic : 1.0f);
} }
if (material->hasParameter("RoughnessFactor")) { if (fmaterial->hasParameter("RoughnessFactor")) {
instance->setParameter("RoughnessFactor", instance->setParameter("RoughnessFactor",
params.roughness >= 0 ? params.roughness : 1.0f); material.roughness >= 0 ? material.roughness : 1.0f);
} }
if (material->hasParameter("UvScale")) { if (fmaterial->hasParameter("UvScale")) {
instance->setParameter("UvScale", ReadFloat3(params.uv_scale)); instance->setParameter("UvScale", ReadFloat3(material.uv_scale));
} }
if (material->hasParameter("UvOffset")) { if (fmaterial->hasParameter("UvOffset")) {
instance->setParameter("UvOffset", ReadFloat3(params.uv_offset)); instance->setParameter("UvOffset", ReadFloat3(material.uv_offset));
} }
if (material->hasParameter("Reflectance")) { if (fmaterial->hasParameter("Reflectance")) {
instance->setParameter("Reflectance", params.reflectance); instance->setParameter("Reflectance", material.reflectance);
} }
// All textures use the same default sampler. // All textures use the same default sampler.
@@ -83,7 +82,7 @@ void UpdateMaterialInstance(filament::MaterialInstance* instance,
auto TrySetTexture = [&](const char* name, const mjrTexture* texture, auto TrySetTexture = [&](const char* name, const mjrTexture* texture,
mjtTextureRole role) { mjtTextureRole role) {
if (material->hasParameter(name)) { if (fmaterial->hasParameter(name)) {
if (texture != nullptr) { if (texture != nullptr) {
instance->setParameter( instance->setParameter(
name, Texture::downcast(texture)->GetFilamentTexture(), sampler); name, Texture::downcast(texture)->GetFilamentTexture(), sampler);
@@ -94,14 +93,14 @@ void UpdateMaterialInstance(filament::MaterialInstance* instance,
} }
}; };
TrySetTexture("BaseColor", textures.color, mjTEXROLE_RGB); TrySetTexture("BaseColor", material.color_texture, mjTEXROLE_RGB);
TrySetTexture("Normal", textures.normal, mjTEXROLE_NORMAL); TrySetTexture("Normal", material.normal_texture, mjTEXROLE_NORMAL);
TrySetTexture("Metallic", textures.metallic, mjTEXROLE_METALLIC); TrySetTexture("Metallic", material.metallic_texture, mjTEXROLE_METALLIC);
TrySetTexture("Roughness", textures.roughness, mjTEXROLE_ROUGHNESS); TrySetTexture("Roughness", material.roughness_texture, mjTEXROLE_ROUGHNESS);
TrySetTexture("Occlusion", textures.occlusion, mjTEXROLE_OCCLUSION); TrySetTexture("Occlusion", material.occlusion_texture, mjTEXROLE_OCCLUSION);
TrySetTexture("ORM", textures.orm, mjTEXROLE_ORM); TrySetTexture("ORM", material.orm_texture, mjTEXROLE_ORM);
TrySetTexture("Emissive", textures.emissive, mjTEXROLE_EMISSIVE); TrySetTexture("Emissive", material.emissive_texture, mjTEXROLE_EMISSIVE);
TrySetTexture("Reflection", textures.reflection, mjTEXROLE_USER); TrySetTexture("Reflection", material.reflection_texture, mjTEXROLE_USER);
} }
} // namespace mujoco } // namespace mujoco
@@ -25,8 +25,7 @@ namespace mujoco {
// 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,
const mjrMaterialParams& params, const mjrMaterial& material,
const mjrMaterialTextures& textures,
ObjectManager* object_mgr); ObjectManager* object_mgr);
} // namespace mujoco } // namespace mujoco
@@ -68,7 +68,6 @@ ObjectManager::ObjectManager(filament::Engine* engine)
materials_[kPhongCubeFade] = LoadMaterial(engine, "phong_cube_fade.filamat"); materials_[kPhongCubeFade] = LoadMaterial(engine, "phong_cube_fade.filamat");
materials_[kPhongCubeReflect] = LoadMaterial(engine, "phong_cube_reflect.filamat"); materials_[kPhongCubeReflect] = LoadMaterial(engine, "phong_cube_reflect.filamat");
materials_[kUnlitSegmentation] = LoadMaterial(engine, "unlit_segmentation.filamat"); materials_[kUnlitSegmentation] = LoadMaterial(engine, "unlit_segmentation.filamat");
materials_[kUnlitLine] = LoadMaterial(engine, "unlit_line.filamat");
materials_[kUnlitDecor] = LoadMaterial(engine, "unlit_decor.filamat"); materials_[kUnlitDecor] = LoadMaterial(engine, "unlit_decor.filamat");
materials_[kUnlitDepth] = LoadMaterial(engine, "unlit_depth.filamat"); materials_[kUnlitDepth] = LoadMaterial(engine, "unlit_depth.filamat");
materials_[kUnlitUi] = LoadMaterial(engine, "unlit_ui.filamat"); materials_[kUnlitUi] = LoadMaterial(engine, "unlit_ui.filamat");
@@ -56,7 +56,6 @@ class ObjectManager {
kUnlitSegmentation, kUnlitSegmentation,
kUnlitDecor, kUnlitDecor,
kUnlitDepth, kUnlitDepth,
kUnlitLine,
kUnlitUi, kUnlitUi,
kNumMaterials, kNumMaterials,
}; };
@@ -51,8 +51,7 @@ static constexpr float kArrowHeadSize = 1.75f;
Renderable::Renderable(FilamentContext* ctx, const mjrRenderableParams& params) Renderable::Renderable(FilamentContext* ctx, const mjrRenderableParams& params)
: object_mgr_(ctx->GetObjectManager()), params_(params) { : object_mgr_(ctx->GetObjectManager()), params_(params) {
mjr_defaultMaterialParams(&material_params_); mjr_defaultMaterial(&material_);
mjr_defaultMaterialTextures(&material_textures_);
} }
Renderable::~Renderable() noexcept { Renderable::~Renderable() noexcept {
@@ -202,21 +201,18 @@ void Renderable::RemoveFromScene(filament::Scene* scene) {
assigned_scene_ = nullptr; assigned_scene_ = nullptr;
} }
void Renderable::UpdateMaterial(const mjrMaterialParams& params, void Renderable::UpdateMaterial(const mjrMaterial& material) {
const mjrMaterialTextures& textures) { material_ = material;
material_params_ = params;
material_textures_ = textures;
AssignMaterial(mjDRAW_MODE_COLOR, GetColorMaterialType()); AssignMaterial(mjDRAW_MODE_COLOR, GetColorMaterialType());
if (params_.shading_model == mjSHADING_MODEL_SCENE_OBJECT) { if (!material_.decor_ux) {
AssignMaterial(mjDRAW_MODE_DEPTH, ObjectManager::kUnlitDepth); AssignMaterial(mjDRAW_MODE_DEPTH, ObjectManager::kUnlitDepth);
AssignMaterial(mjDRAW_MODE_SEGMENTATION, ObjectManager::kUnlitSegmentation); AssignMaterial(mjDRAW_MODE_SEGMENTATION, ObjectManager::kUnlitSegmentation);
} }
for (int i = 0; i < mjNUM_DRAW_MODES; ++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_, object_mgr_);
material_textures_, object_mgr_);
} }
} }
SetDrawMode(draw_mode_); SetDrawMode(draw_mode_);
@@ -241,17 +237,13 @@ void Renderable::AssignMaterial(mjrDrawMode mode,
} }
} }
const mjrMaterialParams& Renderable::GetMaterialParams() const { const mjrMaterial& Renderable::GetMaterial() const {
return material_params_; return material_;
}
const mjrMaterialTextures& Renderable::GetMaterialTextures() const {
return material_textures_;
} }
void Renderable::SetDrawMode(mjrDrawMode 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 (!material_.decor_ux) {
mode = mjDRAW_MODE_COLOR; mode = mjDRAW_MODE_COLOR;
} }
@@ -347,21 +339,21 @@ void Renderable::SetWireframe(bool wireframe) {
} }
ObjectManager::MaterialType Renderable::GetColorMaterialType() const { ObjectManager::MaterialType Renderable::GetColorMaterialType() const {
if (params_.shading_model == mjSHADING_MODEL_DECOR_LINES) { if (material_.decor_ux) {
return ObjectManager::kUnlitLine; if (material_.color_texture) {
} else if (params_.shading_model == mjSHADING_MODEL_DECOR) { return ObjectManager::kUnlitUi;
return ObjectManager::kUnlitDecor; } else {
} else if (params_.shading_model == mjSHADING_MODEL_UX) { return ObjectManager::kUnlitDecor;
return ObjectManager::kUnlitUi; }
} else if (material_textures_.orm) { } else if (material_.orm_texture) {
return ObjectManager::kPbrPacked; return ObjectManager::kPbrPacked;
} else if (material_textures_.metallic) { } else if (material_.metallic_texture) {
return ObjectManager::kPbr; return ObjectManager::kPbr;
} else if (material_textures_.roughness) { } else if (material_.roughness_texture) {
return ObjectManager::kPbr; return ObjectManager::kPbr;
} else if (material_params_.metallic >= 0) { } else if (material_.metallic >= 0) {
return ObjectManager::kPbr; return ObjectManager::kPbr;
} else if (material_params_.roughness >= 0) { } else if (material_.roughness >= 0) {
return ObjectManager::kPbr; return ObjectManager::kPbr;
} }
@@ -370,7 +362,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); const Texture* color_texture = Texture::downcast(material_.color_texture);
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(),
@@ -379,33 +371,33 @@ ObjectManager::MaterialType Renderable::GetColorMaterialType() const {
} }
if (color_texture == nullptr) { if (color_texture == nullptr) {
if (material_params_.color[3] < 1.0f) { if (material_.color[3] < 1.0f) {
return ObjectManager::kPhongColorFade; return ObjectManager::kPhongColorFade;
} else if (material_params_.reflective) { } else if (material_.reflective) {
return ObjectManager::kPhongColorReflect; return ObjectManager::kPhongColorReflect;
} else { } else {
return ObjectManager::kPhongColor; return ObjectManager::kPhongColor;
} }
} else if (color_texture->GetSamplerType() == mjTEXTURE_CUBE) { } else if (color_texture->GetSamplerType() == mjTEXTURE_CUBE) {
if (material_params_.color[3] < 1.0f) { if (material_.color[3] < 1.0f) {
return ObjectManager::kPhongCubeFade; return ObjectManager::kPhongCubeFade;
} else if (material_params_.reflective) { } else if (material_.reflective) {
return ObjectManager::kPhongCubeReflect; return ObjectManager::kPhongCubeReflect;
} else { } else {
return ObjectManager::kPhongCube; return ObjectManager::kPhongCube;
} }
} else if (has_texcoords) { } else if (has_texcoords) {
if (material_params_.color[3] < 1.0f) { if (material_.color[3] < 1.0f) {
return ObjectManager::kPhong2dUvFade; return ObjectManager::kPhong2dUvFade;
} else if (material_params_.reflective) { } else if (material_.reflective) {
return ObjectManager::kPhong2dUvReflect; return ObjectManager::kPhong2dUvReflect;
} else { } else {
return ObjectManager::kPhong2dUv; return ObjectManager::kPhong2dUv;
} }
} else { } else {
if (material_params_.color[3] < 1.0f) { if (material_.color[3] < 1.0f) {
return ObjectManager::kPhong2dFade; return ObjectManager::kPhong2dFade;
} else if (material_params_.reflective) { } else if (material_.reflective) {
return ObjectManager::kPhong2dReflect; return ObjectManager::kPhong2dReflect;
} else { } else {
return ObjectManager::kPhong2d; return ObjectManager::kPhong2d;
@@ -37,15 +37,6 @@ namespace mujoco {
// The mesh describes the surface geometry of the object and the material // The mesh describes the surface geometry of the object and the material
// describes how that surface interacts with light (i.e. the color of each point // describes how that surface interacts with light (i.e. the color of each point
// on the surface). // on the surface).
//
// Defining the mesh is easy; just call SetMesh.
//
// Defining a Material happens in two stages. First, the user specifies the
// ShadingModel to use for Rendering. This describes the overall intent of
// how the Renderable will appear (e.g. lit, unlit, wireframe, etc.). Next,
// the user specifies the MaterialParams and MaterialTextures to use with the
// ShadingModel. Its these properties that ultimately define the actual material
// of the Renderable.
class Renderable : public mjrRenderable { class Renderable : public mjrRenderable {
public: public:
Renderable(FilamentContext* ctx, const mjrRenderableParams& params); Renderable(FilamentContext* ctx, const mjrRenderableParams& params);
@@ -98,19 +89,14 @@ class Renderable : public mjrRenderable {
// Removes the renderable from the given filament Scene. // Removes the renderable from the given filament Scene.
void RemoveFromScene(filament::Scene* scene); void RemoveFromScene(filament::Scene* scene);
// Further defines the material of the renderable. Only applies to renderables // Further defines the material of the renderable.
// with a SceneObject shading model.
void SetDrawMode(mjrDrawMode 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 mjrMaterial& material);
const mjrMaterialTextures& textures);
// Returns the current material parameters. // Returns the current material parameters.
const mjrMaterialParams& GetMaterialParams() const; const mjrMaterial& GetMaterial() const;
// Returns the current material textures.
const mjrMaterialTextures& GetMaterialTextures() const;
// Returns the filament Engine managing the renderables. // Returns the filament Engine managing the renderables.
filament::Engine* GetEngine(); filament::Engine* GetEngine();
@@ -143,8 +129,7 @@ class Renderable : public mjrRenderable {
ObjectManager* object_mgr_; ObjectManager* object_mgr_;
mjrRenderableParams params_; mjrRenderableParams params_;
filament::MaterialInstance* instances_[mjNUM_DRAW_MODES] = {nullptr}; filament::MaterialInstance* instances_[mjNUM_DRAW_MODES] = {nullptr};
mjrMaterialParams material_params_; mjrMaterial material_;
mjrMaterialTextures material_textures_;
mjrDrawMode draw_mode_ = mjDRAW_MODE_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_;
@@ -208,7 +208,7 @@ void SceneView::RemoveFromScene(Light* light) {
void SceneView::AddToScene(Renderable* renderable) { void SceneView::AddToScene(Renderable* renderable) {
if (renderables_.insert(renderable).second) { if (renderables_.insert(renderable).second) {
renderable->AddToScene(scene_); renderable->AddToScene(scene_);
if (renderable->GetMaterialParams().reflective) { if (renderable->GetMaterial().reflective) {
AddReflectiveRenderable(renderable); AddReflectiveRenderable(renderable);
} }
} }
@@ -317,9 +317,9 @@ void SceneView::AddReflectiveRenderable(Renderable* renderable) {
target->Prepare(viewport.width, viewport.height); target->Prepare(viewport.width, viewport.height);
if (reflections_enabled_) { if (reflections_enabled_) {
mjrMaterialTextures textures = renderable->GetMaterialTextures(); mjrMaterial material = renderable->GetMaterial();
textures.reflection = target->GetColorTexture(); material.reflection_texture = target->GetColorTexture();
renderable->UpdateMaterial(renderable->GetMaterialParams(), textures); renderable->UpdateMaterial(material);
} }
} }
@@ -349,18 +349,18 @@ void SceneView::EnableReflections() {
for (int i = 0; i < reflectives_.size(); ++i) { for (int i = 0; i < reflectives_.size(); ++i) {
Renderable* renderable = reflectives_[i]; Renderable* renderable = reflectives_[i];
mjrMaterialTextures textures = renderable->GetMaterialTextures(); mjrMaterial material = renderable->GetMaterial();
textures.reflection = reflect_targets_[i]->GetColorTexture(); material.reflection_texture = reflect_targets_[i]->GetColorTexture();
renderable->UpdateMaterial(renderable->GetMaterialParams(), textures); renderable->UpdateMaterial(material);
} }
} }
void SceneView::DisableReflections() { void SceneView::DisableReflections() {
reflections_enabled_ = false; reflections_enabled_ = false;
for (Renderable* renderable : reflectives_) { for (Renderable* renderable : reflectives_) {
mjrMaterialTextures textures = renderable->GetMaterialTextures(); mjrMaterial material = renderable->GetMaterial();
textures.reflection = nullptr; material.reflection_texture = nullptr;
renderable->UpdateMaterial(renderable->GetMaterialParams(), textures); renderable->UpdateMaterial(material);
} }
} }
@@ -69,10 +69,11 @@ void mjr_defaultTextureConfig(mjrTextureConfig* config) {
} }
void mjr_defaultMeshData(mjrMeshData* data) { void mjr_defaultMeshData(mjrMeshData* data) {
std::memset(data, 0, sizeof(mjrMeshData)); memset(data, 0, sizeof(mjrMeshData));
} }
void mjr_defaultSceneParams(mjrSceneParams* params) { void mjr_defaultSceneParams(mjrSceneParams* params) {
memset(params, 0, sizeof(mjrSceneParams));
params->enable_post_processing = true; params->enable_post_processing = true;
params->enable_reflections = true; params->enable_reflections = true;
params->enable_shadows = true; params->enable_shadows = true;
@@ -81,6 +82,7 @@ void mjr_defaultSceneParams(mjrSceneParams* params) {
} }
void mjr_defaultLightParams(mjrLightParams* params) { void mjr_defaultLightParams(mjrLightParams* params) {
memset(params, 0, sizeof(mjrLightParams));
params->type = mjLIGHT_POINT; params->type = mjLIGHT_POINT;
params->texture = nullptr; params->texture = nullptr;
params->color[0] = 0; params->color[0] = 0;
@@ -95,35 +97,20 @@ void mjr_defaultLightParams(mjrLightParams* params) {
params->vsm_blur_width = 0.0f; params->vsm_blur_width = 0.0f;
} }
void mjr_defaultMaterialTextures(mjrMaterialTextures* textures) { void mjr_defaultMaterial(mjrMaterial* material) {
textures->color = nullptr; memset(material, 0, sizeof(mjrMaterial));
textures->normal = nullptr; setf(material->color, {1.f, 1.f, 1.f, 1.f});
textures->metallic = nullptr; setf(material->segmentation_color, {1, 1, 1, 1});
textures->roughness = nullptr; setf(material->uv_scale, {1, 1, 1});
textures->occlusion = nullptr; material->emissive = -1.0f;
textures->orm = nullptr; material->specular = -1.0f;
textures->emissive = nullptr; material->glossiness = -1.0f;
textures->reflection = nullptr; material->metallic = -1.0f;
} material->roughness = -1.0f;
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) { void mjr_defaultRenderableParams(mjrRenderableParams* params) {
params->shading_model = mjSHADING_MODEL_SCENE_OBJECT; memset(params, 0, sizeof(mjrRenderableParams));
params->cast_shadows = true; params->cast_shadows = true;
params->receive_shadows = true; params->receive_shadows = true;
params->layer_mask = 0x01; params->layer_mask = 0x01;
@@ -265,9 +252,8 @@ void mjrf_setRenderableGeomMesh(mjrRenderable* renderable, mjtGeom type,
} }
void mjrf_setRenderableMaterial(mjrRenderable* renderable, void mjrf_setRenderableMaterial(mjrRenderable* renderable,
const mjrMaterialParams* params, const mjrMaterial* material) {
const mjrMaterialTextures* textures) { mujoco::Renderable::downcast(renderable)->UpdateMaterial(*material);
mujoco::Renderable::downcast(renderable)->UpdateMaterial(*params, *textures);
} }
void mjrf_setRenderableTransform(mjrRenderable* renderable, void mjrf_setRenderableTransform(mjrRenderable* renderable,
@@ -53,19 +53,6 @@ typedef enum mjrDrawMode_ {
enum { mjNUM_DRAW_MODES = 3 }; 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. // The type of data stored in an index buffer.
typedef enum mjrIndexType_ { typedef enum mjrIndexType_ {
mjINDEX_TYPE_U16 = 0, mjINDEX_TYPE_U16 = 0,
@@ -124,41 +111,74 @@ typedef mjtColorSpace mjrColorSpace;
typedef mjtLightType mjrLightType; typedef mjtLightType mjrLightType;
typedef mjvGLCamera mjrCamera; typedef mjvGLCamera mjrCamera;
// The textures that can be assigned to the drawable's material. // The material to be applied to a renderable.
struct mjrMaterialTextures { struct mjrMaterial {
const mjrTexture* color; // The color of the object. Defaults to white.
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 color[4];
// The color to use for segmentation rendering. Defaults to white.
float segmentation_color[4]; float segmentation_color[4];
float tex_repeat[2];
// Applies an addition scale to the UV coordinates of the object. Defaults to
// (1, 1, 1).
float uv_scale[3]; float uv_scale[3];
// Applies an offset to the UV coordinates of the object. Defaults to (0, 0,
// 0).
float uv_offset[3]; float uv_offset[3];
// Applies a scissor test to the object.
float scissor[4]; float scissor[4];
float specular;
float glossiness; // Factors for PBR metallic-roughness materials.
float metallic; float metallic;
float roughness; float roughness;
// Factors for (non-PBR) specular-glossiness materials.
float specular;
float glossiness;
// The emissive (glow) factor of the object.
float emissive; float emissive;
float reflectance;
mjtByte tex_uniform; // Whether or not the object is a reflective surface. Only applies to planes.
mjtByte reflective; mjtByte reflective;
// The blend factor to use for reflective surfaces. A value of 1.0 means that
// the surface is fully reflective (i.e. a mirror).
float reflectance;
// If true, does not apply any lighting to the object. (Assumes the object is
// used for UX or decorative elements like contact forces and labels.)
mjtByte decor_ux;
// The texture containing the base color of the object.
const mjrTexture* color_texture;
// The normal map of the object.
const mjrTexture* normal_texture;
// The metallic map of the object.
const mjrTexture* metallic_texture;
// The roughness map of the object.
const mjrTexture* roughness_texture;
// The occlusion map of the object.
const mjrTexture* occlusion_texture;
// A texture containing the occlusion, roughness, and metallic maps packed
// into the R, G, B channels, respectively.
const mjrTexture* orm_texture;
// An emissive texture for the object.
const mjrTexture* emissive_texture;
// The reflection texture to use for the object. For internal use only.
const mjrTexture* reflection_texture;
}; };
// Initializes the mjrMaterialParams to default values. // Initializes the mjrMaterial to default values.
void mjr_defaultMaterialParams(mjrMaterialParams* params); void mjr_defaultMaterial(mjrMaterial* material);
// The binary contents of a texture. // The binary contents of a texture.
struct mjrTextureData { struct mjrTextureData {
@@ -205,8 +225,6 @@ void mjr_defaultTextureConfig(mjrTextureConfig* config);
// Configuration parameters for a Renderable. // Configuration parameters for a Renderable.
struct mjrRenderableParams { struct mjrRenderableParams {
// The shading model to use for the Renderable.
mjrShadingModel shading_model;
// Whether or not the Renderable casts shadows. // Whether or not the Renderable casts shadows.
mjtByte cast_shadows; mjtByte cast_shadows;
// Whether or not the Renderable receives shadows. // Whether or not the Renderable receives shadows.
@@ -516,8 +534,7 @@ void mjrf_setRenderableGeomMesh(mjrRenderable* renderable, mjtGeom type,
// Sets the material properties and textures of the renderable. // Sets the material properties and textures of the renderable.
void mjrf_setRenderableMaterial(mjrRenderable* renderable, void mjrf_setRenderableMaterial(mjrRenderable* renderable,
const mjrMaterialParams* params, const mjrMaterial* material);
const mjrMaterialTextures* textures);
// Sets the transform (position, rotation, and size) of the renderable. // Sets the transform (position, rotation, and size) of the renderable.
void mjrf_setRenderableTransform(mjrRenderable* renderable, void mjrf_setRenderableTransform(mjrRenderable* renderable,
-1
View File
@@ -89,7 +89,6 @@
"assets/phong_cube_reflect.filamat", "assets/phong_cube_reflect.filamat",
"assets/unlit_decor.filamat", "assets/unlit_decor.filamat",
"assets/unlit_depth.filamat", "assets/unlit_depth.filamat",
"assets/unlit_line.filamat",
"assets/unlit_segmentation.filamat", "assets/unlit_segmentation.filamat",
"assets/unlit_ui.filamat" "assets/unlit_ui.filamat"
]; ];