mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 18:03:56 -04:00
glx support for multisample
This commit is contained in:
parent
03dfb6dea0
commit
8bbda67e2a
@ -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));
|
||||
|
@ -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
|
||||
<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
|
||||
represent something that is barely visible, like glass or a soap
|
||||
bubble. Doing this doesn't improve the likelihood of correct sorting,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
x
Reference in New Issue
Block a user