Use a 2-pass depth based outline algorithm when selected
This commit is contained in:
parent
2acd858bf3
commit
13e18d1d65
7 changed files with 262 additions and 46 deletions
|
@ -36,6 +36,9 @@ uniform SlopeDetection slope;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
uniform bool is_outline;
|
uniform bool is_outline;
|
||||||
|
uniform sampler2D depth_tex;
|
||||||
|
uniform vec2 screen_size;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
uniform sampler2D environment_tex;
|
uniform sampler2D environment_tex;
|
||||||
|
@ -44,6 +47,9 @@ uniform bool is_outline;
|
||||||
|
|
||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
|
uniform float z_far;
|
||||||
|
uniform float z_near;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
varying float color_clip_plane_dot;
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
|
@ -54,6 +60,71 @@ varying vec4 world_pos;
|
||||||
varying float world_normal_z;
|
varying float world_normal_z;
|
||||||
varying vec3 eye_normal;
|
varying vec3 eye_normal;
|
||||||
|
|
||||||
|
vec3 getBackfaceColor(vec3 fill) {
|
||||||
|
float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b;
|
||||||
|
return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Silhouette edge detection & rendering algorithem by leoneruggiero
|
||||||
|
// https://www.shadertoy.com/view/DslXz2
|
||||||
|
#define INFLATE 1
|
||||||
|
|
||||||
|
float GetTolerance(float d, float k)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// Find a tolerance for depth that is constant
|
||||||
|
// in view space (k in view space).
|
||||||
|
//
|
||||||
|
// tol = k*ddx(ZtoDepth(z))
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float A=- (z_far+z_near)/(z_far-z_near);
|
||||||
|
float B=-2.0*z_far*z_near /(z_far-z_near);
|
||||||
|
|
||||||
|
d = d*2.0-1.0;
|
||||||
|
|
||||||
|
return -k*(d+A)*(d+A)/B;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(ivec2 fragCoord, ivec2 dir)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// x0 ___ x1----o
|
||||||
|
// :\ :
|
||||||
|
// r0 : \ : r1
|
||||||
|
// : \ :
|
||||||
|
// o---x2 ___ x3
|
||||||
|
//
|
||||||
|
// r0 and r1 are the differences between actual
|
||||||
|
// and expected (as if x0..3 where on the same
|
||||||
|
// plane) depth values.
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float x0 = abs(texelFetch(depth_tex, (fragCoord + dir*-2), 0).r);
|
||||||
|
float x1 = abs(texelFetch(depth_tex, (fragCoord + dir*-1), 0).r);
|
||||||
|
float x2 = abs(texelFetch(depth_tex, (fragCoord + dir* 0), 0).r);
|
||||||
|
float x3 = abs(texelFetch(depth_tex, (fragCoord + dir* 1), 0).r);
|
||||||
|
|
||||||
|
float d0 = (x1-x0);
|
||||||
|
float d1 = (x2-x3);
|
||||||
|
|
||||||
|
float r0 = x1 + d0 - x2;
|
||||||
|
float r1 = x2 + d1 - x1;
|
||||||
|
|
||||||
|
float tol = GetTolerance(x2, 0.04);
|
||||||
|
|
||||||
|
return smoothstep(0.0, tol*tol, max( - r0*r1, 0.0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(ivec2 fragCoord)
|
||||||
|
{
|
||||||
|
return max(
|
||||||
|
DetectSilho(fragCoord, ivec2(1,0)), // Horizontal
|
||||||
|
DetectSilho(fragCoord, ivec2(0,1)) // Vertical
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
|
@ -94,10 +165,20 @@ void main()
|
||||||
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
||||||
}
|
}
|
||||||
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
if (is_outline)
|
if (is_outline) {
|
||||||
gl_FragColor = uniform_color;
|
color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
|
ivec2 fragCoord = ivec2(gl_FragCoord.xy);
|
||||||
|
float s = DetectSilho(fragCoord);
|
||||||
|
// Makes silhouettes thicker.
|
||||||
|
for(int i=1;i<=INFLATE; i++)
|
||||||
|
{
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + ivec2(i, 0)));
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + ivec2(0, i)));
|
||||||
|
}
|
||||||
|
gl_FragColor = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
|
||||||
|
}
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
else if (use_environment_tex)
|
else if (use_environment_tex)
|
||||||
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
|
|
|
@ -36,6 +36,8 @@ uniform SlopeDetection slope;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
uniform bool is_outline;
|
uniform bool is_outline;
|
||||||
|
uniform sampler2D depth_tex;
|
||||||
|
uniform vec2 screen_size;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
uniform sampler2D environment_tex;
|
uniform sampler2D environment_tex;
|
||||||
|
@ -44,6 +46,9 @@ uniform bool is_outline;
|
||||||
|
|
||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
|
uniform float z_far;
|
||||||
|
uniform float z_near;
|
||||||
|
|
||||||
in vec3 clipping_planes_dots;
|
in vec3 clipping_planes_dots;
|
||||||
in float color_clip_plane_dot;
|
in float color_clip_plane_dot;
|
||||||
|
|
||||||
|
@ -54,6 +59,71 @@ in vec4 world_pos;
|
||||||
in float world_normal_z;
|
in float world_normal_z;
|
||||||
in vec3 eye_normal;
|
in vec3 eye_normal;
|
||||||
|
|
||||||
|
vec3 getBackfaceColor(vec3 fill) {
|
||||||
|
float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b;
|
||||||
|
return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Silhouette edge detection & rendering algorithem by leoneruggiero
|
||||||
|
// https://www.shadertoy.com/view/DslXz2
|
||||||
|
#define INFLATE 1
|
||||||
|
|
||||||
|
float GetTolerance(float d, float k)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// Find a tolerance for depth that is constant
|
||||||
|
// in view space (k in view space).
|
||||||
|
//
|
||||||
|
// tol = k*ddx(ZtoDepth(z))
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float A=- (z_far+z_near)/(z_far-z_near);
|
||||||
|
float B=-2.0*z_far*z_near /(z_far-z_near);
|
||||||
|
|
||||||
|
d = d*2.0-1.0;
|
||||||
|
|
||||||
|
return -k*(d+A)*(d+A)/B;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(ivec2 fragCoord, ivec2 dir)
|
||||||
|
{
|
||||||
|
// -------------------------------------------
|
||||||
|
// x0 ___ x1----o
|
||||||
|
// :\ :
|
||||||
|
// r0 : \ : r1
|
||||||
|
// : \ :
|
||||||
|
// o---x2 ___ x3
|
||||||
|
//
|
||||||
|
// r0 and r1 are the differences between actual
|
||||||
|
// and expected (as if x0..3 where on the same
|
||||||
|
// plane) depth values.
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
float x0 = abs(texelFetch(depth_tex, (fragCoord + dir*-2), 0).r);
|
||||||
|
float x1 = abs(texelFetch(depth_tex, (fragCoord + dir*-1), 0).r);
|
||||||
|
float x2 = abs(texelFetch(depth_tex, (fragCoord + dir* 0), 0).r);
|
||||||
|
float x3 = abs(texelFetch(depth_tex, (fragCoord + dir* 1), 0).r);
|
||||||
|
|
||||||
|
float d0 = (x1-x0);
|
||||||
|
float d1 = (x2-x3);
|
||||||
|
|
||||||
|
float r0 = x1 + d0 - x2;
|
||||||
|
float r1 = x2 + d1 - x1;
|
||||||
|
|
||||||
|
float tol = GetTolerance(x2, 0.04);
|
||||||
|
|
||||||
|
return smoothstep(0.0, tol*tol, max( - r0*r1, 0.0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float DetectSilho(ivec2 fragCoord)
|
||||||
|
{
|
||||||
|
return max(
|
||||||
|
DetectSilho(fragCoord, ivec2(1,0)), // Horizontal
|
||||||
|
DetectSilho(fragCoord, ivec2(0,1)) // Vertical
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
out vec4 out_color;
|
out vec4 out_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
@ -96,10 +166,20 @@ void main()
|
||||||
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
||||||
}
|
}
|
||||||
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
//BBS: add outline_color
|
//BBS: add outline_color
|
||||||
if (is_outline)
|
if (is_outline) {
|
||||||
out_color = uniform_color;
|
color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
|
ivec2 fragCoord = ivec2(gl_FragCoord.xy);
|
||||||
|
float s = DetectSilho(fragCoord);
|
||||||
|
// Makes silhouettes thicker.
|
||||||
|
for(int i=1;i<=INFLATE; i++)
|
||||||
|
{
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + ivec2(i, 0)));
|
||||||
|
s = max(s, DetectSilho(fragCoord.xy + ivec2(0, i)));
|
||||||
|
}
|
||||||
|
out_color = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
|
||||||
|
}
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
else if (use_environment_tex)
|
else if (use_environment_tex)
|
||||||
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
|
|
|
@ -423,7 +423,7 @@ void GLVolume::render()
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: add outline related logic
|
//BBS: add outline related logic
|
||||||
void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
|
void GLVolume::render_with_outline(const GUI::Size& cnv_size)
|
||||||
{
|
{
|
||||||
if (!is_active)
|
if (!is_active)
|
||||||
return;
|
return;
|
||||||
|
@ -435,37 +435,80 @@ void GLVolume::render_with_outline(const Transform3d &view_model_matrix)
|
||||||
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
|
||||||
std::vector<ColorRGBA> colors = get_extruders_colors();
|
std::vector<ColorRGBA> colors = get_extruders_colors();
|
||||||
|
|
||||||
glEnable(GL_STENCIL_TEST);
|
const GUI::OpenGLManager::EFramebufferType framebuffers_type = GUI::OpenGLManager::get_framebuffers_type();
|
||||||
glStencilMask(0xFF);
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Unknown) {
|
||||||
glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
|
// No supported, degrade to normal rendering
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
simple_render(shader, model_objects, colors);
|
||||||
glStencilFunc(GL_ALWAYS, 0xff, 0xFF);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
simple_render(shader, model_objects, colors);
|
// 1st. render pass, render the model into a separate render target that has only depth buffer
|
||||||
|
GLuint depth_fbo = 0;
|
||||||
|
GLuint depth_tex = 0;
|
||||||
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
|
glsafe(::glGenFramebuffers(1, &depth_fbo));
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, depth_fbo));
|
||||||
|
|
||||||
// 2nd. render pass: now draw slightly scaled versions of the objects, this time disabling stencil writing.
|
glActiveTexture(GL_TEXTURE0);
|
||||||
// Because the stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are not drawn, thus only drawing
|
glsafe(::glGenTextures(1, &depth_tex));
|
||||||
// the objects' size differences, making it look like borders.
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF);
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
glStencilMask(0x00);
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
float scale = 1.02f;
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
ColorRGBA body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr));
|
||||||
|
|
||||||
model.set_color(body_color);
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0));
|
||||||
shader->set_uniform("is_outline", true);
|
} else {
|
||||||
|
glsafe(::glGenFramebuffersEXT(1, &depth_fbo));
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fbo));
|
||||||
|
|
||||||
Transform3d matrix = view_model_matrix;
|
glActiveTexture(GL_TEXTURE0);
|
||||||
matrix.scale(scale);
|
glsafe(::glGenTextures(1, &depth_tex));
|
||||||
shader->set_uniform("view_model_matrix", matrix);
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, cnv_size.get_width(), cnv_size.get_height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr));
|
||||||
|
|
||||||
|
glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_tex, 0));
|
||||||
|
}
|
||||||
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
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);
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
|
||||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
// 2nd. render pass, just a normal render with the depth buffer passed as a texture
|
||||||
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
|
} else if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Ext) {
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
}
|
||||||
|
shader->set_uniform("is_outline", true);
|
||||||
|
shader->set_uniform("screen_size", Vec2f{cnv_size.get_width(), cnv_size.get_height()});
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, depth_tex));
|
||||||
|
shader->set_uniform("depth_tex", 0);
|
||||||
|
simple_render(shader, model_objects, colors);
|
||||||
|
|
||||||
|
// Some clean up to do
|
||||||
|
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
shader->set_uniform("screen_size", 0);
|
||||||
shader->set_uniform("is_outline", false);
|
shader->set_uniform("is_outline", false);
|
||||||
|
if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Arb) {
|
||||||
glDisable(GL_STENCIL_TEST);
|
glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
|
if (depth_fbo != 0)
|
||||||
|
glsafe(::glDeleteFramebuffers(1, &depth_fbo));
|
||||||
|
} else if (framebuffers_type == GUI::OpenGLManager::EFramebufferType::Ext) {
|
||||||
|
glsafe(::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
if (depth_fbo != 0)
|
||||||
|
glsafe(::glDeleteFramebuffersEXT(1, &depth_fbo));
|
||||||
|
}
|
||||||
|
if (depth_tex != 0)
|
||||||
|
glsafe(::glDeleteTextures(1, &depth_tex));
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS add render for simple case
|
//BBS add render for simple case
|
||||||
|
@ -847,8 +890,8 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
|
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||||
std::function<bool(const GLVolume&)> filter_func, bool with_outline) const
|
std::function<bool(const GLVolume&)> filter_func) const
|
||||||
{
|
{
|
||||||
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
||||||
if (to_render.empty())
|
if (to_render.empty())
|
||||||
|
@ -953,9 +996,9 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
||||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||||
//BBS: add outline related logic
|
//BBS: add outline related logic
|
||||||
//if (with_outline && volume.first->selected)
|
if (volume.first->selected)
|
||||||
// volume.first->render_with_outline(view_matrix * model_matrix);
|
volume.first->render_with_outline(cnv_size);
|
||||||
//else
|
else
|
||||||
volume.first->render();
|
volume.first->render();
|
||||||
|
|
||||||
#if ENABLE_ENVIRONMENT_MAP
|
#if ENABLE_ENVIRONMENT_MAP
|
||||||
|
|
|
@ -39,6 +39,10 @@ extern Slic3r::ColorRGBA adjust_color_for_rendering(const Slic3r::C
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
class Size;
|
||||||
|
}
|
||||||
|
|
||||||
class SLAPrintObject;
|
class SLAPrintObject;
|
||||||
enum SLAPrintObjectStep : unsigned int;
|
enum SLAPrintObjectStep : unsigned int;
|
||||||
class BuildVolume;
|
class BuildVolume;
|
||||||
|
@ -322,7 +326,7 @@ public:
|
||||||
virtual void render();
|
virtual void render();
|
||||||
|
|
||||||
//BBS: add outline related logic and add virtual specifier
|
//BBS: add outline related logic and add virtual specifier
|
||||||
virtual void render_with_outline(const Transform3d &view_model_matrix);
|
virtual void render_with_outline(const GUI::Size& cnv_size);
|
||||||
|
|
||||||
//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, bool ban_light =false);
|
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<ColorRGBA>& extruder_colors, bool ban_light =false);
|
||||||
|
@ -355,7 +359,7 @@ class GLWipeTowerVolume : public GLVolume {
|
||||||
public:
|
public:
|
||||||
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
GLWipeTowerVolume(const std::vector<ColorRGBA>& colors);
|
||||||
void render() override;
|
void render() override;
|
||||||
void render_with_outline(const Transform3d &view_model_matrix) override { render(); }
|
void render_with_outline(const GUI::Size& cnv_size) override { render(); }
|
||||||
|
|
||||||
std::vector<GUI::GLModel> model_per_colors;
|
std::vector<GUI::GLModel> model_per_colors;
|
||||||
bool IsTransparent();
|
bool IsTransparent();
|
||||||
|
@ -465,8 +469,8 @@ public:
|
||||||
int get_selection_support_threshold_angle(bool&) const;
|
int get_selection_support_threshold_angle(bool&) const;
|
||||||
// Render the volumes by OpenGL.
|
// Render the volumes by OpenGL.
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix,
|
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
||||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(), bool with_outline = true) const;
|
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>()) const;
|
||||||
|
|
||||||
// Clear the geometry
|
// Clear the geometry
|
||||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||||
|
|
|
@ -1244,7 +1244,7 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
|
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
render_shells();
|
render_shells(canvas_width, canvas_height);
|
||||||
|
|
||||||
if (m_roles.empty())
|
if (m_roles.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -4023,7 +4023,7 @@ void GCodeViewer::render_toolpaths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::render_shells()
|
void GCodeViewer::render_shells(int canvas_width, int canvas_height)
|
||||||
{
|
{
|
||||||
//BBS: add shell previewing logic
|
//BBS: add shell previewing logic
|
||||||
if ((!m_shells.previewing && !m_shells.visible) || m_shells.volumes.empty())
|
if ((!m_shells.previewing && !m_shells.visible) || m_shells.volumes.empty())
|
||||||
|
@ -4039,7 +4039,9 @@ void GCodeViewer::render_shells()
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
shader->set_uniform("emission_factor", 0.1f);
|
shader->set_uniform("emission_factor", 0.1f);
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
shader->set_uniform("z_far", camera.get_far_z());
|
||||||
|
shader->set_uniform("z_near", camera.get_near_z());
|
||||||
|
m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, false, camera.get_view_matrix(), camera.get_projection_matrix(), {canvas_width, canvas_height});
|
||||||
shader->set_uniform("emission_factor", 0.0f);
|
shader->set_uniform("emission_factor", 0.0f);
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
|
||||||
|
|
|
@ -893,7 +893,7 @@ private:
|
||||||
//void load_shells(const Print& print);
|
//void load_shells(const Print& print);
|
||||||
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
|
||||||
void render_toolpaths();
|
void render_toolpaths();
|
||||||
void render_shells();
|
void render_shells(int canvas_width, int canvas_height);
|
||||||
|
|
||||||
//BBS: GUI refactor: add canvas size
|
//BBS: GUI refactor: add canvas size
|
||||||
void render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin);
|
void render_legend(float &legend_height, int canvas_width, int canvas_height, int right_margin);
|
||||||
|
|
|
@ -7228,6 +7228,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
if (shader != nullptr) {
|
if (shader != nullptr) {
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
|
|
||||||
|
const Size& cvn_size = get_canvas_size();
|
||||||
|
{
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
shader->set_uniform("z_far", camera.get_far_z());
|
||||||
|
shader->set_uniform("z_near", camera.get_near_z());
|
||||||
|
}
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -7239,7 +7245,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
|
if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
|
||||||
int object_id = m_layers_editing.last_object_id;
|
int object_id = m_layers_editing.last_object_id;
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [object_id](const GLVolume& volume) {
|
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [object_id](const GLVolume& volume) {
|
||||||
// Which volume to paint without the layer height profile shader?
|
// Which volume to paint without the layer height profile shader?
|
||||||
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
|
return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
|
||||||
});
|
});
|
||||||
|
@ -7255,14 +7261,14 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
//BBS:add assemble view related logic
|
//BBS:add assemble view related logic
|
||||||
// do not cull backfaces to show broken geometry, if any
|
// do not cull backfaces to show broken geometry, if any
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
m_volumes.render(type, m_picking_enabled, camera.get_view_matrix(), camera.get_projection_matrix(), [this, canvas_type](const GLVolume& volume) {
|
m_volumes.render(type, m_picking_enabled, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [this, canvas_type](const GLVolume& volume) {
|
||||||
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
||||||
return !volume.is_modifier && !volume.is_wipe_tower;
|
return !volume.is_modifier && !volume.is_wipe_tower;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
||||||
}
|
}
|
||||||
}, with_outline);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -7289,14 +7295,14 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
}*/
|
}*/
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
//BBS:add assemble view related logic
|
//BBS:add assemble view related logic
|
||||||
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), [this, canvas_type](const GLVolume& volume) {
|
m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [this, canvas_type](const GLVolume& volume) {
|
||||||
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
if (canvas_type == ECanvasType::CanvasAssembleView) {
|
||||||
return !volume.is_modifier;
|
return !volume.is_modifier;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, with_outline);
|
});
|
||||||
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
||||||
const GLGizmosManager& gm = get_gizmos_manager();
|
const GLGizmosManager& gm = get_gizmos_manager();
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
|
Loading…
Reference in a new issue