mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-09 07:56:24 -06:00
Fix outline rendering
This commit is contained in:
parent
71fd4084c2
commit
03daf61862
4 changed files with 65 additions and 249 deletions
|
@ -396,250 +396,65 @@ 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);
|
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||||
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
|
simple_render(shader, model_objects, colors);
|
||||||
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()];
|
//BBS: add outline related logic
|
||||||
if (volume_idx() >= mo->volumes.size())
|
void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
|
||||||
break;
|
{
|
||||||
|
if (!is_active)
|
||||||
|
return;
|
||||||
|
|
||||||
ModelVolume* mv = mo->volumes[volume_idx()];
|
GLShaderProgram *shader = GUI::wxGetApp().get_current_shader();
|
||||||
if (mv->mmu_segmentation_facets.empty())
|
if (shader == nullptr)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
color_volume = true;
|
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
||||||
if (mv->mmu_segmentation_facets.timestamp() != mmuseg_ts) {
|
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||||
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();
|
glEnable(GL_STENCIL_TEST);
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, new mmuseg_ts %3%, new color size %4%")
|
glStencilMask(0xFF);
|
||||||
%this %this->name %mmuseg_ts %mmuseg_models.size();
|
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
|
||||||
}
|
glClear(GL_STENCIL_BUFFER_BIT);
|
||||||
} while (0);
|
glStencilFunc(GL_ALWAYS, 0xff, 0xFF);
|
||||||
|
|
||||||
if (color_volume) {
|
simple_render(shader, model_objects, colors);
|
||||||
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
|
|
||||||
std::vector<ColorRGBA> colors = get_extruders_colors();
|
|
||||||
|
|
||||||
//when force_transparent, we need to keep the alpha
|
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
||||||
if (force_native_color && (render_color.is_transparent())) {
|
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
|
||||||
for (int index = 0; index < colors.size(); index++)
|
// the objects' size differences, making it look like borders.
|
||||||
colors[index].a(render_color.a());
|
glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF);
|
||||||
}
|
glStencilMask(0x00);
|
||||||
for (int idx = 0; idx < mmuseg_models.size(); idx++) {
|
float scale = 1.02f;
|
||||||
GUI::GLModel &m = mmuseg_models[idx];
|
ColorRGBA body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
|
||||||
if (m.is_empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (shader) {
|
model.set_color(body_color);
|
||||||
if (idx == 0) {
|
shader->set_uniform("is_outline", true);
|
||||||
ModelObject* mo = model_objects[object_idx()];
|
|
||||||
ModelVolume* mv = mo->volumes[volume_idx()];
|
|
||||||
int extruder_id = mv->extruder_id();
|
|
||||||
//shader->set_uniform("uniform_color", colors[extruder_id - 1]);
|
|
||||||
//to make black not too hard too see
|
|
||||||
ColorRGBA new_color = adjust_color_for_rendering(colors[extruder_id - 1]);
|
|
||||||
m.set_color(new_color);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (idx <= colors.size()) {
|
|
||||||
//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
|
Transform3d matrix = view_model_matrix;
|
||||||
//BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader;
|
matrix.scale(scale);
|
||||||
if (with_outline && shader != nullptr)
|
shader->set_uniform("view_model_matrix", matrix);
|
||||||
{
|
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
||||||
do
|
model.render();
|
||||||
{
|
else
|
||||||
glEnable(GL_STENCIL_TEST);
|
model.render(this->tverts_range);
|
||||||
glStencilMask(0xFF);
|
|
||||||
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
|
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
|
||||||
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");
|
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||||
if (outline_shader == nullptr)
|
shader->set_uniform("is_outline", false);
|
||||||
{
|
|
||||||
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);*/
|
glDisable(GL_STENCIL_TEST);
|
||||||
#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.
|
|
||||||
// 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.
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------------------
|
|
||||||
/*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);
|
|
||||||
glStencilMask(0x00);
|
|
||||||
float scale = 1.02f;
|
|
||||||
ColorRGBA body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
|
|
||||||
|
|
||||||
model.set_color(body_color);
|
|
||||||
shader->set_uniform("is_outline", true);
|
|
||||||
glsafe(::glPopMatrix());
|
|
||||||
glsafe(::glPushMatrix());
|
|
||||||
|
|
||||||
Transform3d matrix = world_matrix();
|
|
||||||
matrix.scale(scale);
|
|
||||||
glsafe(::glMultMatrixd(matrix.data()));
|
|
||||||
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
|
|
||||||
model.render();
|
|
||||||
else
|
|
||||||
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("is_outline", false);
|
|
||||||
|
|
||||||
//glStencilMask(0xFF);
|
|
||||||
//glStencilFunc(GL_ALWAYS, 0, 0xFF);
|
|
||||||
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,26 +499,22 @@ 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
|
||||||
|
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[extruder_id - 1]);
|
||||||
|
m.set_color(new_color);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (idx <= extruder_colors.size()) {
|
||||||
//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[extruder_id - 1]);
|
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[idx - 1]);
|
||||||
m.set_color(new_color);
|
m.set_color(new_color);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (idx <= extruder_colors.size()) {
|
//to make black not too hard too see
|
||||||
//shader->set_uniform("uniform_color", extruder_colors[idx - 1]);
|
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[0]);
|
||||||
//to make black not too hard too see
|
m.set_color(new_color);
|
||||||
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[idx - 1]);
|
|
||||||
m.set_color(new_color);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//shader->set_uniform("uniform_color", extruder_colors[0]);
|
|
||||||
//to make black not too hard too see
|
|
||||||
ColorRGBA new_color = adjust_color_for_rendering(extruder_colors[0]);
|
|
||||||
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))
|
||||||
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue