diff --git a/src/libvgcode/src/Shaders.hpp b/src/libvgcode/src/Shaders.hpp index 596b42df5c..9f546d6dc8 100644 --- a/src/libvgcode/src/Shaders.hpp +++ b/src/libvgcode/src/Shaders.hpp @@ -34,6 +34,10 @@ static const char* Segments_Vertex_Shader = // ORCA: 0 during the shadow caster pass - the bias below shifts eye_position but not // world_position, so the caster would write a depth the receiver never looks up. "uniform float bias_scale;\n" +// draw the instances last to first, top layers before the ones they hide, so that early depth +// rejection discards most of the hidden fragments; set when the camera looks down on the print +"uniform int reverse_order;\n" +"uniform int instance_count;\n" "in int vertex_id;\n" "out vec3 color;\n" "// ORCA: realistic view - the light the shadow map is able to block, kept apart from the\n" @@ -59,7 +63,8 @@ static const char* Segments_Vertex_Shader = " return top_diffuse + front_diffuse + top_specular;\n" "}\n" "void main() {\n" -" int id_a = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n" +" int instance = (reverse_order != 0) ? instance_count - 1 - gl_InstanceID : gl_InstanceID;\n" +" int id_a = int(texelFetch(segment_index_tex, instance).r);\n" " int id_b = id_a + 1;\n" " vec3 pos_a = texelFetch(position_tex, id_a).xyz;\n" " vec3 pos_b = texelFetch(position_tex, id_b).xyz;\n" diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index b1a7550b42..8212717931 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -763,6 +763,8 @@ void ViewerImpl::init(const std::string& opengl_context_version) m_uni_segments_height_width_angle_tex_id = glGetUniformLocation(m_segments_shader_id, "height_width_angle_tex"); m_uni_segments_colors_tex_id = glGetUniformLocation(m_segments_shader_id, "color_tex"); m_uni_segments_segment_index_tex_id = glGetUniformLocation(m_segments_shader_id, "segment_index_tex"); + m_uni_segments_reverse_order_id = glGetUniformLocation(m_segments_shader_id, "reverse_order"); + m_uni_segments_instance_count_id = glGetUniformLocation(m_segments_shader_id, "instance_count"); // ORCA: realistic view m_uni_segments_shadow_map_id = glGetUniformLocation(m_segments_shader_id, "shadow_map"); m_uni_segments_shadow_light_vp_id = glGetUniformLocation(m_segments_shader_id, "shadow_light_vp"); @@ -2090,6 +2092,15 @@ void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projec glsafe(glUniformMatrix4fv(m_uni_segments_view_matrix_id, 1, GL_FALSE, view_matrix.data())); glsafe(glUniformMatrix4fv(m_uni_segments_projection_matrix_id, 1, GL_FALSE, projection_matrix.data())); glsafe(glUniform3fv(m_uni_segments_camera_position_id, 1, camera_position.data())); + // The segments come in print order, bottom layer first. Seen from above, that is back to front, + // and every hidden fragment is shaded before the one that covers it. Drawing them last to first + // lets the depth test reject the hidden ones instead. The camera looks down when the world's + // up axis points towards it, which is the view matrix's (2, 2) entry being positive. + const bool top_down = !m_rendering_shadow_casters && view_matrix[10] > 0.0f; + glsafe(glUniform1i(m_uni_segments_reverse_order_id, top_down ? 1 : 0)); +#ifndef ENABLE_OPENGL_ES + glsafe(glUniform1i(m_uni_segments_instance_count_id, static_cast(m_enabled_segments_count))); +#endif // ENABLE_OPENGL_ES // ORCA: realistic view. The depth pass writes the map it would otherwise read, so it shades // with the lookup off. glsafe(glUniform1i(m_uni_segments_shadow_map_id, m_shadow_map_texture_unit)); diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index c9d658beb1..707f0f6bb7 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -362,6 +362,8 @@ private: int m_uni_segments_height_width_angle_tex_id{ -1 }; int m_uni_segments_colors_tex_id{ -1 }; int m_uni_segments_segment_index_tex_id{ -1 }; + int m_uni_segments_reverse_order_id{ -1 }; + int m_uni_segments_instance_count_id{ -1 }; int m_uni_segments_shadow_map_id{ -1 }; int m_uni_segments_shadow_light_vp_id{ -1 }; int m_uni_segments_shadow_intensity_id{ -1 };