Merge pull request #978 from aftersomemath:depth-precision-in-place

PiperOrigin-RevId: 572961667
Change-Id: I69011ddf835ae286e30e7f84cca67867cfe94fa4
This commit is contained in:
Copybara-Service
2023-10-12 11:18:36 -07:00
14 changed files with 194 additions and 34 deletions
+10
View File
@@ -502,6 +502,16 @@ These are the possible framebuffers. They are used as an argument to the functio
.. mujoco-include:: mjtFramebuffer .. mujoco-include:: mjtFramebuffer
mjtDepthMap
~~~~~~~~~~~
These are the depth mapping options. They are used as a value for the ``readPixelDepth`` attribute of the
:ref:`mjrContext` struct, to control how the depth returned by :ref:`mjr_readPixels` is mapped from
``znear`` to ``zfar``.
.. mujoco-include:: mjtDepthMap
.. _mjtFontScale: .. _mjtFontScale:
mjtFontScale mjtFontScale
+12 -8
View File
@@ -131,15 +131,19 @@ General
22. Added multi-threaded constraint solving via :ref:`mj_island` and :ref:`mjThreadPool` to :ref:`testspeed<saTestspeed>` 22. Added multi-threaded constraint solving via :ref:`mj_island` and :ref:`mjThreadPool` to :ref:`testspeed<saTestspeed>`
exposed via npoolthread flag. The `22 humanoids <https://github.com/deepmind/mujoco/blob/main/model/humanoid/22_humanoids.xml>`__ exposed via npoolthread flag. The `22 humanoids <https://github.com/deepmind/mujoco/blob/main/model/humanoid/22_humanoids.xml>`__
model shows a 3x speedup compared to the single threaded simulation. model shows a 3x speedup compared to the single threaded simulation.
23. Implemented reversed Z rendering for better depth precision. An enum :ref:`mjtDepthMap` was added with values
:ref:`mjDEPTH_ZERONEAR` and :ref:`mjDEPTH_ZEROFAR`, which can be used to set the new ``readDepthMap`` attribute in
:ref:`mjrContext`` to control how the depth returned by :ref:`mjr_readPixels` is mapped from ``znear`` to ``zfar``.
`Contribution <https://github.com/google-deepmind/mujoco/pull/978>`__ by `Levi Burner <https://github.com/aftersomemath>`__.
Python bindings Python bindings
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
23. Fixed `#870 <https://github.com/google-deepmind/mujoco/issues/870>`__ where calling ``update_scene`` with an invalid 24. Fixed `#870 <https://github.com/google-deepmind/mujoco/issues/870>`__ where calling ``update_scene`` with an invalid
camera name used the default camera. camera name used the default camera.
24. Added ``user_scn`` to the :ref:`passive viewer<PyViewerPassive>` handle, which allows users to add custom 25. Added ``user_scn`` to the :ref:`passive viewer<PyViewerPassive>` handle, which allows users to add custom
visualization geoms (`#1023 <https://github.com/google-deepmind/mujoco/issues/870>`__). visualization geoms (`#1023 <https://github.com/google-deepmind/mujoco/issues/870>`__).
25. Added optional boolean keyword arguments ``show_left_ui`` and ``show_right_ui`` to the functions ``viewer.launch`` 26. Added optional boolean keyword arguments ``show_left_ui`` and ``show_right_ui`` to the functions ``viewer.launch``
and ``viewer.launch_passive``, which allow users to launch a viewer with UI panels hidden. and ``viewer.launch_passive``, which allow users to launch a viewer with UI panels hidden.
Simulate Simulate
@@ -149,21 +153,21 @@ Simulate
:align: right :align: right
:width: 240px :width: 240px
26. Added **state history** mechanism to :ref:`simulate<saSimulate>` and the managed 27. Added **state history** mechanism to :ref:`simulate<saSimulate>` and the managed
:ref:`Python viewer<PyViewerManaged>`. State history can be viewed by scrubbing the History slider and (more :ref:`Python viewer<PyViewerManaged>`. State history can be viewed by scrubbing the History slider and (more
precisely) with the left and right arrow keys. See screen capture: precisely) with the left and right arrow keys. See screen capture:
27. The ``LOADING...`` label is now shown correctly. 28. The ``LOADING...`` label is now shown correctly.
`Contribution <https://github.com/google-deepmind/mujoco/pull/1070>`__ by `Contribution <https://github.com/google-deepmind/mujoco/pull/1070>`__ by
`Levi Burner <https://github.com/aftersomemath>`__. `Levi Burner <https://github.com/aftersomemath>`__.
Bug fixes Bug fixes
^^^^^^^^^ ^^^^^^^^^
28. Fixed a bug that was causing :ref:`geom margin<body-geom-margin>` to be ignored during the construction of 29. Fixed a bug that was causing :ref:`geom margin<body-geom-margin>` to be ignored during the construction of
midphase collision trees. midphase collision trees.
29. Fixed a bug that was generating incorrect values in ``efc_diagApprox`` for weld equality constraints. 30. Fixed a bug that was generating incorrect values in ``efc_diagApprox`` for weld equality constraints.
Version 2.3.7 (July 20, 2023) Version 2.3.7 (July 20, 2023)
+7
View File
@@ -1443,6 +1443,10 @@ typedef enum mjtFramebuffer_ { // OpenGL framebuffer option
mjFB_WINDOW = 0, // default/window buffer mjFB_WINDOW = 0, // default/window buffer
mjFB_OFFSCREEN // offscreen buffer mjFB_OFFSCREEN // offscreen buffer
} mjtFramebuffer; } mjtFramebuffer;
typedef enum mjtDepthMap_ { // depth mapping for `mjr_readPixels`
mjDEPTH_ZERONEAR = 0, // standard depth map; 0: znear, 1: zfar
mjDEPTH_ZEROFAR = 1 // reversed depth map; 1: znear, 0: zfar
} mjtDepthMap;
typedef enum mjtFontScale_ { // font scale, used at context creation typedef enum mjtFontScale_ { // font scale, used at context creation
mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering
mjFONTSCALE_100 = 100, // normal scale, suitable in the absence of DPI scaling mjFONTSCALE_100 = 100, // normal scale, suitable in the absence of DPI scaling
@@ -1546,6 +1550,9 @@ struct mjrContext_ { // custom OpenGL context
// pixel output format // pixel output format
int readPixelFormat; // default color pixel format for mjr_readPixels int readPixelFormat; // default color pixel format for mjr_readPixels
// depth output format
int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR
}; };
typedef struct mjrContext_ mjrContext; typedef struct mjrContext_ mjrContext;
typedef enum mjtTaskStatus_ { // status values for mjTask typedef enum mjtTaskStatus_ { // status values for mjTask
+7
View File
@@ -43,6 +43,10 @@ typedef enum mjtFramebuffer_ { // OpenGL framebuffer option
mjFB_OFFSCREEN // offscreen buffer mjFB_OFFSCREEN // offscreen buffer
} mjtFramebuffer; } mjtFramebuffer;
typedef enum mjtDepthMap_ { // depth mapping for `mjr_readPixels`
mjDEPTH_ZERONEAR = 0, // standard depth map; 0: znear, 1: zfar
mjDEPTH_ZEROFAR = 1 // reversed depth map; 1: znear, 0: zfar
} mjtDepthMap;
typedef enum mjtFontScale_ { // font scale, used at context creation typedef enum mjtFontScale_ { // font scale, used at context creation
mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering
@@ -155,6 +159,9 @@ struct mjrContext_ { // custom OpenGL context
// pixel output format // pixel output format
int readPixelFormat; // default color pixel format for mjr_readPixels int readPixelFormat; // default color pixel format for mjr_readPixels
// depth output format
int readDepthMap; // depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR
}; };
typedef struct mjrContext_ mjrContext; typedef struct mjrContext_ mjrContext;
+9
View File
@@ -650,6 +650,15 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjFB_OFFSCREEN', 1), ('mjFB_OFFSCREEN', 1),
]), ]),
)), )),
('mjtDepthMap',
EnumDecl(
name='mjtDepthMap',
declname='enum mjtDepthMap_',
values=dict([
('mjDEPTH_ZERONEAR', 0),
('mjDEPTH_ZEROFAR', 1),
]),
)),
('mjtFontScale', ('mjtFontScale',
EnumDecl( EnumDecl(
name='mjtFontScale', name='mjtFontScale',
+5
View File
@@ -7905,6 +7905,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
type=ValueType(name='int'), type=ValueType(name='int'),
doc='default color pixel format for mjr_readPixels', doc='default color pixel format for mjr_readPixels',
), ),
StructFieldDecl(
name='readDepthMap',
type=ValueType(name='int'),
doc='depth mapping: mjDEPTH_ZERONEAR or mjDEPTH_ZEROFAR',
),
), ),
)), )),
('mjuiState', ('mjuiState',
+1
View File
@@ -215,6 +215,7 @@ PYBIND11_MODULE(_render, pymodule) {
X(windowDoublebuffer); X(windowDoublebuffer);
X(currentBuffer); X(currentBuffer);
X(readPixelFormat); X(readPixelFormat);
X(readDepthMap);
#undef X #undef X
#define X(var) \ #define X(var) \
+31 -5
View File
@@ -86,6 +86,7 @@ the clause:
_render.mjr_setBuffer( _render.mjr_setBuffer(
_enums.mjtFramebuffer.mjFB_OFFSCREEN.value, self._mjr_context _enums.mjtFramebuffer.mjFB_OFFSCREEN.value, self._mjr_context
) )
self._mjr_context.readDepthMap = _enums.mjtDepthMap.mjDEPTH_ZEROFAR
# Default render flags. # Default render flags.
self._depth_rendering = False self._depth_rendering = False
@@ -138,7 +139,9 @@ the clause:
""" """
original_flags = self._scene.flags.copy() original_flags = self._scene.flags.copy()
if self._segmentation_rendering: # Using segmented rendering for depth makes the calculated depth more
# accurate at far distances.
if self._depth_rendering or self._segmentation_rendering:
self._scene.flags[_enums.mjtRndFlag.mjRND_SEGMENT] = True self._scene.flags[_enums.mjtRndFlag.mjRND_SEGMENT] = True
self._scene.flags[_enums.mjtRndFlag.mjRND_IDCOLOR] = True self._scene.flags[_enums.mjtRndFlag.mjRND_IDCOLOR] = True
@@ -173,11 +176,34 @@ the clause:
near = self._model.vis.map.znear * extent near = self._model.vis.map.znear * extent
far = self._model.vis.map.zfar * extent far = self._model.vis.map.zfar * extent
# Convert from [0 1] to depth in units of length, see links below: # Calculate OpenGL perspective matrix values in float32 precision
# http://stackoverflow.com/a/6657284/1461210 # so they are close to what glFrustum returns
# https://www.khronos.org/opengl/wiki/Depth_Buffer_Precision # https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml
out = near / (1 - out * (1 - near / far)) zfar = np.float32(far)
znear = np.float32(near)
c_coef = -(zfar + znear) / (zfar - znear)
d_coef = -(np.float32(2) * zfar * znear) / (zfar - znear)
# In reverse Z mode the perspective matrix is transformed by the following
c_coef = np.float32(-0.5) * c_coef - np.float32(0.5)
d_coef = np.float32(-0.5) * d_coef
# We need 64 bits to convert Z from ndc to metric depth without noticeable
# losses in precision
out_64 = out.astype(np.float64)
# Undo OpenGL projection
# Note: We do not need to take action to convert from window coordinates
# to normalized device coordinates because in reversed Z mode the mapping
# is identity
out_64 = d_coef / (out_64 + c_coef)
# Cast result back to float32 for backwards compatibility
# This has a small accuracy cost
out[:] = out_64.astype(np.float32)
# Reset scene flags.
np.copyto(self._scene.flags, original_flags)
elif self._segmentation_rendering: elif self._segmentation_rendering:
_render.mjr_readPixels(out, None, self._rect, self._mjr_context) _render.mjr_readPixels(out, None, self._rect, self._mjr_context)
+15 -3
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
// Based on the OpenGL loader generated by glad 0.1.35 on Mon Mar 21 12:42:33 2022. // Based on the OpenGL loader generated by glad 0.1.34 on Thu Jun 22 14:40:03 2023.
// //
// The original generated code is distributed under CC0. // The original generated code is distributed under CC0.
// https://creativecommons.org/publicdomain/zero/1.0/ // https://creativecommons.org/publicdomain/zero/1.0/
@@ -22,6 +22,8 @@
// APIs: gl=1.5 // APIs: gl=1.5
// Profile: compatibility // Profile: compatibility
// Extensions: // Extensions:
// GL_ARB_clip_control,
// GL_ARB_depth_buffer_float,
// GL_ARB_framebuffer_object, // GL_ARB_framebuffer_object,
// GL_ARB_seamless_cube_map, // GL_ARB_seamless_cube_map,
// GL_ARB_vertex_buffer_object, // GL_ARB_vertex_buffer_object,
@@ -32,9 +34,9 @@
// Reproducible: False // Reproducible: False
// //
// Commandline: // Commandline:
// --profile="compatibility" --api="gl=1.5" --generator="c" --spec="gl" --extensions="GL_ARB_framebuffer_object,GL_ARB_seamless_cube_map,GL_ARB_vertex_buffer_object,GL_KHR_debug" // --profile="compatibility" --api="gl=1.5" --generator="c" --spec="gl" --extensions="GL_ARB_clip_control,GL_ARB_depth_buffer_float,GL_ARB_framebuffer_object,GL_ARB_seamless_cube_map,GL_ARB_vertex_buffer_object,GL_KHR_debug"
// Online: // Online:
// https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D1.5&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_seamless_cube_map&extensions=GL_ARB_vertex_buffer_object&extensions=GL_KHR_debug // https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D1.5&extensions=GL_ARB_clip_control&extensions=GL_ARB_depth_buffer_float&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_seamless_cube_map&extensions=GL_ARB_vertex_buffer_object&extensions=GL_KHR_debug
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -829,10 +831,13 @@ PFNGLWINDOWPOS3IPROC mjGlad_glWindowPos3i = NULL;
PFNGLWINDOWPOS3IVPROC mjGlad_glWindowPos3iv = NULL; PFNGLWINDOWPOS3IVPROC mjGlad_glWindowPos3iv = NULL;
PFNGLWINDOWPOS3SPROC mjGlad_glWindowPos3s = NULL; PFNGLWINDOWPOS3SPROC mjGlad_glWindowPos3s = NULL;
PFNGLWINDOWPOS3SVPROC mjGlad_glWindowPos3sv = NULL; PFNGLWINDOWPOS3SVPROC mjGlad_glWindowPos3sv = NULL;
int mjGLAD_GL_ARB_clip_control = 0;
int mjGLAD_GL_ARB_depth_buffer_float = 0;
int mjGLAD_GL_ARB_framebuffer_object = 0; int mjGLAD_GL_ARB_framebuffer_object = 0;
int mjGLAD_GL_ARB_seamless_cube_map = 0; int mjGLAD_GL_ARB_seamless_cube_map = 0;
int mjGLAD_GL_ARB_vertex_buffer_object = 0; int mjGLAD_GL_ARB_vertex_buffer_object = 0;
int mjGLAD_GL_KHR_debug = 0; int mjGLAD_GL_KHR_debug = 0;
PFNGLCLIPCONTROLPROC mjGlad_glClipControl = NULL;
PFNGLISRENDERBUFFERPROC mjGlad_glIsRenderbuffer = NULL; PFNGLISRENDERBUFFERPROC mjGlad_glIsRenderbuffer = NULL;
PFNGLBINDRENDERBUFFERPROC mjGlad_glBindRenderbuffer = NULL; PFNGLBINDRENDERBUFFERPROC mjGlad_glBindRenderbuffer = NULL;
PFNGLDELETERENDERBUFFERSPROC mjGlad_glDeleteRenderbuffers = NULL; PFNGLDELETERENDERBUFFERSPROC mjGlad_glDeleteRenderbuffers = NULL;
@@ -1355,6 +1360,10 @@ static void mjGlad_load_GL_VERSION_1_5(GLADloadproc load) {
mjGlad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv"); mjGlad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv");
mjGlad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv"); mjGlad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv");
} }
static void mjGlad_load_GL_ARB_clip_control(GLADloadproc load) {
if(!mjGLAD_GL_ARB_clip_control) return;
mjGlad_glClipControl = (PFNGLCLIPCONTROLPROC)load("glClipControl");
}
static void mjGlad_load_GL_ARB_framebuffer_object(GLADloadproc load) { static void mjGlad_load_GL_ARB_framebuffer_object(GLADloadproc load) {
if(!mjGLAD_GL_ARB_framebuffer_object) return; if(!mjGLAD_GL_ARB_framebuffer_object) return;
mjGlad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer"); mjGlad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
@@ -1419,6 +1428,8 @@ static void mjGlad_load_GL_KHR_debug(GLADloadproc load) {
} }
static int mjGlad_find_extensionsGL(void) { static int mjGlad_find_extensionsGL(void) {
if (!mjGlad_get_exts()) return 0; if (!mjGlad_get_exts()) return 0;
mjGLAD_GL_ARB_clip_control = mjGlad_has_ext("GL_ARB_clip_control");
mjGLAD_GL_ARB_depth_buffer_float = mjGlad_has_ext("GL_ARB_depth_buffer_float");
mjGLAD_GL_ARB_framebuffer_object = mjGlad_has_ext("GL_ARB_framebuffer_object"); mjGLAD_GL_ARB_framebuffer_object = mjGlad_has_ext("GL_ARB_framebuffer_object");
mjGLAD_GL_ARB_seamless_cube_map = mjGlad_has_ext("GL_ARB_seamless_cube_map"); mjGLAD_GL_ARB_seamless_cube_map = mjGlad_has_ext("GL_ARB_seamless_cube_map");
mjGLAD_GL_ARB_vertex_buffer_object = mjGlad_has_ext("GL_ARB_vertex_buffer_object"); mjGLAD_GL_ARB_vertex_buffer_object = mjGlad_has_ext("GL_ARB_vertex_buffer_object");
@@ -1491,6 +1502,7 @@ int mjGladLoadGLUnsafe(void) {
mjGlad_load_GL_VERSION_1_5(mjGlad_get_proc); mjGlad_load_GL_VERSION_1_5(mjGlad_get_proc);
if (!mjGlad_find_extensionsGL()) return 0; if (!mjGlad_find_extensionsGL()) return 0;
mjGlad_load_GL_ARB_clip_control(mjGlad_get_proc);
mjGlad_load_GL_ARB_framebuffer_object(mjGlad_get_proc); mjGlad_load_GL_ARB_framebuffer_object(mjGlad_get_proc);
mjGlad_load_GL_ARB_vertex_buffer_object(mjGlad_get_proc); mjGlad_load_GL_ARB_vertex_buffer_object(mjGlad_get_proc);
mjGlad_load_GL_KHR_debug(mjGlad_get_proc); mjGlad_load_GL_KHR_debug(mjGlad_get_proc);
+25 -3
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
// Based on the OpenGL loader generated by glad 0.1.35 on Mon Mar 21 12:42:33 2022. // Based on the OpenGL loader generated by glad 0.1.34 on Thu Jun 22 14:40:03 2023.
// //
// The original generated code is distributed under CC0. // The original generated code is distributed under CC0.
// https://creativecommons.org/publicdomain/zero/1.0/ // https://creativecommons.org/publicdomain/zero/1.0/
@@ -22,6 +22,8 @@
// APIs: gl=1.5 // APIs: gl=1.5
// Profile: compatibility // Profile: compatibility
// Extensions: // Extensions:
// GL_ARB_clip_control,
// GL_ARB_depth_buffer_float,
// GL_ARB_framebuffer_object, // GL_ARB_framebuffer_object,
// GL_ARB_seamless_cube_map, // GL_ARB_seamless_cube_map,
// GL_ARB_vertex_buffer_object, // GL_ARB_vertex_buffer_object,
@@ -32,9 +34,9 @@
// Reproducible: False // Reproducible: False
// //
// Commandline: // Commandline:
// --profile="compatibility" --api="gl=1.5" --generator="c" --spec="gl" --extensions="GL_ARB_framebuffer_object,GL_ARB_seamless_cube_map,GL_ARB_vertex_buffer_object,GL_KHR_debug" // --profile="compatibility" --api="gl=1.5" --generator="c" --spec="gl" --extensions="GL_ARB_clip_control,GL_ARB_depth_buffer_float,GL_ARB_framebuffer_object,GL_ARB_seamless_cube_map,GL_ARB_vertex_buffer_object,GL_KHR_debug"
// Online: // Online:
// https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D1.5&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_seamless_cube_map&extensions=GL_ARB_vertex_buffer_object&extensions=GL_KHR_debug // https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D1.5&extensions=GL_ARB_clip_control&extensions=GL_ARB_depth_buffer_float&extensions=GL_ARB_framebuffer_object&extensions=GL_ARB_seamless_cube_map&extensions=GL_ARB_vertex_buffer_object&extensions=GL_KHR_debug
#ifndef MUJOCO_SRC_RENDER_GLAD_GLAD_H_ #ifndef MUJOCO_SRC_RENDER_GLAD_GLAD_H_
#define MUJOCO_SRC_RENDER_GLAD_GLAD_H_ #define MUJOCO_SRC_RENDER_GLAD_GLAD_H_
@@ -2304,6 +2306,15 @@ typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname,
GLAPI PFNGLGETBUFFERPOINTERVPROC mjGlad_glGetBufferPointerv; GLAPI PFNGLGETBUFFERPOINTERVPROC mjGlad_glGetBufferPointerv;
#define glGetBufferPointerv mjGlad_glGetBufferPointerv #define glGetBufferPointerv mjGlad_glGetBufferPointerv
#endif #endif
#define GL_LOWER_LEFT 0x8CA1
#define GL_UPPER_LEFT 0x8CA2
#define GL_NEGATIVE_ONE_TO_ONE 0x935E
#define GL_ZERO_TO_ONE 0x935F
#define GL_CLIP_ORIGIN 0x935C
#define GL_CLIP_DEPTH_MODE 0x935D
#define GL_DEPTH_COMPONENT32F 0x8CAC
#define GL_DEPTH32F_STENCIL8 0x8CAD
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 #define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 #define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
@@ -2487,6 +2498,17 @@ GLAPI PFNGLGETBUFFERPOINTERVPROC mjGlad_glGetBufferPointerv;
#define GL_STACK_OVERFLOW_KHR 0x0503 #define GL_STACK_OVERFLOW_KHR 0x0503
#define GL_STACK_UNDERFLOW_KHR 0x0504 #define GL_STACK_UNDERFLOW_KHR 0x0504
#define GL_DISPLAY_LIST 0x82E7 #define GL_DISPLAY_LIST 0x82E7
#ifndef GL_ARB_clip_control
#define GL_ARB_clip_control 1
GLAPI int mjGLAD_GL_ARB_clip_control;
typedef void (APIENTRYP PFNGLCLIPCONTROLPROC)(GLenum origin, GLenum depth);
GLAPI PFNGLCLIPCONTROLPROC mjGlad_glClipControl;
#define glClipControl mjGlad_glClipControl
#endif
#ifndef GL_ARB_depth_buffer_float
#define GL_ARB_depth_buffer_float 1
GLAPI int mjGLAD_GL_ARB_depth_buffer_float;
#endif
#ifndef GL_ARB_framebuffer_object #ifndef GL_ARB_framebuffer_object
#define GL_ARB_framebuffer_object 1 #define GL_ARB_framebuffer_object 1
GLAPI int mjGLAD_GL_ARB_framebuffer_object; GLAPI int mjGLAD_GL_ARB_framebuffer_object;
+13 -8
View File
@@ -1062,7 +1062,7 @@ static void makeShadow(const mjModel* m, mjrContext* con) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
@@ -1126,11 +1126,14 @@ static void makeOff(mjrContext* con) {
mju_error("Could not allocate offscreen depth and stencil buffer"); mju_error("Could not allocate offscreen depth and stencil buffer");
} }
glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil); glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil);
GLenum depth_buffer_format =
mjGLAD_GL_ARB_depth_buffer_float ? GL_DEPTH32F_STENCIL8 : GL_DEPTH24_STENCIL8;
if (con->offSamples) { if (con->offSamples) {
glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, GL_DEPTH24_STENCIL8, glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, depth_buffer_format,
con->offWidth, con->offHeight); con->offWidth, con->offHeight);
} else { } else {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, con->offWidth, con->offHeight); glRenderbufferStorage(GL_RENDERBUFFER, depth_buffer_format, con->offWidth, con->offHeight);
} }
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, con->offDepthStencil); GL_RENDERBUFFER, con->offDepthStencil);
@@ -1169,7 +1172,7 @@ static void makeOff(mjrContext* con) {
mju_error("Could not allocate offscreen depth and stencil buffer_r"); mju_error("Could not allocate offscreen depth and stencil buffer_r");
} }
glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil_r); glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil_r);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, con->offWidth, con->offHeight); glRenderbufferStorage(GL_RENDERBUFFER, depth_buffer_format, con->offWidth, con->offHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, con->offDepthStencil_r); GL_RENDERBUFFER, con->offDepthStencil_r);
@@ -1535,7 +1538,6 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// free previous context
mjr_freeContext(con); mjr_freeContext(con);
// no model: offscreen and font only // no model: offscreen and font only
@@ -1607,6 +1609,9 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale,
// set default color pixel format for mjr_readPixels // set default color pixel format for mjr_readPixels
con->readPixelFormat = GL_RGB; con->readPixelFormat = GL_RGB;
// set default depth mapping for mjr_readPixels
con->readDepthMap = mjDEPTH_ZERONEAR;
} }
@@ -1830,10 +1835,10 @@ MJAPI void mjr_resizeOffscreen(int width, int height, mjrContext* con) {
glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil); glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil);
if (con->offSamples) { if (con->offSamples) {
glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, GL_DEPTH24_STENCIL8, glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, GL_DEPTH32F_STENCIL8,
con->offWidth, con->offHeight); con->offWidth, con->offHeight);
} else { } else {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, con->offWidth, con->offHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, con->offWidth, con->offHeight);
} }
if (con->offSamples) { if (con->offSamples) {
@@ -1841,6 +1846,6 @@ MJAPI void mjr_resizeOffscreen(int width, int height, mjrContext* con) {
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, con->offWidth, con->offHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, con->offWidth, con->offHeight);
glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil_r); glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil_r);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, con->offWidth, con->offHeight); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, con->offWidth, con->offHeight);
} }
} }
+20 -1
View File
@@ -14,6 +14,7 @@
#include "render/render_gl2.h" #include "render/render_gl2.h"
#include <math.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@@ -92,6 +93,23 @@ void mjr_restoreBuffer(const mjrContext* con) {
static inline void flipDepthIfRequired(float* depth, mjrRect viewport, const mjrContext* con) {
if (con->readDepthMap == mjDEPTH_ZERONEAR) {
int npixel = viewport.width * viewport.height;
for (int i = 0; i < npixel; i++) {
depth[i] = 1.0 - depth[i]; // Reverse the reversed Z buffer
}
} else if (!mjGLAD_GL_ARB_clip_control) {
mju_warning("ARB_clip_control unavailable while mjDEPTH_ZEROFAR requested, "
"depth accuracy will be limited");
} else if (!mjGLAD_GL_ARB_depth_buffer_float) {
mju_warning("ARB_depth_buffer_float unavailable while mjDEPTH_ZEROFAR requested, "
"depth accuracy will be limited");
}
}
// read pixels from current OpenGL framebuffer to client buffer // read pixels from current OpenGL framebuffer to client buffer
// viewport is in OpenGL framebuffer; client buffer starts at (0,0) // viewport is in OpenGL framebuffer; client buffer starts at (0,0)
void mjr_readPixels(unsigned char* rgb, float* depth, void mjr_readPixels(unsigned char* rgb, float* depth,
@@ -115,6 +133,7 @@ void mjr_readPixels(unsigned char* rgb, float* depth,
if (depth) { if (depth) {
glReadPixels(viewport.left, viewport.bottom, viewport.width, viewport.height, glReadPixels(viewport.left, viewport.bottom, viewport.width, viewport.height,
GL_DEPTH_COMPONENT, GL_FLOAT, depth); GL_DEPTH_COMPONENT, GL_FLOAT, depth);
flipDepthIfRequired(depth, viewport, con);
} }
} }
@@ -159,6 +178,7 @@ void mjr_readPixels(unsigned char* rgb, float* depth,
if (depth) { if (depth) {
glReadPixels(viewport.left, viewport.bottom, viewport.width, viewport.height, glReadPixels(viewport.left, viewport.bottom, viewport.width, viewport.height,
GL_DEPTH_COMPONENT, GL_FLOAT, depth); GL_DEPTH_COMPONENT, GL_FLOAT, depth);
flipDepthIfRequired(depth, viewport, con);
} }
// restore currentBuffer // restore currentBuffer
@@ -432,7 +452,6 @@ void mjr_text(int font, const char* txt, const mjrContext* con,
static int draw_overlay(int font, mjrRect viewport, int skip, int gridpos, static int draw_overlay(int font, mjrRect viewport, int skip, int gridpos,
float red, float green, float blue, float red, float green, float blue,
const char* overlay, const mjrContext* con) { const char* overlay, const mjrContext* con) {
int pos, ncthis, nc, nr, W, H, flg_big = (font == mjFONT_BIG); int pos, ncthis, nc, nr, W, H, flg_big = (font == mjFONT_BIG);
int PAD = 5, sz = mjMIN(mjMAXOVERLAY, (int)strlen(overlay)); int PAD = 5, sz = mjMIN(mjMAXOVERLAY, (int)strlen(overlay));
char text[mjMAXOVERLAY]; char text[mjMAXOVERLAY];
+34 -6
View File
@@ -580,6 +580,9 @@ static void initGL3(const mjvScene* scn, const mjrContext* con) {
// common options // common options
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);
if (mjGLAD_GL_ARB_clip_control) {
glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
}
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
if (scn->flags[mjRND_CULL_FACE]) { if (scn->flags[mjRND_CULL_FACE]) {
@@ -588,11 +591,11 @@ static void initGL3(const mjvScene* scn, const mjrContext* con) {
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_GEQUAL);
glDepthRange(0, 1); glDepthRange(0, 1);
glAlphaFunc(GL_GEQUAL, 0.99f); glAlphaFunc(GL_GEQUAL, 0.99f);
glClearColor(0, 0, 0, 0); glClearColor(0, 0, 0, 0);
glClearDepth(1); glClearDepth(0);
glClearStencil(0); glClearStencil(0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@@ -682,6 +685,15 @@ static void setView(int view, mjrRect viewport, const mjvScene* scn, const mjrCo
// set projection // set projection
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
if (mjGLAD_GL_ARB_clip_control) {
// reverse Z rendering mapping [znear, zfar] -> [1, 0] (ndc)
glTranslatef(0.0f, 0.0f, 0.5f);
glScalef(1.0f, 1.0f, -0.5f);
}
else {
// reverse Z rendering mapping without shift [znear, zfar] -> [1, -1] (ndc)
glScalef(1.0f, 1.0f, -1.0f);
}
glFrustum(cam.frustum_center - halfwidth, glFrustum(cam.frustum_center - halfwidth,
cam.frustum_center + halfwidth, cam.frustum_center + halfwidth,
cam.frustum_bottom, cam.frustum_bottom,
@@ -757,9 +769,15 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) {
float biasMatrix[16] = { float biasMatrix[16] = {
0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f 0.5f, 0.5f, 0.0f, 1.0f
}; };
if (!mjGLAD_GL_ARB_clip_control) {
// account for conversion from ndc to window coordinates
biasMatrix[2*4+2] = 0.5;
biasMatrix[3*4+2] = 0.5;
}
float tempMatrix[16], textureMatrix[16]; float tempMatrix[16], textureMatrix[16];
mjvGeom *thisgeom, tempgeom; mjvGeom *thisgeom, tempgeom;
mjvLight *thislight; mjvLight *thislight;
@@ -884,7 +902,7 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) {
} }
// render with stereo // render with stereo
for (int view=(stereo?0:-1); view < (stereo?2:0); view++) { for (int view = (stereo ? 0 : -1); view < (stereo ? 2 : 0); view++) {
// change drawbuffer for QUADBUFFERED stereo // change drawbuffer for QUADBUFFERED stereo
if (stereo == mjSTEREO_QUADBUFFERED) { if (stereo == mjSTEREO_QUADBUFFERED) {
if (con->windowDoublebuffer) { if (con->windowDoublebuffer) {
@@ -1107,6 +1125,15 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) {
// set projection: from light viewpoint // set projection: from light viewpoint
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
if (mjGLAD_GL_ARB_clip_control) {
// reverse Z rendering mapping [znear, zfar] -> [1, 0] (ndc)
glTranslatef(0.0f, 0.0f, 0.5f);
glScalef(1.0f, 1.0f, -0.5f);
}
else {
// reverse Z rendering mapping without shift [znear, zfar] -> [1, -1] (ndc)
glScalef(1.0f, 1.0f, -1.0f);
}
if (thislight->directional) { if (thislight->directional) {
glOrtho(-con->shadowClip, con->shadowClip, glOrtho(-con->shadowClip, con->shadowClip,
-con->shadowClip, con->shadowClip, -con->shadowClip, con->shadowClip,
@@ -1127,7 +1154,8 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) {
glBindFramebuffer(GL_FRAMEBUFFER, con->shadowFBO); glBindFramebuffer(GL_FRAMEBUFFER, con->shadowFBO);
glDrawBuffer(GL_NONE); glDrawBuffer(GL_NONE);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
glViewport(1, 1, con->shadowSize-2, con->shadowSize-2); // avoid infinite shadows from edges glViewport(
1, 1, con->shadowSize-2, con->shadowSize-2); // avoid infinite shadows from edges
glCullFace(GL_FRONT); glCullFace(GL_FRONT);
glShadeModel(GL_FLAT); glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
+5
View File
@@ -406,6 +406,10 @@ public enum mjtFramebuffer : int{
mjFB_WINDOW = 0, mjFB_WINDOW = 0,
mjFB_OFFSCREEN = 1, mjFB_OFFSCREEN = 1,
} }
public enum mjtDepthMap : int{
mjDEPTH_ZERONEAR = 0,
mjDEPTH_ZEROFAR = 1,
}
public enum mjtFontScale : int{ public enum mjtFontScale : int{
mjFONTSCALE_50 = 50, mjFONTSCALE_50 = 50,
mjFONTSCALE_100 = 100, mjFONTSCALE_100 = 100,
@@ -5596,6 +5600,7 @@ public unsafe struct mjrContext_ {
public int windowDoublebuffer; public int windowDoublebuffer;
public int currentBuffer; public int currentBuffer;
public int readPixelFormat; public int readPixelFormat;
public int readDepthMap;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]