Improved rendering of transparent volumes

This commit is contained in:
Enrico Turri 2018-12-21 09:56:11 +01:00
parent 3182611ac2
commit 5006633221
4 changed files with 135 additions and 1 deletions

View File

@ -44,6 +44,8 @@
#define ENABLE_RENDER_SELECTION_CENTER (0 && ENABLE_1_42_0)
// Show visual hints in the 3D scene when sidebar matrix fields have focus
#define ENABLE_SIDEBAR_VISUAL_HINTS (1 && ENABLE_1_42_0)
// Separate rendering for opaque and transparent volumes
#define ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_1_42_0)
#endif // _technologies_h_

View File

@ -797,6 +797,9 @@ int GLVolumeCollection::load_object_volume(
color[2] = 1.0f;
}
color[3] = model_volume->is_model_part() ? 1.f : 0.5f; */
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
color[3] = model_volume->is_model_part() ? 1.f : 0.5f;
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
this->volumes.emplace_back(new GLVolume(color));
GLVolume &v = *this->volumes.back();
v.set_color_from_model_volume(model_volume);
@ -953,12 +956,54 @@ int GLVolumeCollection::load_wipe_tower_preview(
return int(this->volumes.size() - 1);
}
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
typedef std::pair<GLVolume*, double> GLVolumeWithZ;
typedef std::vector<GLVolumeWithZ> GLVolumesWithZList;
GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type)
{
GLVolumesWithZList list;
for (GLVolume* volume : volumes)
{
bool is_transparent = (volume->render_color[3] < 1.0f);
if (((type == GLVolumeCollection::Opaque) && !is_transparent) ||
((type == GLVolumeCollection::Transparent) && is_transparent) ||
(type == GLVolumeCollection::All))
list.push_back(std::make_pair(volume, 0.0));
}
if ((type == GLVolumeCollection::Transparent) && (list.size() > 1))
{
Transform3d modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
for (GLVolumeWithZ& volume : list)
{
volume.second = volume.first->bounding_box.transformed(modelview_matrix * volume.first->world_matrix()).max(2);
}
std::sort(list.begin(), list.end(),
[](const GLVolumeWithZ& v1, const GLVolumeWithZ& v2) -> bool { return v1.second < v2.second; }
);
}
return list;
}
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface) const
#else
void GLVolumeCollection::render_VBOs() const
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
{
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
::glCullFace(GL_BACK);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (disable_cullface)
::glDisable(GL_CULL_FACE);
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
@ -980,6 +1025,18 @@ void GLVolumeCollection::render_VBOs() const
if (z_range_id != -1)
::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type);
for (GLVolumeWithZ& volume : to_render)
{
if (volume.first->layer_height_texture_data.can_use())
volume.first->generate_layer_height_texture(volume.first->layer_height_texture_data.print_object, false);
else
volume.first->set_render_color();
volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
}
#else
for (GLVolume *volume : this->volumes)
{
if (volume->layer_height_texture_data.can_use())
@ -989,6 +1046,7 @@ void GLVolumeCollection::render_VBOs() const
volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
}
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
::glBindBuffer(GL_ARRAY_BUFFER, 0);
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@ -996,27 +1054,55 @@ void GLVolumeCollection::render_VBOs() const
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (disable_cullface)
::glEnable(GL_CULL_FACE);
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
::glDisable(GL_BLEND);
}
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const
#else
void GLVolumeCollection::render_legacy() const
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_BACK);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (disable_cullface)
::glDisable(GL_CULL_FACE);
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type);
for (GLVolumeWithZ& volume : to_render)
{
volume.first->set_render_color();
volume.first->render_legacy();
}
#else
for (GLVolume *volume : this->volumes)
{
volume->set_render_color();
volume->render_legacy();
}
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (disable_cullface)
::glEnable(GL_CULL_FACE);
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
glDisable(GL_BLEND);
}

View File

@ -500,6 +500,17 @@ typedef std::vector<GLVolume*> GLVolumePtrs;
class GLVolumeCollection
{
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
public:
enum ERenderType : unsigned char
{
Opaque,
Transparent,
All
};
private:
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// min and max vertex of the print box volume
float print_box_min[3];
float print_box_max[3];
@ -544,8 +555,13 @@ public:
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width);
// Render the volumes by OpenGL.
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
void render_VBOs(ERenderType type, bool disable_cullface) const;
void render_legacy(ERenderType type, bool disable_cullface) const;
#else
void render_VBOs() const;
void render_legacy() const;
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// Finalize the initialization of the geometry & indices,
// upload the geometry and indices to OpenGL VBO objects

View File

@ -4313,7 +4313,13 @@ void GLCanvas3D::render()
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_render_background();
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// textured bed needs to be rendered after objects if the texture is transparent
bool early_bed_render = is_custom_bed || (theta <= 90.0f);
if (early_bed_render)
#else
if (is_custom_bed) // untextured bed needs to be rendered before objects
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
_render_bed(theta);
_render_objects();
@ -4322,7 +4328,11 @@ void GLCanvas3D::render()
_render_axes();
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (!early_bed_render)
#else
if (!is_custom_bed) // textured bed needs to be rendered after objects
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
_render_bed(theta);
#if ENABLE_RENDER_SELECTION_CENTER
@ -6119,7 +6129,7 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co
// margin factor to give some empty space around the bbox
double margin_factor = 1.25;
for (const Vec3d v : vertices)
for (const Vec3d& v : vertices)
{
// project vertex on the plane perpendicular to camera forward axis
Vec3d pos(v(0) - bb_center(0), v(1) - bb_center(1), v(2) - bb_center(2));
@ -6328,8 +6338,10 @@ void GLCanvas3D::_render_objects() const
m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height"));
m_volumes.check_outside_state(m_config, nullptr);
}
#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// do not cull backfaces to show broken geometry, if any
::glDisable(GL_CULL_FACE);
#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
}
if (m_use_clipping_planes)
@ -6338,11 +6350,19 @@ void GLCanvas3D::_render_objects() const
m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
m_shader.start_using();
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// do not cull backfaces to show broken geometry, if any
m_volumes.render_VBOs(GLVolumeCollection::Opaque, m_picking_enabled);
m_volumes.render_VBOs(GLVolumeCollection::Transparent, false);
#else
m_volumes.render_VBOs();
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
m_shader.stop_using();
#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (m_picking_enabled)
::glEnable(GL_CULL_FACE);
#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
}
else
{
@ -6354,14 +6374,24 @@ void GLCanvas3D::_render_objects() const
::glEnable(GL_CLIP_PLANE1);
}
#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// do not cull backfaces to show broken geometry, if any
if (m_picking_enabled)
::glDisable(GL_CULL_FACE);
#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
// do not cull backfaces to show broken geometry, if any
m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled);
m_volumes.render_legacy(GLVolumeCollection::Transparent, false);
#else
m_volumes.render_legacy();
#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (m_picking_enabled)
::glEnable(GL_CULL_FACE);
#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING
if (m_use_clipping_planes)
{