瀏覽代碼

glx support for multisample

David Rose 21 年之前
父節點
當前提交
8bbda67e2a

+ 1 - 0
panda/src/display/graphicsEngine.cxx

@@ -78,6 +78,7 @@ GraphicsEngine(Pipeline *pipeline) :
   _frame_buffer_properties.set_frame_buffer_mode
   _frame_buffer_properties.set_frame_buffer_mode
     (FrameBufferProperties::FM_rgba | 
     (FrameBufferProperties::FM_rgba | 
      FrameBufferProperties::FM_double_buffer | 
      FrameBufferProperties::FM_double_buffer | 
+     FrameBufferProperties::FM_multisample | 
      FrameBufferProperties::FM_depth);
      FrameBufferProperties::FM_depth);
 
 
   set_threading_model(GraphicsThreadingModel(threading_model));
   set_threading_model(GraphicsThreadingModel(threading_model));

+ 42 - 15
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
 appear to be cutouts of the appropriate nature, which is another
 reason to use egg-palettize if you are not using it already.
 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.
-
-A third option is simply to disable the depth write on your
+If you don't use egg-palettize (you really should, you know), you can
+just hand-edit the egg files to put the line:
+
+  <Scalar> alpha { dual }
+
+within the <Texture> 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:
+
+  <Scalar> alpha { ms }
+
+within the <Texture> 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
 transparent objects.  This is most effective when you are trying to
 represent something that is barely visible, like glass or a soap
 represent something that is barely visible, like glass or a soap
 bubble.  Doing this doesn't improve the likelihood of correct sorting,
 bubble.  Doing this doesn't improve the likelihood of correct sorting,

+ 4 - 11
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -89,18 +89,12 @@ report_my_errors(int line, const char *source_file) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 enable_multisample(bool val) {
 enable_multisample(bool val) {
-  if (_multisample_enabled != val) {
+  if (_multisample_enabled != val && _supports_multisample) {
     _multisample_enabled = val;
     _multisample_enabled = val;
     if (val) {
     if (val) {
-      if (_supports_multisample) {
-        GLP(Enable)(GL_MULTISAMPLE);
-      }
-      GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST);
+      GLP(Enable)(GL_MULTISAMPLE);
     } else {
     } 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;
     _line_smooth_enabled = val;
     if (val) {
     if (val) {
       GLP(Enable)(GL_LINE_SMOOTH);
       GLP(Enable)(GL_LINE_SMOOTH);
-      GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_FASTEST);
+      GLP(Hint)(GL_LINE_SMOOTH_HINT, GL_NICEST);
     } else {
     } else {
       GLP(Disable)(GL_LINE_SMOOTH);
       GLP(Disable)(GL_LINE_SMOOTH);
     }
     }
@@ -137,7 +131,6 @@ enable_point_smooth(bool val) {
       GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST);
       GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_NICEST);
     } else {
     } else {
       GLP(Disable)(GL_POINT_SMOOTH);
       GLP(Disable)(GL_POINT_SMOOTH);
-      GLP(Hint)(GL_POINT_SMOOTH_HINT, GL_FASTEST);
     }
     }
   }
   }
 }
 }

+ 19 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -311,6 +311,7 @@ reset() {
 
 
   _supports_bgr = has_extension("GL_EXT_bgra");
   _supports_bgr = has_extension("GL_EXT_bgra");
   _supports_multisample = has_extension("GL_ARB_multisample");
   _supports_multisample = has_extension("GL_ARB_multisample");
+
   _supports_generate_mipmap = 
   _supports_generate_mipmap = 
     has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4);
     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;
     _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();
   report_my_gl_errors();
 
 
   _buffer_mask = 0;
   _buffer_mask = 0;
@@ -458,6 +476,7 @@ reset() {
 
 
   // Antialiasing.
   // Antialiasing.
   enable_line_smooth(false);
   enable_line_smooth(false);
+  enable_point_smooth(false);
   enable_multisample(true);
   enable_multisample(true);
 
 
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL

+ 15 - 18
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -430,7 +430,7 @@ choose_fbconfig(FrameBufferProperties &properties) const {
   // Now update our framebuffer_mode and bit depth appropriately.
   // Now update our framebuffer_mode and bit depth appropriately.
   int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
   int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
     alpha_size, ared_size, agreen_size, ablue_size, aalpha_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_RGBA, &render_mode);
   glXGetFBConfigAttrib(_display, fbconfig, GLX_DOUBLEBUFFER, &double_buffer);
   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_ACCUM_ALPHA_SIZE, &aalpha_size);
   glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size);
   glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size);
   glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size);
   glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size);
