Fix outline rendering

This commit is contained in:
Noisyfox 2023-10-26 15:06:46 +08:00
parent 71fd4084c2
commit 03daf61862
4 changed files with 65 additions and 249 deletions

View file

@ -396,216 +396,45 @@ void GLVolume::set_range(double min_z, double max_z)
} }
} }
//BBS: add outline related logic void GLVolume::render()
//static unsigned char stencil_data[1284][2944];
void GLVolume::render(bool with_outline)
{ {
if (!is_active) if (!is_active)
return; return;
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); GLShaderProgram *shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr) if (shader == nullptr)
return; return;
if (this->is_left_handed()) ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
glFrontFace(GL_CW);
glsafe(::glCullFace(GL_BACK));
if (with_outline) {
// Error: not supported!
throw Slic3r::InvalidArgument("Render GLVolume with outline is not supported");
}
// BBS: add logic for mmu segmentation rendering
auto render_body = [&]() {
bool color_volume = false;
ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects;
do {
if ((!printable) || object_idx() >= model_objects.size())
break;
ModelObject* mo = model_objects[object_idx()];
if (volume_idx() >= mo->volumes.size())
break;
ModelVolume* mv = mo->volumes[volume_idx()];
if (mv->mmu_segmentation_facets.empty())
break;
color_volume = true;
if (mv->mmu_segmentation_facets.timestamp() != mmuseg_ts) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, current mmuseg_ts %3%, current color size %4%")
%this %this->name %mmuseg_ts %mmuseg_models.size() ;
mmuseg_models.clear();
std::vector<indexed_triangle_set> its_per_color;
mv->mmu_segmentation_facets.get_facets(*mv, its_per_color);
mmuseg_models.resize(its_per_color.size());
for (int idx = 0; idx < its_per_color.size(); idx++) {
mmuseg_models[idx].init_from(its_per_color[idx]);
}
mmuseg_ts = mv->mmu_segmentation_facets.timestamp();
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, new mmuseg_ts %3%, new color size %4%")
%this %this->name %mmuseg_ts %mmuseg_models.size();
}
} while (0);
if (color_volume) {
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
std::vector<ColorRGBA> colors = get_extruders_colors(); std::vector<ColorRGBA> colors = get_extruders_colors();
//when force_transparent, we need to keep the alpha simple_render(shader, model_objects, colors);
if (force_native_color && (render_color.is_transparent())) { }
for (int index = 0; index < colors.size(); index++)
colors[index].a(render_color.a());
}
for (int idx = 0; idx < mmuseg_models.size(); idx++) {
GUI::GLModel &m = mmuseg_models[idx];
if (m.is_empty())
continue;
if (shader) { //BBS: add outline related logic
if (idx == 0) { void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
ModelObject* mo = model_objects[object_idx()]; {
ModelVolume* mv = mo->volumes[volume_idx()]; if (!is_active)
int extruder_id = mv->extruder_id(); return;
//shader->set_uniform("uniform_color", colors[extruder_id - 1]);
//to make black not too hard too see GLShaderProgram *shader = GUI::wxGetApp().get_current_shader();
ColorRGBA new_color = adjust_color_for_rendering(colors[extruder_id - 1]); if (shader == nullptr)
m.set_color(new_color); return;
}
else { ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
if (idx <= colors.size()) { std::vector<ColorRGBA> colors = get_extruders_colors();
//shader->set_uniform("uniform_color", colors[idx - 1]);
//to make black not too hard too see
ColorRGBA new_color = adjust_color_for_rendering(colors[idx - 1]);
m.set_color(new_color);
}
else {
//shader->set_uniform("uniform_color", colors[0]);
//to make black not too hard too see
ColorRGBA new_color = adjust_color_for_rendering(colors[0]);
m.set_color(new_color);
}
}
}
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
m.render();
else
m.render(this->tverts_range);
/*if (force_native_color && (render_color[3] < 1.0)) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}")
%this %this->name %this->tverts_range.first %this->tverts_range.second
% this->qverts_range.first % this->qverts_range.second;
}*/
}
}
else {
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
model.render();
else
model.render(this->tverts_range);
}
};
//BBS: add logic of outline rendering
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader;
if (with_outline && shader != nullptr)
{
do
{
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilMask(0xFF); glStencilMask(0xFF);
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 0xff, 0xFF); glStencilFunc(GL_ALWAYS, 0xff, 0xFF);
//another way use depth buffer
//glsafe(::glEnable(GL_DEPTH_TEST));
//glsafe(::glDepthFunc(GL_ALWAYS));
//glsafe(::glDepthMask(GL_FALSE));
//glsafe(::glEnable(GL_BLEND));
//glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
/*GLShaderProgram* outline_shader = GUI::wxGetApp().get_shader("outline"); simple_render(shader, model_objects, colors);
if (outline_shader == nullptr)
{
glDisable(GL_STENCIL_TEST);
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
break;
}
shader->stop_using();
outline_shader->start_using();
//float scale_ratio = 1.02f;
ColorRGBA outline_color = { 0.0f, 1.0f, 0.0f, 1.0f };
outline_shader->set_uniform("uniform_color", outline_color);*/
#if 0 //dump stencil buffer
int i = 100, j = 100;
std::string file_name;
FILE* file = NULL;
memset(stencil_data, 0, sizeof(stencil_data));
glReadPixels(0, 0, 2936, 1083, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencil_data);
for (i = 100; i < 1083; i++)
{
for (j = 100; j < 2936; j++)
{
if (stencil_data[i][j] != 0)
{
file_name = "before_stencil_index_" + std::to_string(i) + "x" + std::to_string(j) + ".a8";
break;
}
}
if (stencil_data[i][j] != 0)
break;
}
file = fopen(file_name.c_str(), "w");
if (file)
{
fwrite(stencil_data, 2936 * 1083, 1, file);
fclose(file);
}
#endif
render_body();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render body, shader name %2%")%__LINE__ %shader->get_name();
#if 0 //dump stencil buffer after first rendering
memset(stencil_data, 0, sizeof(stencil_data));
glReadPixels(0, 0, 2936, 1083, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencil_data);
for (i = 100; i < 1083; i++)
{
for (j = 100; j < 2936; j++)
if (stencil_data[i][j] != 0)
{
file_name = "after_stencil_index_" + std::to_string(i) + "x" + std::to_string(j) + ".a8";
break;
}
if (stencil_data[i][j] != 0)
break;
}
file = fopen(file_name.c_str(), "w");
if (file)
{
fwrite(stencil_data, 2936 * 1083, 1, file);
fclose(file);
}
#endif
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing. // 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing // Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
// the objects' size differences, making it look like borders. // the objects' size differences, making it look like borders.
// -----------------------------------------------------------------------------------------------------------------------------
/*GLShaderProgram* outline_shader = GUI::wxGetApp().get_shader("outline");
if (outline_shader == nullptr)
{
glDisable(GL_STENCIL_TEST);
break;
}
shader->stop_using();
outline_shader->start_using();*/
//outline_shader->stop_using();
//shader->start_using();
glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF); glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF);
glStencilMask(0x00); glStencilMask(0x00);
float scale = 1.02f; float scale = 1.02f;
@ -613,33 +442,19 @@ void GLVolume::render(bool with_outline)
model.set_color(body_color); model.set_color(body_color);
shader->set_uniform("is_outline", true); shader->set_uniform("is_outline", true);
glsafe(::glPopMatrix());
glsafe(::glPushMatrix());
Transform3d matrix = world_matrix(); Transform3d matrix = view_model_matrix;
matrix.scale(scale); matrix.scale(scale);
glsafe(::glMultMatrixd(matrix.data())); shader->set_uniform("view_model_matrix", matrix);
if (tverts_range == std::make_pair<size_t, size_t>(0, -1)) if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
model.render(); model.render();
else else
model.render(this->tverts_range); model.render(this->tverts_range);
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name();
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("is_outline", false); shader->set_uniform("is_outline", false);
//glStencilMask(0xFF);
//glStencilFunc(GL_ALWAYS, 0, 0xFF);
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
//glEnable(GL_DEPTH_TEST);
//outline_shader->stop_using();
//shader->start_using();
} while (0);
}
else {
render_body();
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__;
}
if (this->is_left_handed())
glFrontFace(GL_CCW);
} }
//BBS add render for simple case //BBS add render for simple case
@ -684,7 +499,6 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj
if (m.is_empty()) if (m.is_empty())
continue; continue;
if (shader) {
if (idx == 0) { if (idx == 0) {
int extruder_id = model_volume->extruder_id(); int extruder_id = model_volume->extruder_id();
//to make black not too hard too see //to make black not too hard too see
@ -693,19 +507,16 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj
} }
else { else {
if (idx <= extruder_colors.size()) { if (idx <= extruder_colors.size()) {
//shader->set_uniform("uniform_color", extruder_colors[idx - 1]);
//to make black not too hard too see //to make black not too hard too see
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[idx - 1]); ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[idx - 1]);
m.set_color(new_color); m.set_color(new_color);
} }
else { else {
//shader->set_uniform("uniform_color", extruder_colors[0]);
//to make black not too hard too see //to make black not too hard too see
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[0]); ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[0]);
m.set_color(new_color); m.set_color(new_color);
} }
} }
}
if (tverts_range == std::make_pair<size_t, size_t>(0, -1)) if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
m.render(); m.render();
else else
@ -748,7 +559,7 @@ GLWipeTowerVolume::GLWipeTowerVolume(const std::vector<ColorRGBA>& colors)
m_colors = colors; m_colors = colors;
} }
void GLWipeTowerVolume::render(bool with_outline) void GLWipeTowerVolume::render()
{ {
if (!is_active) if (!is_active)
return; return;
@ -1102,7 +913,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
shader->set_uniform("projection_matrix", projection_matrix); shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
//BBS: add outline related logic //BBS: add outline related logic
volume.first->render(with_outline && volume.first->selected); if (with_outline && volume.first->selected)
volume.first->render_with_outline(matrix);
else
volume.first->render();
#if ENABLE_ENVIRONMENT_MAP #if ENABLE_ENVIRONMENT_MAP
if (use_environment_texture) if (use_environment_texture)

View file

@ -312,8 +312,10 @@ public:
void set_range(double low, double high); void set_range(double low, double high);
virtual void render();
//BBS: add outline related logic and add virtual specifier //BBS: add outline related logic and add virtual specifier
virtual void render(bool with_outline = false); void render_with_outline(const Transform3d &view_model_matrix);
//BBS: add simple render function for thumbnail //BBS: add simple render function for thumbnail
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors); void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors);
@ -345,7 +347,7 @@ public:
class GLWipeTowerVolume : public GLVolume { class GLWipeTowerVolume : public GLVolume {
public: public:
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors); GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
virtual void render(bool with_outline = false); void render() override;
std::vector<GUI::GLModel> model_per_colors; std::vector<GUI::GLModel> model_per_colors;
bool IsTransparent(); bool IsTransparent();

View file

@ -5608,7 +5608,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
shader->set_uniform("view_model_matrix", matrix); shader->set_uniform("view_model_matrix", matrix);
shader->set_uniform("projection_matrix", projection_matrix); shader->set_uniform("projection_matrix", projection_matrix);
shader->set_uniform("normal_matrix", (Matrix3d) matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); shader->set_uniform("normal_matrix", (Matrix3d) matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
vol->simple_render(nullptr, model_objects, extruder_colors); vol->simple_render(shader, model_objects, extruder_colors);
vol->is_active = is_active; vol->is_active = is_active;
} }

View file

@ -116,8 +116,8 @@ void GLGizmoFdmSupports::render_painter_gizmo()
//BBS: draw support volumes //BBS: draw support volumes
if (m_volume_ready && m_support_volume && (m_edit_state != state_generating)) if (m_volume_ready && m_support_volume && (m_edit_state != state_generating))
{ {
//m_support_volume->set_render_color(); // TODO: FIXME
::glColor4f(0.f, 0.7f, 0.f, 0.7f); m_support_volume->set_render_color({0.f, 0.7f, 0.f, 0.7f});
m_support_volume->render(); m_support_volume->render();
} }