From 8bbda67e2a2e7acc756a8a401900a8a2e950d9cd Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 17 Dec 2004 23:08:58 +0000 Subject: [PATCH] glx support for multisample --- panda/src/display/graphicsEngine.cxx | 1 + .../src/doc/howto.fix_transparency_issues.txt | 55 ++++++++++++++----- .../src/glstuff/glGraphicsStateGuardian_src.I | 15 ++--- .../glstuff/glGraphicsStateGuardian_src.cxx | 19 +++++++ panda/src/glxdisplay/glxGraphicsPipe.cxx | 33 +++++------ panda/src/grutil/multitexReducer.cxx | 6 ++ 6 files changed, 86 insertions(+), 43 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index efe40651f5..a8d4bcc56e 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -78,6 +78,7 @@ GraphicsEngine(Pipeline *pipeline) : _frame_buffer_properties.set_frame_buffer_mode (FrameBufferProperties::FM_rgba | FrameBufferProperties::FM_double_buffer | + FrameBufferProperties::FM_multisample | FrameBufferProperties::FM_depth); set_threading_model(GraphicsThreadingModel(threading_model)); diff --git a/panda/src/doc/howto.fix_transparency_issues.txt b/panda/src/doc/howto.fix_transparency_issues.txt index 4a845a81a7..cffba5574e 100755 --- a/panda/src/doc/howto.fix_transparency_issues.txt +++ b/panda/src/doc/howto.fix_transparency_issues.txt @@ -44,21 +44,48 @@ on automatically for a particular model if it detects textures that appear to be cutouts of the appropriate nature, which is another reason to use egg-palettize if you are not using it already. -Second, an easy thing to do is to chop up one or both competing models -into smaller pieces, each of which can be sorted independently by -Panda. For instance, you can split one big polygon into a grid of -little polygons, and the sorting is more likely to be accurate for -each piece (because the center of the bounding volume is closer to the -pixels). You can draw a picture to see how this works. In order to -do this properly, you can't just make it one big mesh of small -polygons, since Panda will make a mesh into a single Geom of -tristrips; instead, it needs to be separate meshes, so that each one -will become its own Geom. Obviously, this is slightly more expensive -too, since you are introducing additional vertices and adding more -objects to the sort list; so you don't want to go too crazy with the -smallness of your polygons. +If you don't use egg-palettize (you really should, you know), you can +just hand-edit the egg files to put the line: -A third option is simply to disable the depth write on your + alpha { dual } + +within the reference for the textures in question. + +A second easy option is to use M_multisample transparency, which +doesn't have any ordering issues at all, but it only looks good on +very high-end cards that have special multisample bits to support +full-screen antialiasing. Also, at the present it only looks good on +these high-end cards in OpenGL mode (since our pandadx drivers don't +support M_multisample explicitly right now). But if M_multisample is +not supported by a particular hardware or panda driver, it +automatically falls back to M_binary, which also doesn't have any +ordering issues, but it always has jaggy edges along the cutout edge. +This only works well on texture images that represent cutouts, like +M_dual, above. + +If you use egg-palettize, you can engage M_multisample mode by putting +the keyword "ms" on the line with the texture(s). Without +egg-palettize, hand-edit the egg files to put the line: + + alpha { ms } + +within the reference for the textures in question. + +A third easy option is to chop up one or both competing models into +smaller pieces, each of which can be sorted independently by Panda. +For instance, you can split one big polygon into a grid of little +polygons, and the sorting is more likely to be accurate for each piece +(because the center of the bounding volume is closer to the pixels). +You can draw a picture to see how this works. In order to do this +properly, you can't just make it one big mesh of small polygons, since +Panda will make a mesh into a single Geom of tristrips; instead, it +needs to be separate meshes, so that each one will become its own +Geom. Obviously, this is slightly more expensive too, since you are +introducing additional vertices and adding more objects to the sort +list; so you don't want to go too crazy with the smallness of your +polygons. + +A fourth option is simply to disable the depth write on your transparent objects. This is most effective when you are trying to represent something that is barely visible, like glass or a soap bubble. Doing this doesn't improve the likelihood of correct sorting, diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.I b/panda/src/glstuff/glGraphicsStateGuardian_src.I index f620969d74..5b62e4a3f0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.I +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.I @@ -89,18 +89,12 @@ report_my_errors(int line, const char *source_file) { //////////////////////////////////////////////////////////////////// INLINE void CLP(GraphicsStateGuardian):: enable_multisample(bool val) { - if (_multisample_enabled != val) { + if (_multisample_enabled != val && _supports_multisample) { _multisample_enabled = val; if (val) { - if (_supports_multisample) { - GLP(Enable)(GL_MULTISAMPLE); - } - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST); + GLP(Enable)(GL_MULTISAMPLE); } else { - if (_supports_multisample) { - GLP(Disable)(GL_MULTISAMPLE); - } - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_FASTEST); + GLP(Disable)(GL_MULTISAMPLE); } } } @@ -116,7 +110,7 @@ enable_line_smooth(bool val) { _line_smooth_enabled = val; if (val) { GLP(Enable)(GL_LINE_SMOOTH); - GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_FASTEST); + GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_NICEST); } else { GLP(Disable)(GL_LINE_SMOOTH); } @@ -137,7 +131,6 @@ enable_point_smooth(bool val) { GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST); } else { GLP(Disable)(GL_POINT_SMOOTH); - GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_FASTEST); } } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 87c2584fd2..dec811833e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -311,6 +311,7 @@ reset() { _supports_bgr = has_extension("GL_EXT_bgra"); _supports_multisample = has_extension("GL_ARB_multisample"); + _supports_generate_mipmap = has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4); @@ -397,6 +398,23 @@ reset() { _mirror_border_clamp = GL_MIRROR_CLAMP_TO_BORDER_EXT; } + if (_supports_multisample) { + GLint sample_buffers; + GLP(GetIntegerv)(GL_SAMPLE_BUFFERS, &sample_buffers); + if (sample_buffers != 1) { + _supports_multisample = false; + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Selected frame buffer does not provide antialiasing support.\n"; + } + } else { + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Selected frame buffer provides antialiasing support.\n"; + } + } + } + report_my_gl_errors(); _buffer_mask = 0; @@ -458,6 +476,7 @@ reset() { // Antialiasing. enable_line_smooth(false); + enable_point_smooth(false); enable_multisample(true); #ifdef HAVE_CGGL diff --git a/panda/src/glxdisplay/glxGraphicsPipe.cxx b/panda/src/glxdisplay/glxGraphicsPipe.cxx index d80509155b..9fa747641e 100644 --- a/panda/src/glxdisplay/glxGraphicsPipe.cxx +++ b/panda/src/glxdisplay/glxGraphicsPipe.cxx @@ -430,7 +430,7 @@ choose_fbconfig(FrameBufferProperties &properties) const { // Now update our framebuffer_mode and bit depth appropriately. int render_mode, double_buffer, stereo, red_size, green_size, blue_size, alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, - depth_size, stencil_size; + depth_size, stencil_size, samples; glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &render_mode); glXGetFBConfigAttrib(_display, fbconfig, GLX_DOUBLEBUFFER, &double_buffer); @@ -445,6 +445,7 @@ choose_fbconfig(FrameBufferProperties &properties) const { glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size); glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size); + glXGetFBConfigAttrib(_display, fbconfig, GLX_SAMPLES, &samples); frame_buffer_mode = 0; if (double_buffer) { @@ -468,6 +469,9 @@ choose_fbconfig(FrameBufferProperties &properties) const { if (ared_size + agreen_size + ablue_size != 0) { frame_buffer_mode |= FrameBufferProperties::FM_accum; } + if (samples != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_multisample; + } properties.set_frame_buffer_mode(frame_buffer_mode); properties.set_color_bits(red_size + green_size + blue_size + alpha_size); @@ -482,6 +486,7 @@ choose_fbconfig(FrameBufferProperties &properties) const { << ablue_size << " " << aalpha_size << endl << " Depth: " << depth_size << endl << " Stencil: " << stencil_size << endl + << " Samples: " << samples << endl << " DoubleBuffer? " << double_buffer << endl << " Stereo? " << stereo << endl; } @@ -578,14 +583,13 @@ try_for_fbconfig(int framebuffer_mode, attrib_list[n++] = want_color_component_bits; } } - /* + if (framebuffer_mode & FrameBufferProperties::FM_multisample) { glxdisplay_cat.debug(false) << " MULTISAMPLE"; - attrib_list[n++] = GLX_SAMPLES_SGIS; + attrib_list[n++] = GLX_SAMPLES; // We decide 4 is minimum number of samples attrib_list[n++] = 4; } - */ // Terminate the list nassertr(n < max_attrib_list, None); @@ -650,16 +654,6 @@ choose_visual(FrameBufferProperties &properties) const { want_color_bits = properties.get_color_bits(); } - /* - if (frame_buffer_mode & FrameBufferProperties::FM_multisample) { - if (!glx_supports("GLX_SGIS_multisample")) { - glxdisplay_cat.info() - << "multisample not supported by this glx implementation.\n"; - frame_buffer_mode &= ~FrameBufferProperties::FM_multisample; - } - } - */ - XVisualInfo *visual = try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits); @@ -778,7 +772,7 @@ choose_visual(FrameBufferProperties &properties) const { // Now update our framebuffer_mode and bit depth appropriately. int render_mode, double_buffer, stereo, red_size, green_size, blue_size, alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, - depth_size, stencil_size; + depth_size, stencil_size, samples; glXGetConfig(_display, visual, GLX_RGBA, &render_mode); glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer); @@ -793,6 +787,7 @@ choose_visual(FrameBufferProperties &properties) const { glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size); glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size); + glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &samples); frame_buffer_mode = 0; if (double_buffer) { @@ -816,6 +811,9 @@ choose_visual(FrameBufferProperties &properties) const { if (ared_size + agreen_size + ablue_size != 0) { frame_buffer_mode |= FrameBufferProperties::FM_accum; } + if (samples != 0) { + frame_buffer_mode |= FrameBufferProperties::FM_multisample; + } properties.set_frame_buffer_mode(frame_buffer_mode); properties.set_color_bits(red_size + green_size + blue_size + alpha_size); @@ -830,6 +828,7 @@ choose_visual(FrameBufferProperties &properties) const { << ablue_size << " " << aalpha_size << endl << " Depth: " << depth_size << endl << " Stencil: " << stencil_size << endl + << " Samples: " << samples << endl << " DoubleBuffer? " << double_buffer << endl << " Stereo? " << stereo << endl; } @@ -911,14 +910,12 @@ try_for_visual(int framebuffer_mode, attrib_list[n++] = want_color_component_bits; } } - /* if (framebuffer_mode & FrameBufferProperties::FM_multisample) { glxdisplay_cat.debug(false) << " MULTISAMPLE"; - attrib_list[n++] = GLX_SAMPLES_SGIS; + attrib_list[n++] = GLX_SAMPLES; // We decide 4 is minimum number of samples attrib_list[n++] = 4; } - */ // Terminate the list nassertr(n < max_attrib_list, NULL); diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index 9baaeb7737..1db9833460 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -730,6 +730,12 @@ make_texture_layer(const NodePath &render, geom.set_texture(stage_info._tex); geom.node()->set_attrib(cba); + + if (grutil_cat.is_debug()) { + GeomNode *geom_node; + DCAST_INTO_V(geom_node, geom.node()); + geom_node->write_verbose(grutil_cat.debug(), 0); + } } ////////////////////////////////////////////////////////////////////