+  glXGetFBConfigAttrib(_display, fbconfig, GLX_SAMPLES, &samples);
 
 
   frame_buffer_mode = 0;
   frame_buffer_mode = 0;
   if (double_buffer) {
   if (double_buffer) {
@@ -468,6 +469,9 @@ choose_fbconfig(FrameBufferProperties &properties) const {
   if (ared_size + agreen_size + ablue_size != 0) {
   if (ared_size + agreen_size + ablue_size != 0) {
     frame_buffer_mode |= FrameBufferProperties::FM_accum;
     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_frame_buffer_mode(frame_buffer_mode);
   properties.set_color_bits(red_size + green_size + blue_size + alpha_size);
   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
       << ablue_size << " " << aalpha_size << endl
       << " Depth: " << depth_size << endl
       << " Depth: " << depth_size << endl
       << " Stencil: " << stencil_size << endl
       << " Stencil: " << stencil_size << endl
+      << " Samples: " << samples << endl
       << " DoubleBuffer? " << double_buffer << endl
       << " DoubleBuffer? " << double_buffer << endl
       << " Stereo? " << stereo << endl;
       << " Stereo? " << stereo << endl;
   }
   }
@@ -578,14 +583,13 @@ try_for_fbconfig(int framebuffer_mode,
       attrib_list[n++] = want_color_component_bits;
       attrib_list[n++] = want_color_component_bits;
     }
     }
   }
   }
-  /*
+
   if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
   if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
     glxdisplay_cat.debug(false) << " 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
     // We decide 4 is minimum number of samples
     attrib_list[n++] = 4;
     attrib_list[n++] = 4;
   }
   }
-  */
 
 
   // Terminate the list
   // Terminate the list
   nassertr(n < max_attrib_list, None);
   nassertr(n < max_attrib_list, None);
@@ -650,16 +654,6 @@ choose_visual(FrameBufferProperties &properties) const {
     want_color_bits = properties.get_color_bits();
     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 = 
   XVisualInfo *visual = 
     try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits);
     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.
   // Now update our framebuffer_mode and bit depth appropriately.
   int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
   int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
     alpha_size, ared_size, agreen_size, ablue_size, aalpha_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_RGBA, &render_mode);
   glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
   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_ACCUM_ALPHA_SIZE, &aalpha_size);
   glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
   glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
   glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
   glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
+  glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &samples);
 
 
   frame_buffer_mode = 0;
   frame_buffer_mode = 0;
   if (double_buffer) {
   if (double_buffer) {
@@ -816,6 +811,9 @@ choose_visual(FrameBufferProperties &properties) const {
   if (ared_size + agreen_size + ablue_size != 0) {
   if (ared_size + agreen_size + ablue_size != 0) {
     frame_buffer_mode |= FrameBufferProperties::FM_accum;
     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_frame_buffer_mode(frame_buffer_mode);
   properties.set_color_bits(red_size + green_size + blue_size + alpha_size);
   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
       << ablue_size << " " << aalpha_size << endl
       << " Depth: " << depth_size << endl
       << " Depth: " << depth_size << endl
       << " Stencil: " << stencil_size << endl
       << " Stencil: " << stencil_size << endl
+      << " Samples: " << samples << endl
       << " DoubleBuffer? " << double_buffer << endl
       << " DoubleBuffer? " << double_buffer << endl
       << " Stereo? " << stereo << endl;
       << " Stereo? " << stereo << endl;
   }
   }
@@ -911,14 +910,12 @@ try_for_visual(int framebuffer_mode,
       attrib_list[n++] = want_color_component_bits;
       attrib_list[n++] = want_color_component_bits;
     }
     }
   }
   }
-  /*
   if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
   if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
     glxdisplay_cat.debug(false) << " 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
     // We decide 4 is minimum number of samples
     attrib_list[n++] = 4;
     attrib_list[n++] = 4;
   }
   }
-  */
 
 
   // Terminate the list
   // Terminate the list
   nassertr(n < max_attrib_list, NULL);
   nassertr(n < max_attrib_list, NULL);

+ 6 - 0
panda/src/grutil/multitexReducer.cxx

@@ -730,6 +730,12 @@ make_texture_layer(const NodePath &render,
 
 
   geom.set_texture(stage_info._tex);
   geom.set_texture(stage_info._tex);
   geom.node()->set_attrib(cba);
   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);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////