Support reversed Z rendering and float32 offscreen depth buffer

Combined, both options greatly improve camera depth accuracy compared to
OpenGL default Z mapping and int24 depth buffer.

Requires GL_ARB_clip_control and ARB_depth_buffer_float extensions
This commit is contained in:
Levi Burner
2023-06-14 14:42:42 -04:00
parent e1549376f6
commit fc7b212369
10 changed files with 193 additions and 17 deletions
+28 -8
View File
@@ -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);
}
}