mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
ENABLE_THUMBNAIL_GENERATOR -> Use multisampling when generating thumbnail using off-screen framebuffer
This commit is contained in:
parent
3ff3eed2b1
commit
a7b4b232e9
1 changed files with 114 additions and 38 deletions
|
@ -3567,6 +3567,29 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_THUMBNAIL_GENERATOR
|
#if ENABLE_THUMBNAIL_GENERATOR
|
||||||
|
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
static void debug_output_thumbnail(const ThumbnailData& thumbnail_data)
|
||||||
|
{
|
||||||
|
// debug export of generated image
|
||||||
|
wxImage image(thumbnail_data.width, thumbnail_data.height);
|
||||||
|
image.InitAlpha();
|
||||||
|
|
||||||
|
for (unsigned int r = 0; r < thumbnail_data.height; ++r)
|
||||||
|
{
|
||||||
|
unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width;
|
||||||
|
for (unsigned int c = 0; c < thumbnail_data.width; ++c)
|
||||||
|
{
|
||||||
|
unsigned char* px = (unsigned char*)thumbnail_data.pixels.data() + 4 * (rr + c);
|
||||||
|
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
|
||||||
|
image.SetAlpha((int)c, (int)r, px[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.SaveFile("C:/prusa/test/test.png", wxBITMAP_TYPE_PNG);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
|
||||||
static void render_volumes_in_thumbnail(const GLVolumePtrs& volumes, ThumbnailData& thumbnail_data, bool printable_only, bool parts_only)
|
static void render_volumes_in_thumbnail(const GLVolumePtrs& volumes, ThumbnailData& thumbnail_data, bool printable_only, bool parts_only)
|
||||||
{
|
{
|
||||||
auto is_visible = [](const GLVolume& v) -> bool
|
auto is_visible = [](const GLVolume& v) -> bool
|
||||||
|
@ -3617,26 +3640,6 @@ static void render_volumes_in_thumbnail(const GLVolumePtrs& volumes, ThumbnailDa
|
||||||
|
|
||||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||||
glsafe(::glDisable(GL_LIGHTING));
|
glsafe(::glDisable(GL_LIGHTING));
|
||||||
glsafe(::glReadPixels(0, 0, thumbnail_data.width, thumbnail_data.height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// debug export of generated image
|
|
||||||
wxImage image(thumbnail_data.width, thumbnail_data.height);
|
|
||||||
image.InitAlpha();
|
|
||||||
|
|
||||||
for (unsigned int r = 0; r < thumbnail_data.height; ++r)
|
|
||||||
{
|
|
||||||
unsigned int rr = (thumbnail_data.height - 1 - r) * thumbnail_data.width;
|
|
||||||
for (unsigned int c = 0; c < thumbnail_data.width; ++c)
|
|
||||||
{
|
|
||||||
unsigned char* px = thumbnail_data.pixels.data() + 4 * (rr + c);
|
|
||||||
image.SetRGB((int)c, (int)r, px[0], px[1], px[2]);
|
|
||||||
image.SetAlpha((int)c, (int)r, px[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image.SaveFile("C:/prusa/test/test.png", wxBITMAP_TYPE_PNG);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only)
|
void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only)
|
||||||
|
@ -3645,34 +3648,102 @@ void GLCanvas3D::_render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, un
|
||||||
if (!thumbnail_data.is_valid())
|
if (!thumbnail_data.is_valid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GLuint fbo;
|
bool multisample = m_multisample_allowed;
|
||||||
glsafe(::glGenFramebuffers(1, &fbo));
|
if (multisample)
|
||||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, fbo));
|
glsafe(::glEnable(GL_MULTISAMPLE));
|
||||||
|
|
||||||
GLuint tex;
|
GLint max_samples;
|
||||||
glsafe(::glGenTextures(1, &tex));
|
glsafe(::glGetIntegerv(GL_MAX_SAMPLES, &max_samples));
|
||||||
glsafe(::glBindTexture(GL_TEXTURE_2D, tex));
|
GLsizei num_samples = max_samples / 2;
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
|
||||||
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0));
|
|
||||||
|
|
||||||
GLuint depth;
|
GLuint render_fbo;
|
||||||
glsafe(::glGenRenderbuffers(1, &depth));
|
glsafe(::glGenFramebuffers(1, &render_fbo));
|
||||||
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, depth));
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, render_fbo));
|
||||||
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h));
|
|
||||||
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth));
|
GLuint render_tex = 0;
|
||||||
|
GLuint render_tex_buffer = 0;
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
// use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
|
||||||
|
glsafe(::glGenRenderbuffers(1, &render_tex_buffer));
|
||||||
|
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_tex_buffer));
|
||||||
|
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_RGBA8, w, h));
|
||||||
|
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, render_tex_buffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glsafe(::glGenTextures(1, &render_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_tex, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint render_depth;
|
||||||
|
glsafe(::glGenRenderbuffers(1, &render_depth));
|
||||||
|
glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_depth));
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_DEPTH_COMPONENT24, w, h));
|
||||||
|
else
|
||||||
|
glsafe(::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, render_depth));
|
||||||
|
|
||||||
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
glsafe(::glDrawBuffers(1, drawBufs));
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
render_volumes_in_thumbnail(m_volumes.volumes, thumbnail_data, printable_only, parts_only);
|
render_volumes_in_thumbnail(m_volumes.volumes, thumbnail_data, printable_only, parts_only);
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
{
|
||||||
|
GLuint resolve_fbo;
|
||||||
|
glsafe(::glGenFramebuffers(1, &resolve_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo));
|
||||||
|
|
||||||
|
GLuint resolve_tex;
|
||||||
|
glsafe(::glGenTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolve_tex, 0));
|
||||||
|
|
||||||
|
glsafe(::glDrawBuffers(1, drawBufs));
|
||||||
|
|
||||||
|
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, render_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo));
|
||||||
|
glsafe(::glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
|
||||||
|
|
||||||
|
glsafe(::glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo));
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glDeleteTextures(1, &resolve_tex));
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &resolve_fbo));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
}
|
||||||
|
|
||||||
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
glsafe(::glDeleteRenderbuffers(1, &depth));
|
glsafe(::glDeleteRenderbuffers(1, &render_depth));
|
||||||
glsafe(::glDeleteTextures(1, &tex));
|
if (render_tex_buffer != 0)
|
||||||
glsafe(::glDeleteFramebuffers(1, &fbo));
|
glsafe(::glDeleteRenderbuffers(1, &render_tex_buffer));
|
||||||
|
if (render_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &render_tex));
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &render_fbo));
|
||||||
|
|
||||||
|
if (multisample)
|
||||||
|
glsafe(::glDisable(GL_MULTISAMPLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only)
|
void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only)
|
||||||
|
@ -3694,6 +3765,11 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne
|
||||||
|
|
||||||
render_volumes_in_thumbnail(m_volumes.volumes, thumbnail_data, printable_only, parts_only);
|
render_volumes_in_thumbnail(m_volumes.volumes, thumbnail_data, printable_only, parts_only);
|
||||||
|
|
||||||
|
glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
|
||||||
|
#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
debug_output_thumbnail(thumbnail_data);
|
||||||
|
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
|
||||||
|
|
||||||
// restore the default framebuffer size to avoid flickering on the 3D scene
|
// restore the default framebuffer size to avoid flickering on the 3D scene
|
||||||
m_camera.apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height());
|
m_camera.apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue