diff --git a/resources/shaders/gouraud_light_instanced_attr.vs b/resources/shaders/gouraud_light_instanced_attr.vs new file mode 100644 index 0000000000..7069feb65e --- /dev/null +++ b/resources/shaders/gouraud_light_instanced_attr.vs @@ -0,0 +1,50 @@ +#version 110 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +// vertex attributes +attribute vec3 v_position; +attribute vec3 v_normal; +// instance attributes +attribute vec3 i_offset; +attribute vec2 i_scales; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 eye_normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0); + vec4 eye_position = view_model_matrix * world_position; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_Position = projection_matrix * eye_position; +} diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index e51b9526c4..abbde51c86 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -676,7 +676,11 @@ void GCodeViewer::init() #if !DISABLE_GCODEVIEWER_INSTANCED_MODELS if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; +#if ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES + buffer.shader = "gouraud_light_instanced_attr"; +#else buffer.shader = "gouraud_light_instanced"; +#endif // ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES buffer.model.model.init_from(diamond(16)); buffer.model.color = option_color(type); buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; @@ -3158,7 +3162,6 @@ void GCodeViewer::render_toolpaths() int normal_id = -1; const bool use_attributes = boost::algorithm::iends_with(shader->get_name(), "_attr"); if (use_attributes) { - const Camera& camera = wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); shader->set_uniform("view_model_matrix", view_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index c32a4e26ac..13606cb655 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -1083,7 +1083,11 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance GLShaderProgram* shader = wxGetApp().get_current_shader(); #if ENABLE_GLBEGIN_GLEND_REMOVAL +#if ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES + if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced_attr")) +#else if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced")) +#endif // ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES return; // vertex attributes diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index eda9097202..b35670d277 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -56,8 +56,12 @@ std::pair GLShadersManager::init() // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview - if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); +#if ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES + valid &= append_shader("gouraud_light_instanced_attr", { "gouraud_light_instanced_attr.vs", "gouraud_light_instanced.fs" }); +#endif // ENABLE_GLBEGIN_GLEND_SHADERS_ATTRIBUTES + } // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor