diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index f8e31eeb7f..fe19007e07 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1309,6 +1309,7 @@ sub Render { $self->draw_volumes; } elsif ($self->UseVBOs) { if ($self->enable_picking) { + $self->mark_volumes_for_layer_height; $self->volumes->set_print_box($self->bed_bounding_box->x_min, $self->bed_bounding_box->y_min, 0.0, $self->bed_bounding_box->x_max, $self->bed_bounding_box->y_max, $self->{config}->get('max_print_height')); } $self->{plain_shader}->enable if $self->{plain_shader}; @@ -1358,36 +1359,10 @@ sub draw_volumes { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative; foreach my $volume_idx (0..$#{$self->volumes}) { my $volume = $self->volumes->[$volume_idx]; - my $shader_active = 0; - my $object_id = int($volume->select_group_id / 1000000); - if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{layer_height_edit_shader} && - $volume->has_layer_height_texture && $object_id < $self->{print}->object_count) { - # Update the height texture if the ModelObject::layer_height_texture is invalid. - $volume->generate_layer_height_texture($self->{print}->get_object($object_id), 0); - $self->{layer_height_edit_shader}->enable; - $self->{layer_height_edit_shader}->set_uniform('z_to_texture_row', $volume->layer_height_texture_z_to_row_id); - $self->{layer_height_edit_shader}->set_uniform('z_texture_row_to_normalized', 1. / $volume->layer_height_texture_height); - $self->{layer_height_edit_shader}->set_uniform('z_cursor', $volume->bounding_box->z_max * $z_cursor_relative); - $self->{layer_height_edit_shader}->set_uniform('z_cursor_band_width', $self->{layer_height_edit_band_width}); - glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_z_texture_id}); -# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LEVEL, 0); -# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1); - glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $volume->layer_height_texture_width, $volume->layer_height_texture_height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D_c(GL_TEXTURE_2D, 1, GL_RGBA8, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); -# glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -# glPixelStorei(GL_UNPACK_ROW_LENGTH, $self->{layer_preview_z_texture_width}); - glTexSubImage2D_c(GL_TEXTURE_2D, 0, 0, 0, $volume->layer_height_texture_width, $volume->layer_height_texture_height, - GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level0); - glTexSubImage2D_c(GL_TEXTURE_2D, 1, 0, 0, $volume->layer_height_texture_width / 2, $volume->layer_height_texture_height / 2, - GL_RGBA, GL_UNSIGNED_BYTE, $volume->layer_height_texture_data_ptr_level1); - $shader_active = 1; - } elsif ($fakecolor) { + if ($fakecolor) { # Object picking mode. Render the object with a color encoding the object index. my $r = ($volume_idx & 0x000000FF) >> 0; my $g = ($volume_idx & 0x0000FF00) >> 8; @@ -1402,11 +1377,6 @@ sub draw_volumes { } $volume->render; - - if ($shader_active) { - glBindTexture(GL_TEXTURE_2D, 0); - $self->{layer_height_edit_shader}->disable; - } } glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_BLEND); @@ -1421,6 +1391,22 @@ sub draw_volumes { glDisableClientState(GL_VERTEX_ARRAY); } +sub mark_volumes_for_layer_height { + my ($self) = @_; + + foreach my $volume_idx (0..$#{$self->volumes}) { + my $volume = $self->volumes->[$volume_idx]; + my $object_id = int($volume->select_group_id / 1000000); + if ($self->layer_editing_enabled && $volume->selected && $self->{layer_height_edit_shader} && + $volume->has_layer_height_texture && $object_id < $self->{print}->object_count) { + $volume->set_layer_height_texture_data($self->{layer_preview_z_texture_id}, $self->{layer_height_edit_shader}->shader_program_id, + $self->{print}->get_object($object_id), $self->_variable_layer_thickness_bar_mouse_cursor_z_relative, $self->{layer_height_edit_band_width}); + } else { + $volume->reset_layer_height_texture_data(); + } + } +} + sub _load_image_set_texture { my ($self, $file_name) = @_; # Load a PNG with an alpha channel. diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index e49314013f..0824e6cd07 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -281,6 +281,51 @@ void GLVolume::render() const glPopMatrix(); } +void GLVolume::render_using_layer_height() const +{ + if (!is_active) + return; + + GLint current_program_id; + glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + + if ((layer_height_texture_data.shader_id > 0) && (layer_height_texture_data.shader_id != current_program_id)) + glUseProgram(layer_height_texture_data.shader_id); + + GLint z_to_texture_row_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_to_texture_row") : -1; + GLint z_texture_row_to_normalized_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_texture_row_to_normalized") : -1; + GLint z_cursor_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor") : -1; + GLint z_cursor_band_width_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor_band_width") : -1; + + if (z_to_texture_row_id >= 0) + glUniform1f(z_to_texture_row_id, (GLfloat)layer_height_texture_z_to_row_id()); + + if (z_texture_row_to_normalized_id >= 0) + glUniform1f(z_texture_row_to_normalized_id, (GLfloat)(1.0f / layer_height_texture_height())); + + if (z_cursor_id >= 0) + glUniform1f(z_cursor_id, (GLfloat)(bounding_box.max.z * layer_height_texture_data.z_cursor_relative)); + + if (z_cursor_band_width_id >= 0) + glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width); + + unsigned int w = layer_height_texture_width(); + unsigned int h = layer_height_texture_height(); + + glBindTexture(GL_TEXTURE_2D, layer_height_texture_data.texture_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w / 2, h / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level0()); + glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, w / 2, h / 2, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level1()); + + render(); + + glBindTexture(GL_TEXTURE_2D, 0); + + if ((current_program_id > 0) && (layer_height_texture_data.shader_id != current_program_id)) + glUseProgram(current_program_id); +} + void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force) { GLTexture *tex = this->layer_height_texture.get(); @@ -398,15 +443,15 @@ int GLVolumeCollection::load_wipe_tower_preview( void GLVolumeCollection::render_VBOs() const { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + ::glEnable(GL_BLEND); + ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glCullFace(GL_BACK); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + ::glCullFace(GL_BACK); + ::glEnableClientState(GL_VERTEX_ARRAY); + ::glEnableClientState(GL_NORMAL_ARRAY); GLint current_program_id; - glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1; GLint print_box_max_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.max") : -1; @@ -419,6 +464,17 @@ void GLVolumeCollection::render_VBOs() const if (!volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id) continue; + if (volume->layer_height_texture_data.can_use()) + { + ::glDisableClientState(GL_VERTEX_ARRAY); + ::glDisableClientState(GL_NORMAL_ARRAY); + volume->generate_layer_height_texture(volume->layer_height_texture_data.print_object, false); + volume->render_using_layer_height(); + ::glEnableClientState(GL_VERTEX_ARRAY); + ::glEnableClientState(GL_NORMAL_ARRAY); + continue; + } + volume->set_render_color(); GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first)); @@ -458,9 +514,9 @@ void GLVolumeCollection::render_VBOs() const } if (color_id >= 0) - glUniform4fv(color_id, 1, (const GLfloat*)volume->render_color); + ::glUniform4fv(color_id, 1, (const GLfloat*)volume->render_color); else - glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]); + ::glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]); if (print_box_min_id != -1) ::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min); @@ -474,36 +530,36 @@ void GLVolumeCollection::render_VBOs() const ::glUniform4fv(print_box_origin_id, 1, (const GLfloat*)origin); } - glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); - glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); - glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); + ::glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); + ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); + ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr); bool has_offset = (volume->origin.x != 0) || (volume->origin.y != 0) || (volume->origin.z != 0); if (has_offset) { - glPushMatrix(); - glTranslated(volume->origin.x, volume->origin.y, volume->origin.z); + ::glPushMatrix(); + ::glTranslated(volume->origin.x, volume->origin.y, volume->origin.z); } if (n_triangles > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id); - glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(volume->tverts_range.first * 4)); + ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id); + ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(volume->tverts_range.first * 4)); } if (n_quads > 0) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id); - glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(volume->qverts_range.first * 4)); + ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id); + ::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(volume->qverts_range.first * 4)); } if (has_offset) - glPopMatrix(); + ::glPopMatrix(); } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + ::glBindBuffer(GL_ARRAY_BUFFER, 0); + ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + ::glDisableClientState(GL_VERTEX_ARRAY); + ::glDisableClientState(GL_NORMAL_ARRAY); - glDisable(GL_BLEND); + ::glDisable(GL_BLEND); } void GLVolumeCollection::render_legacy() const diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index e1e711bfe5..0fd31d8d69 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -210,6 +210,32 @@ public: }; class GLVolume { + struct LayerHeightTextureData + { + // ID of the layer height texture + unsigned int texture_id; + // ID of the shader used to render with the layer height texture + unsigned int shader_id; + // The print object to update when generating the layer height texture + PrintObject* print_object; + + float z_cursor_relative; + float edit_band_width; + + LayerHeightTextureData() { reset(); } + + void reset() + { + texture_id = 0; + shader_id = 0; + print_object = nullptr; + z_cursor_relative = 0.0f; + edit_band_width = 0.0f; + } + + bool can_use() { return (texture_id > 0) && (shader_id > 0) && (print_object != nullptr); } + }; + public: static const float SELECTED_COLOR[4]; static const float HOVER_COLOR[4]; @@ -301,11 +327,14 @@ public: void set_range(coordf_t low, coordf_t high); void render() const; + void render_using_layer_height() const; void finalize_geometry(bool use_VBOs) { this->indexed_vertex_array.finalize_geometry(use_VBOs); } void release_geometry() { this->indexed_vertex_array.release_geometry(); } /************************************************ Layer height texture ****************************************************/ std::shared_ptr layer_height_texture; + // Data to render this volume using the layer height texture + LayerHeightTextureData layer_height_texture_data; bool has_layer_height_texture() const { return this->layer_height_texture.get() != nullptr; } @@ -315,11 +344,11 @@ public: { return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->height; } size_t layer_height_texture_cells() const { return (this->layer_height_texture.get() == nullptr) ? 0 : this->layer_height_texture->cells; } - void* layer_height_texture_data_ptr_level0() { + void* layer_height_texture_data_ptr_level0() const { return (layer_height_texture.get() == nullptr) ? 0 : (void*)layer_height_texture->data.data(); } - void* layer_height_texture_data_ptr_level1() { + void* layer_height_texture_data_ptr_level1() const { return (layer_height_texture.get() == nullptr) ? 0 : (void*)(layer_height_texture->data.data() + layer_height_texture->width * layer_height_texture->height * 4); } @@ -328,6 +357,17 @@ public: double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * bounding_box.max.z); } void generate_layer_height_texture(PrintObject *print_object, bool force); + + void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, PrintObject* print_object, float z_cursor_relative, float edit_band_width) + { + layer_height_texture_data.texture_id = texture_id; + layer_height_texture_data.shader_id = shader_id; + layer_height_texture_data.print_object = print_object; + layer_height_texture_data.z_cursor_relative = z_cursor_relative; + layer_height_texture_data.edit_band_width = edit_band_width; + } + + void reset_layer_height_texture_data() { layer_height_texture_data.reset(); } }; class GLVolumeCollection diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 6324f933e1..25aa6b81a7 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -19,6 +19,9 @@ void enable() const; void disable() const; + int shader_program_id() const + %code%{ RETVAL = THIS->shader_program_id; %}; + std::string last_error() const %code%{ RETVAL = THIS->last_error; %}; }; @@ -45,6 +48,9 @@ int zoom_to_volumes() %code%{ RETVAL = THIS->zoom_to_volumes; %}; + void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, PrintObject* print_object, float z_cursor_relative, float edit_band_width); + void reset_layer_height_texture_data(); + int object_idx() const; int volume_idx() const; int instance_idx() const;