diff --git a/include/mujoco/mjrender.h b/include/mujoco/mjrender.h index fb37d926..cd11423b 100644 --- a/include/mujoco/mjrender.h +++ b/include/mujoco/mjrender.h @@ -39,6 +39,15 @@ typedef enum mjtFramebuffer_ { // OpenGL framebuffer option mjFB_OFFSCREEN // offscreen buffer } mjtFramebuffer; +typedef enum mjtDepthMapping_ { // OpenGL depth buffer mapping (from znear to zfar) + mjDB_NEGONETOONE = 0, // Negative one to one (OpenGL default) + mjDB_ONETOZERO // Reversed Z buffer (decreases numerical error) +} mjtDepthMapping; + +typedef enum mjtDepthPrecision_ { // OpenGL depth buffer precision + mjDB_INT24 = 0, // 24 bit integer buffer (OpenGL default) + mjDB_FLOAT32 // 32 bit float buffer +} mjtDepthPrecision; typedef enum mjtFontScale_ { // font scale, used at context creation mjFONTSCALE_50 = 50, // 50% scale, suitable for low-res rendering @@ -151,6 +160,12 @@ struct mjrContext_ { // custom OpenGL context // pixel output format int readPixelFormat; // default color pixel format for mjr_readPixels + + // depth buffer mode + int depthMapping; // depth buffer mapping from [znear zfar] to normalized device coordinates: mjDB_NEGONETOONE or mjDB_ONETOZERO + + // depth buffer precision + int depthPrecision; // depth buffer precision: mjDB_INT24 or mjDB_FLOAT32 }; typedef struct mjrContext_ mjrContext; diff --git a/introspect/enums.py b/introspect/enums.py index fbee5402..d14523b3 100644 --- a/introspect/enums.py +++ b/introspect/enums.py @@ -621,6 +621,24 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjFB_OFFSCREEN', 1), ]), )), + ('mjtDepthMapping', + EnumDecl( + name='mjtDepthMapping', + declname='enum mjtDepthMapping_', + values=dict([ + ('mjDB_NEGONETOONE', 0), + ('mjDB_ONETOZERO', 1), + ]), + )), + ('mjtDepthPrecision', + EnumDecl( + name='mjtDepthPrecision', + declname='enum mjtDepthPrecision_', + values=dict([ + ('mjDB_INT24', 0), + ('mjDB_FLOAT32', 1), + ]), + )), ('mjtFontScale', EnumDecl( name='mjtFontScale', diff --git a/introspect/structs.py b/introspect/structs.py index a06e9a67..fd718da4 100644 --- a/introspect/structs.py +++ b/introspect/structs.py @@ -7126,6 +7126,16 @@ STRUCTS: Mapping[str, StructDecl] = dict([ type=ValueType(name='int'), doc='default color pixel format for mjr_readPixels', ), + StructFieldDecl( + name='depthMapping', + type=ValueType(name='int'), + doc='depth buffer mapping from [znear zfar] to normalized device coordinates: mjDB_NEGONETOONE or mjDB_ONETOZERO', # pylint: disable=line-too-long + ), + StructFieldDecl( + name='depthPrecision', + type=ValueType(name='int'), + doc='depth buffer precision: mjDB_INT24 or mjDB_FLOAT32', + ), ), )), ('mjuiState', diff --git a/python/mujoco/render.cc b/python/mujoco/render.cc index 622bbb7a..c1d2b9c8 100644 --- a/python/mujoco/render.cc +++ b/python/mujoco/render.cc @@ -34,6 +34,10 @@ class MjWrapper : public WrapperBase { public: MjWrapper(); MjWrapper(const MjModelWrapper& model, int fontscale); + MjWrapper(const MjModelWrapper& model, + int fontscale, + mjtDepthMapping depthmapping, + mjtDepthPrecision depthprecision); MjWrapper(const MjWrapper&) = delete; MjWrapper(MjWrapper&&) = default; ~MjWrapper() = default; @@ -122,6 +126,35 @@ MjrContextWrapper::MjWrapper(const MjModelWrapper& model, int fontscale) X_SKIN(skinfaceVBO), X(charWidth), X(charWidthBig) {} + +MjrContextWrapper::MjWrapper(const MjModelWrapper& model, + int fontscale, + mjtDepthMapping depthmapping, + mjtDepthPrecision depthprecision) + : WrapperBase([fontscale, depthmapping, depthprecision](const raw::MjModel* m) { + raw::MjrContext *const ctx = new raw::MjrContext; + mjr_defaultContext(ctx); + ctx->depthMapping = depthmapping; + ctx->depthPrecision = depthprecision; + InterceptMjErrors(mjr_makeContext)(m, ctx, fontscale); + return ctx; + }(model.get()), &MjrContextCapsuleDestructor), + X(fogRGBA), + X(auxWidth), + X(auxHeight), + X(auxSamples), + X(auxFBO), + X(auxFBO_r), + X(auxColor), + X(auxColor_r), + X(textureType), + X(texture), + X_SKIN(skinvertVBO), + X_SKIN(skinnormalVBO), + X_SKIN(skintexcoordVBO), + X_SKIN(skinfaceVBO), + X(charWidth), + X(charWidthBig) {} #undef X_SKIN #undef X @@ -166,6 +199,7 @@ PYBIND11_MODULE(_render, pymodule) { py::class_ mjrContext(pymodule, "MjrContext"); mjrContext.def(py::init<>()); mjrContext.def(py::init()); + mjrContext.def(py::init()); mjrContext.def( "free", [](MjrContextWrapper& self) { self.Free(); }, py::doc("Frees resources in current active OpenGL context, sets struct " diff --git a/simulate/platform_ui_adapter.cc b/simulate/platform_ui_adapter.cc index 5f502a47..f5b154ed 100644 --- a/simulate/platform_ui_adapter.cc +++ b/simulate/platform_ui_adapter.cc @@ -27,6 +27,7 @@ void PlatformUIAdapter::FreeMjrContext() { bool PlatformUIAdapter::RefreshMjrContext(const mjModel* m, int fontscale) { if (m != last_model_ || fontscale != last_fontscale_) { + // con_.depthMapping = mjDB_ONETOZERO; mjr_makeContext(m, &con_, fontscale); last_model_ = m; last_fontscale_ = fontscale; diff --git a/src/render/glad/glad.c b/src/render/glad/glad.c index 9b5e4c6d..fa1642c4 100644 --- a/src/render/glad/glad.c +++ b/src/render/glad/glad.c @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // 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. // https://creativecommons.org/publicdomain/zero/1.0/ @@ -22,6 +22,8 @@ // APIs: gl=1.5 // Profile: compatibility // Extensions: +// GL_ARB_clip_control, +// GL_ARB_depth_buffer_float, // GL_ARB_framebuffer_object, // GL_ARB_seamless_cube_map, // GL_ARB_vertex_buffer_object, @@ -32,9 +34,9 @@ // Reproducible: False // // 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: -// 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__) #pragma GCC diagnostic push @@ -829,10 +831,13 @@ PFNGLWINDOWPOS3IPROC mjGlad_glWindowPos3i = NULL; PFNGLWINDOWPOS3IVPROC mjGlad_glWindowPos3iv = NULL; PFNGLWINDOWPOS3SPROC mjGlad_glWindowPos3s = 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_seamless_cube_map = 0; int mjGLAD_GL_ARB_vertex_buffer_object = 0; int mjGLAD_GL_KHR_debug = 0; +PFNGLCLIPCONTROLPROC mjGlad_glClipControl = NULL; PFNGLISRENDERBUFFERPROC mjGlad_glIsRenderbuffer = NULL; PFNGLBINDRENDERBUFFERPROC mjGlad_glBindRenderbuffer = 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_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) { if(!mjGLAD_GL_ARB_framebuffer_object) return; mjGlad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer"); @@ -1419,6 +1428,8 @@ static void mjGlad_load_GL_KHR_debug(GLADloadproc load) { } static int mjGlad_find_extensionsGL(void) { 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_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"); @@ -1491,6 +1502,7 @@ int mjGladLoadGLUnsafe(void) { mjGlad_load_GL_VERSION_1_5(mjGlad_get_proc); 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_vertex_buffer_object(mjGlad_get_proc); mjGlad_load_GL_KHR_debug(mjGlad_get_proc); diff --git a/src/render/glad/glad.h b/src/render/glad/glad.h index 4fc2c6c8..1b1fd449 100644 --- a/src/render/glad/glad.h +++ b/src/render/glad/glad.h @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // 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. // https://creativecommons.org/publicdomain/zero/1.0/ @@ -22,6 +22,8 @@ // APIs: gl=1.5 // Profile: compatibility // Extensions: +// GL_ARB_clip_control, +// GL_ARB_depth_buffer_float, // GL_ARB_framebuffer_object, // GL_ARB_seamless_cube_map, // GL_ARB_vertex_buffer_object, @@ -32,9 +34,9 @@ // Reproducible: False // // 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: -// 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_ #define MUJOCO_SRC_RENDER_GLAD_GLAD_H_ @@ -2304,6 +2306,15 @@ typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, GLAPI PFNGLGETBUFFERPOINTERVPROC mjGlad_glGetBufferPointerv; #define glGetBufferPointerv mjGlad_glGetBufferPointerv #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_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 #define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 @@ -2487,6 +2498,17 @@ GLAPI PFNGLGETBUFFERPOINTERVPROC mjGlad_glGetBufferPointerv; #define GL_STACK_OVERFLOW_KHR 0x0503 #define GL_STACK_UNDERFLOW_KHR 0x0504 #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 #define GL_ARB_framebuffer_object 1 GLAPI int mjGLAD_GL_ARB_framebuffer_object; diff --git a/src/render/render_context.c b/src/render/render_context.c index 18c71805..6ba5da82 100644 --- a/src/render/render_context.c +++ b/src/render/render_context.c @@ -1062,7 +1062,11 @@ 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_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_FUNC, GL_LEQUAL); + if (con->depthMapping == mjDB_ONETOZERO) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GEQUAL); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + } glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); @@ -1121,16 +1125,17 @@ static void makeOff(mjrContext* con) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, con->offColor); // create depth and stencil buffer + GLenum depth_buffer_format = con->depthPrecision == mjDB_FLOAT32 ? GL_DEPTH32F_STENCIL8 : GL_DEPTH24_STENCIL8; glGenRenderbuffers(1, &con->offDepthStencil); if (!con->offDepthStencil) { mju_error("Could not allocate offscreen depth and stencil buffer"); } glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil); if (con->offSamples) { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, GL_DEPTH24_STENCIL8, + glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, depth_buffer_format, con->offWidth, con->offHeight); } 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, GL_RENDERBUFFER, con->offDepthStencil); @@ -1169,7 +1174,7 @@ static void makeOff(mjrContext* con) { mju_error("Could not allocate offscreen depth and stencil buffer_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, GL_RENDERBUFFER, con->offDepthStencil_r); @@ -1489,6 +1494,12 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale, if (!mjGLAD_GL_ARB_vertex_buffer_object) { mju_error("OpenGL ARB_vertex_buffer_object required"); } + if (!mjGLAD_GL_ARB_clip_control) { + mju_error("OpenGL ARB_clip_control required"); + } + if (!mjGLAD_GL_ARB_depth_buffer_float) { + mju_error("OpenGL ARB_depth_buffer_float required"); + } con->glInitialized = 1; // determine window availability (could be EGL-headless) @@ -1535,8 +1546,15 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale, glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // free previous context + // free previous context but keep depth settings + // Doing this is the only way users can control these + // settings without breaking changes to either the + // behaviour of mjr_makeContext or the signature + int oldDepthMapping = con->depthMapping; + int oldDepthPrecision = con->depthPrecision; mjr_freeContext(con); + con->depthMapping = oldDepthMapping; + con->depthPrecision = oldDepthPrecision; // no model: offscreen and font only if (!m) { @@ -1828,12 +1846,14 @@ MJAPI void mjr_resizeOffscreen(int width, int height, mjrContext* con) { glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, con->offWidth, con->offHeight); } + + GLenum depth_buffer_format = con->depthPrecision == mjDB_FLOAT32 ? GL_DEPTH32F_STENCIL8 : GL_DEPTH24_STENCIL8; glBindRenderbuffer(GL_RENDERBUFFER, con->offDepthStencil); if (con->offSamples) { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, GL_DEPTH24_STENCIL8, + glRenderbufferStorageMultisample(GL_RENDERBUFFER, con->offSamples, depth_buffer_format, con->offWidth, con->offHeight); } else { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, con->offWidth, con->offHeight); + glRenderbufferStorage(GL_RENDERBUFFER, depth_buffer_format, con->offWidth, con->offHeight); } if (con->offSamples) { @@ -1841,6 +1861,6 @@ MJAPI void mjr_resizeOffscreen(int width, int height, mjrContext* con) { glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, con->offWidth, con->offHeight); 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); } } diff --git a/src/render/render_gl3.c b/src/render/render_gl3.c index 526e130c..97e18715 100644 --- a/src/render/render_gl3.c +++ b/src/render/render_gl3.c @@ -498,6 +498,11 @@ static void initGL3(const mjvScene* scn, const mjrContext* con) { // common options glDisable(GL_BLEND); glEnable(GL_NORMALIZE); + if (con->depthMapping == mjDB_ONETOZERO) { + glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); + } else { + glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE); + } glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); if (scn->flags[mjRND_CULL_FACE]) { @@ -506,11 +511,19 @@ static void initGL3(const mjvScene* scn, const mjrContext* con) { glDisable(GL_CULL_FACE); } glShadeModel(GL_SMOOTH); - glDepthFunc(GL_LEQUAL); + if (con->depthMapping == mjDB_ONETOZERO) { + glDepthFunc(GL_GEQUAL); + } else { + glDepthFunc(GL_LEQUAL); + } glDepthRange(0, 1); glAlphaFunc(GL_GEQUAL, 0.99f); glClearColor(0, 0, 0, 0); - glClearDepth(1); + if (con->depthMapping == mjDB_ONETOZERO) { + glClearDepth(0); + } else { + glClearDepth(1); + } glClearStencil(0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -600,6 +613,11 @@ static void setView(int view, mjrRect viewport, const mjvScene* scn, const mjrCo // set projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); + if (con->depthMapping == mjDB_ONETOZERO) { + // account for GL_ZERO_TO_ONE and reverse Z + glTranslatef(0,0,0.5); + glScalef(1,1,-0.5); + } glFrustum(cam.frustum_center - halfwidth, cam.frustum_center + halfwidth, cam.frustum_bottom, @@ -672,12 +690,25 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) { float temp[4], headpos[3], forward[3], skyboxdst; float camProject[16], camView[16], lightProject[16], lightView[16]; double clipplane[4]; - float biasMatrix[16] = { + float biasMatrixOneToZero[16] = { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f + }; + float biasMatrixNegOneToOne[16] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f }; + float* biasMatrix; + if (con->depthMapping == mjDB_ONETOZERO) { + biasMatrix = biasMatrixOneToZero; + } else { + biasMatrix = biasMatrixNegOneToOne; + } + float tempMatrix[16], textureMatrix[16]; mjvGeom *thisgeom, tempgeom; mjvLight *thislight; @@ -1025,6 +1056,11 @@ void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con) { // set projection: from light viewpoint glMatrixMode(GL_PROJECTION); glLoadIdentity(); + if (con->depthMapping == mjDB_ONETOZERO) { + // account for GL_ZERO_TO_ONE and reverse Z + glTranslatef(0,0,0.5); + glScalef(1,1,-0.5); + } if (thislight->directional) { glOrtho(-con->shadowClip, con->shadowClip, -con->shadowClip, con->shadowClip, diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index ac5c8161..40e938b3 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -389,6 +389,14 @@ public enum mjtFramebuffer : int{ mjFB_WINDOW = 0, mjFB_OFFSCREEN = 1, } +public enum mjtDepthMapping : int{ + mjDB_NEGONETOONE = 0, + mjDB_ONETOZERO = 1, +} +public enum mjtDepthPrecision : int{ + mjDB_INT24 = 0, + mjDB_FLOAT32 = 1, +} public enum mjtFontScale : int{ mjFONTSCALE_50 = 50, mjFONTSCALE_100 = 100,