diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index efbecc2f..ef01da9d 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -2866,11 +2866,15 @@ and the +Y axis points up. Thus the frame position and orientation are the key a ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This element creates a light, which moves with the body where it is defined. To create a fixed light, define it in the -world body. The lights created here are in addition to the default headlight which is always defined and is adjusted via -the :ref:`visual ` element. MuJoCo relies on the standard lighting model in OpenGL (fixed functionality) -augmented with shadow mapping. The effects of lights are additive, thus adding a light always makes the scene brighter. -The maximum number of lights that can be active simultaneously is 8, counting the headlight. The light is shining along -the direction specified by the dir attribute. It does not have a full spatial frame with three orthogonal axes. +world body. The lights created here are in addition to the headlight which is always defined and is configured via the +:ref:`visual ` element. Lights shine along the direction specified by the dir attribute. They do not have +a full spatial frame with three orthogonal axes. + +By default, MuJoCo uses the standard OpenGL (fixed functional) Phong lighting model for its rendering, with augmented +with shadow mapping. (See the OpenGL documentation for more information, including details about various attributes.) + +MJCF also supports alternative lighting models (e.g. physically-based rendering) by providing additional attributes. +Attributes may be applied or ignored depending on the lighting model being used. .. _body-light-name: @@ -2919,12 +2923,6 @@ the direction specified by the dir attribute. It does not have a full spatial fr these clipping planes bound the cone or box shadow volume in the light direction. As a result, some shadows (especially those very close to the light) may be clipped. -.. _body-light-bulbradius: - -:at:`radius`: :at-val:`real, "0.02"` - Radius of the light, affects shadow softness. This attribute has no effect in MuJoCo's native renderer, but it can be - useful when rendering scenes with an external renderer. - .. _body-light-active: :at:`active`: :at-val:`[false, true], "true"` @@ -2941,11 +2939,45 @@ the direction specified by the dir attribute. It does not have a full spatial fr :at:`dir`: :at-val:`real(3), "0 0 -1"` Direction of the light. +.. _body-light-diffuse: + +:at:`diffuse`: :at-val:`real(3), "0.7 0.7 0.7"` + The color of the light. For the Phong (default) lighting model, this defines the diffuse color of + the light. + +.. _body-light-intensity: + +:at:`intensity`: :at-val:`real, "1000.0"` + The intensity of the light source, measured in candela, used for physically-based lighting models. + This is unused by the default Phong lighting model. + +.. _body-light-ambient: + +:at:`ambient`: :at-val:`real(3), "0 0 0"` + The ambient color of the light, used by the default Phong lighting model. + +.. _body-light-specular: + +:at:`specular`: :at-val:`real(3), "0.3 0.3 0.3"` + The specular color of the light, used by the default Phong lighting model. + +.. _body-light-range: + +:at:`range`: :at-val:`real, "10.0"` + The effective range of the light. Objects further than this distance from the light position + will not be illuminated by this light. This only applies to spotlights. + +.. _body-light-bulbradius: + +:at:`bulbradius`: :at-val:`real, "0.02"` + The radius of the light source which can affect shadow softness depending on the + renderer. This only applies to spotlights. + .. _body-light-attenuation: :at:`attenuation`: :at-val:`real(3), "1 0 0"` - These are the constant, linear and quadratic attenuation coefficients in OpenGL. The default corresponds to no - attenuation. See the OpenGL documentation for more information on this and all other OpenGL-related properties. + These are the constant, linear and quadratic attenuation coefficients for Phong lighting. + The default corresponds to no attenuation. .. _body-light-cutoff: @@ -2957,22 +2989,6 @@ the direction specified by the dir attribute. It does not have a full spatial fr :at:`exponent`: :at-val:`real, "10"` Exponent for spotlights. This setting controls the softness of the spotlight cutoff. -.. _body-light-ambient: - -:at:`ambient`: :at-val:`real(3), "0 0 0"` - The ambient color of the light. - -.. _body-light-diffuse: - -:at:`diffuse`: :at-val:`real(3), "0.7 0.7 0.7"` - The diffuse color of the light. - -.. _body-light-specular: - -:at:`specular`: :at-val:`real(3), "0.3 0.3 0.3"` - The specular color of the light. - - .. _body-composite: :el-prefix:`body/` |-| **composite** (*) @@ -8257,26 +8273,30 @@ if omitted. .. _default-light-dir: -.. _default-light-bulbradius: - .. _default-light-directional: .. _default-light-castshadow: .. _default-light-active: +.. _default-light-diffuse: + +.. _default-light-intensity: + +.. _default-light-ambient: + +.. _default-light-specular: + +.. _default-light-bulbradius: + +.. _default-light-range: + .. _default-light-attenuation: .. _default-light-cutoff: .. _default-light-exponent: -.. _default-light-ambient: - -.. _default-light-diffuse: - -.. _default-light-specular: - .. _default-light-mode: :el-prefix:`default/` |-| **light** (?) diff --git a/doc/XMLschema.rst b/doc/XMLschema.rst index 5b32d4bb..4935a883 100644 --- a/doc/XMLschema.rst +++ b/doc/XMLschema.rst @@ -317,9 +317,11 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`active` | :ref:`pos` | :ref:`dir` | :ref:`bulbradius` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`attenuation` | :ref:`cutoff` | :ref:`exponent` | :ref:`ambient` | | +| | | | :ref:`intensity` | :ref:`range` | :ref:`attenuation` | :ref:`cutoff` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`diffuse` | :ref:`specular` | :ref:`mode` | :ref:`target` | | +| | | | :ref:`exponent` | :ref:`ambient` | :ref:`diffuse` | :ref:`specular` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`mode` | :ref:`target` | | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| body |br| |_| |L| | | .. table:: | @@ -1457,13 +1459,13 @@ | :ref:`light | ? | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`pos` | :ref:`dir` | :ref:`bulbradius` | :ref:`directional` | | +| | | | :ref:`pos` | :ref:`dir` | :ref:`bulbradius` | :ref:`intensity` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`castshadow` | :ref:`active` | :ref:`attenuation` | :ref:`cutoff` | | +| | | | :ref:`range` | :ref:`directional` | :ref:`castshadow` | :ref:`active` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`exponent` | :ref:`ambient` | :ref:`diffuse` | :ref:`specular` | | +| | | | :ref:`attenuation` | :ref:`cutoff` | :ref:`exponent` | :ref:`ambient` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`mode` | | | | | +| | | | :ref:`diffuse` | :ref:`specular` | :ref:`mode` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| default |br| |_| |L| | | .. table:: | diff --git a/doc/includes/references.h b/doc/includes/references.h index ffada3b8..c8349418 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -1178,6 +1178,8 @@ struct mjModel_ { mjtByte* light_directional; // directional light (nlight x 1) mjtByte* light_castshadow; // does light cast shadows (nlight x 1) float* light_bulbradius; // light radius for soft shadows (nlight x 1) + float* light_intensity; // intensity, in candela (nlight x 1) + float* light_range; // range of effectiveness (nlight x 1) mjtByte* light_active; // is light on (nlight x 1) mjtNum* light_pos; // position rel. to body frame (nlight x 3) mjtNum* light_dir; // direction rel. to body frame (nlight x 3) @@ -2030,7 +2032,9 @@ typedef struct mjsLight_ { // light specification mjtByte active; // is light active mjtByte directional; // is light directional or spot mjtByte castshadow; // does light cast shadows - double bulbradius; // bulb radius, for soft shadows + float bulbradius; // bulb radius, for soft shadows + float intensity; // intensity, in candelas + float range; // range of effectiveness float attenuation[3]; // OpenGL attenuation (quadratic model) float cutoff; // OpenGL cutoff float exponent; // OpenGL exponent @@ -2838,6 +2842,8 @@ struct mjvLight_ { // OpenGL light mjtByte directional; // directional light mjtByte castshadow; // does light cast shadows float bulbradius; // bulb radius for soft shadows + float intensity; // intensity, in candelas + float range; // range of effectiveness }; typedef struct mjvLight_ mjvLight; struct mjvOption_ { // abstract visualization options @@ -3055,6 +3061,8 @@ struct mjvSceneState_ { mjtByte* light_directional; mjtByte* light_castshadow; float* light_bulbradius; + float* light_intensity; + float* light_range; mjtByte* light_active; float* light_attenuation; float* light_cutoff; diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index fd63b272..8c00e062 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -845,6 +845,8 @@ struct mjModel_ { mjtByte* light_directional; // directional light (nlight x 1) mjtByte* light_castshadow; // does light cast shadows (nlight x 1) float* light_bulbradius; // light radius for soft shadows (nlight x 1) + float* light_intensity; // intensity, in candela (nlight x 1) + float* light_range; // range of effectiveness (nlight x 1) mjtByte* light_active; // is light on (nlight x 1) mjtNum* light_pos; // position rel. to body frame (nlight x 3) mjtNum* light_dir; // direction rel. to body frame (nlight x 3) diff --git a/include/mujoco/mjspec.h b/include/mujoco/mjspec.h index fb95afad..512e7c29 100644 --- a/include/mujoco/mjspec.h +++ b/include/mujoco/mjspec.h @@ -396,7 +396,9 @@ typedef struct mjsLight_ { // light specification mjtByte active; // is light active mjtByte directional; // is light directional or spot mjtByte castshadow; // does light cast shadows - double bulbradius; // bulb radius, for soft shadows + float bulbradius; // bulb radius, for soft shadows + float intensity; // intensity, in candelas + float range; // range of effectiveness float attenuation[3]; // OpenGL attenuation (quadratic model) float cutoff; // OpenGL cutoff float exponent; // OpenGL exponent diff --git a/include/mujoco/mjvisualize.h b/include/mujoco/mjvisualize.h index fa0aec4f..0093216b 100644 --- a/include/mujoco/mjvisualize.h +++ b/include/mujoco/mjvisualize.h @@ -271,6 +271,8 @@ struct mjvLight_ { // OpenGL light mjtByte directional; // directional light mjtByte castshadow; // does light cast shadows float bulbradius; // bulb radius for soft shadows + float intensity; // intensity, in candelas + float range; // range of effectiveness }; typedef struct mjvLight_ mjvLight; @@ -504,6 +506,8 @@ struct mjvSceneState_ { mjtByte* light_directional; mjtByte* light_castshadow; float* light_bulbradius; + float* light_intensity; + float* light_range; mjtByte* light_active; float* light_attenuation; float* light_cutoff; diff --git a/include/mujoco/mjxmacro.h b/include/mujoco/mjxmacro.h index f46b4ff5..bbd79ad1 100644 --- a/include/mujoco/mjxmacro.h +++ b/include/mujoco/mjxmacro.h @@ -302,6 +302,8 @@ XMJV( mjtByte, light_directional, nlight, 1 ) \ XMJV( mjtByte, light_castshadow, nlight, 1 ) \ XMJV( float, light_bulbradius, nlight, 1 ) \ + XMJV( float, light_intensity, nlight, 1 ) \ + XMJV( float, light_range, nlight, 1 ) \ XMJV( mjtByte, light_active, nlight, 1 ) \ X ( mjtNum, light_pos, nlight, 3 ) \ X ( mjtNum, light_dir, nlight, 3 ) \ diff --git a/python/mujoco/introspect/structs.py b/python/mujoco/introspect/structs.py index 4efca1ee..e8044c71 100644 --- a/python/mujoco/introspect/structs.py +++ b/python/mujoco/introspect/structs.py @@ -2243,6 +2243,22 @@ STRUCTS: Mapping[str, StructDecl] = dict([ doc='light radius for soft shadows', array_extent=('nlight',), ), + StructFieldDecl( + name='light_intensity', + type=PointerType( + inner_type=ValueType(name='float'), + ), + doc='intensity, in candela', + array_extent=('nlight',), + ), + StructFieldDecl( + name='light_range', + type=PointerType( + inner_type=ValueType(name='float'), + ), + doc='range of effectiveness', + array_extent=('nlight',), + ), StructFieldDecl( name='light_active', type=PointerType( @@ -6735,6 +6751,16 @@ STRUCTS: Mapping[str, StructDecl] = dict([ type=ValueType(name='float'), doc='bulb radius for soft shadows', ), + StructFieldDecl( + name='intensity', + type=ValueType(name='float'), + doc='intensity, in candelas', + ), + StructFieldDecl( + name='range', + type=ValueType(name='float'), + doc='range of effectiveness', + ), ), )), ('mjvOption', @@ -7851,6 +7877,20 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), doc='', ), + StructFieldDecl( + name='light_intensity', + type=PointerType( + inner_type=ValueType(name='float'), + ), + doc='', + ), + StructFieldDecl( + name='light_range', + type=PointerType( + inner_type=ValueType(name='float'), + ), + doc='', + ), StructFieldDecl( name='light_active', type=PointerType( @@ -10600,9 +10640,19 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), StructFieldDecl( name='bulbradius', - type=ValueType(name='double'), + type=ValueType(name='float'), doc='bulb radius, for soft shadows', ), + StructFieldDecl( + name='intensity', + type=ValueType(name='float'), + doc='intensity, in candelas', + ), + StructFieldDecl( + name='range', + type=ValueType(name='float'), + doc='range of effectiveness', + ), StructFieldDecl( name='attenuation', type=ArrayType( diff --git a/python/mujoco/structs.cc b/python/mujoco/structs.cc index 3cf6eb82..735e0a0b 100644 --- a/python/mujoco/structs.cc +++ b/python/mujoco/structs.cc @@ -1076,6 +1076,8 @@ This is useful for example when the MJB is not available as a file on disk.)")); X(directional); X(castshadow); X(bulbradius); + X(intensity); + X(range); #undef X #define X(var) DefinePyArray(mjvLight, #var, &MjvLightWrapper::var) diff --git a/src/engine/engine_vis_visualize.c b/src/engine/engine_vis_visualize.c index 012cb966..0425b85c 100644 --- a/src/engine/engine_vis_visualize.c +++ b/src/engine/engine_vis_visualize.c @@ -2172,6 +2172,8 @@ void mjv_makeLights(const mjModel* m, const mjData* d, mjvScene* scn) { thislight->directional = m->light_directional[i]; thislight->castshadow = m->light_castshadow[i]; thislight->bulbradius = m->light_bulbradius[i]; + thislight->intensity = m->light_intensity[i]; + thislight->range = m->light_range[i]; if (!thislight->directional) { f2f(thislight->attenuation, m->light_attenuation+3*i, 3); thislight->exponent = m->light_exponent[i]; diff --git a/src/user/user_init.c b/src/user/user_init.c index 183034ce..01f4a8b9 100644 --- a/src/user/user_init.c +++ b/src/user/user_init.c @@ -203,6 +203,8 @@ void mjs_defaultLight(mjsLight* light) { // intrinsics light->castshadow = 1; light->bulbradius = 0.02; + light->intensity = 1000.0; + light->range = 10.0; light->active = 1; light->attenuation[0] = 1; light->cutoff = 45; @@ -404,4 +406,3 @@ void mjs_defaultKey(mjsKey* key) { void mjs_defaultPlugin(mjsPlugin* plugin) { memset(plugin, 0, sizeof(mjsPlugin)); } - diff --git a/src/user/user_model.cc b/src/user/user_model.cc index 93449339..f705551c 100644 --- a/src/user/user_model.cc +++ b/src/user/user_model.cc @@ -2675,6 +2675,8 @@ void mjCModel::CopyTree(mjModel* m) { mjuu_copyvec(m->light_pos+3*lid, pl->pos, 3); mjuu_copyvec(m->light_dir+3*lid, pl->dir, 3); m->light_bulbradius[lid] = pl->bulbradius; + m->light_intensity[lid] = pl->intensity; + m->light_range[lid] = pl->range; mjuu_copyvec(m->light_attenuation+3*lid, pl->attenuation, 3); m->light_cutoff[lid] = pl->cutoff; m->light_exponent[lid] = pl->exponent; diff --git a/src/xml/xml_native_reader.cc b/src/xml/xml_native_reader.cc index 8404364a..85723a6e 100644 --- a/src/xml/xml_native_reader.cc +++ b/src/xml/xml_native_reader.cc @@ -167,8 +167,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = { {"camera", "?", "17", "orthographic", "fovy", "ipd", "resolution", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"}, - {"light", "?", "13", "pos", "dir", "bulbradius", "directional", "castshadow", "active", - "attenuation", "cutoff", "exponent", "ambient", "diffuse", "specular", "mode"}, + {"light", "?", "15", "pos", "dir", "bulbradius", "intensity", "range", + "directional", "castshadow", "active", "attenuation", "cutoff", "exponent", + "ambient", "diffuse", "specular", "mode"}, {"pair", "?", "7", "condim", "friction", "solref", "solreffriction", "solimp", "gap", "margin"}, {"equality", "?", "3", "active", "solref", "solimp"}, @@ -280,9 +281,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = { {"camera", "*", "20", "name", "class", "orthographic", "fovy", "ipd", "resolution", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target", "focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"}, - {"light", "*", "16", "name", "class", "directional", "castshadow", "active", - "pos", "dir", "bulbradius", "attenuation", "cutoff", "exponent", "ambient", "diffuse", - "specular", "mode", "target"}, + {"light", "*", "18", "name", "class", "directional", "castshadow", "active", + "pos", "dir", "bulbradius", "intensity", "range", "attenuation", "cutoff", + "exponent", "ambient", "diffuse", "specular", "mode", "target"}, {"plugin", "*", "2", "plugin", "instance"}, {"<"}, {"config", "*", "2", "key", "value"}, @@ -1856,6 +1857,8 @@ void mjXReader::OneLight(XMLElement* elem, mjsLight* light) { ReadAttr(elem, "pos", 3, light->pos, text); ReadAttr(elem, "dir", 3, light->dir, text); ReadAttr(elem, "bulbradius", 1, &light->bulbradius, text); + ReadAttr(elem, "intensity", 1, &light->intensity, text); + ReadAttr(elem, "range", 1, &light->range, text); ReadAttr(elem, "attenuation", 3, light->attenuation, text); ReadAttr(elem, "cutoff", 1, &light->cutoff, text); ReadAttr(elem, "exponent", 1, &light->exponent, text); diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index bf5093c5..a7f27871 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -604,6 +604,8 @@ void mjXWriter::OneLight(XMLElement* elem, const mjCLight* light, mjCDef* def, // defaults and regular WriteAttr(elem, "bulbradius", 1, &light->bulbradius, &def->Light().bulbradius); + WriteAttr(elem, "intensity", 1, &light->intensity, &def->Light().intensity); + WriteAttr(elem, "range", 1, &light->range, &def->Light().range); WriteAttrKey(elem, "directional", bool_map, 2, light->directional, def->Light().directional); WriteAttrKey(elem, "castshadow", bool_map, 2, light->castshadow, def->Light().castshadow); WriteAttrKey(elem, "active", bool_map, 2, light->active, def->Light().active); diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index d743436c..a77daf2e 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -5433,6 +5433,8 @@ public unsafe struct mjModel_ { public byte* light_directional; public byte* light_castshadow; public float* light_bulbradius; + public float* light_intensity; + public float* light_range; public byte* light_active; public double* light_pos; public double* light_dir; @@ -6077,6 +6079,8 @@ public unsafe struct mjvLight_ { public byte directional; public byte castshadow; public float bulbradius; + public float intensity; + public float range; } [StructLayout(LayoutKind.Sequential)] @@ -6357,6 +6361,8 @@ public unsafe struct model { public byte* light_directional; public byte* light_castshadow; public float* light_bulbradius; + public float* light_intensity; + public float* light_range; public byte* light_active; public float* light_attenuation; public float* light_cutoff;