Use OpenGL 2.0 shaders for the layer height rendering.
Use OpenGL 2.0 shaders for the print path rendering for performance reasons.
This commit is contained in:
parent
56f845f3c1
commit
045de596e2
@ -14,7 +14,6 @@ use Slic3r::GUI::ConfigWizard;
|
||||
use Slic3r::GUI::Controller;
|
||||
use Slic3r::GUI::Controller::ManualControlDialog;
|
||||
use Slic3r::GUI::Controller::PrinterPanel;
|
||||
use Slic3r::GUI::GLShader;
|
||||
use Slic3r::GUI::MainFrame;
|
||||
use Slic3r::GUI::Notifier;
|
||||
use Slic3r::GUI::Plater;
|
||||
|
@ -149,8 +149,6 @@ sub new {
|
||||
$self->{layer_height_edit_last_z} = 0.;
|
||||
$self->{layer_height_edit_last_action} = 0;
|
||||
|
||||
$self->{use_VBOs} = 0;
|
||||
|
||||
$self->reset_objects;
|
||||
|
||||
EVT_PAINT($self, sub {
|
||||
@ -194,15 +192,15 @@ sub layer_editing_enabled {
|
||||
if (! $self->{layer_editing_initialized}) {
|
||||
# Enabling the layer editing for the first time. This triggers compilation of the necessary OpenGL shaders.
|
||||
# If compilation fails, a message box is shown with the error codes.
|
||||
my $shader = $self->{shader} = new Slic3r::GUI::GLShader;
|
||||
my $shader = new Slic3r::GUI::_3DScene::GLShader;
|
||||
my $error_message;
|
||||
if (ref($shader)) {
|
||||
my $info = $shader->Load($self->_fragment_shader, $self->_vertex_shader);
|
||||
if (defined($info)) {
|
||||
if (! $shader->load($self->_fragment_shader_variable_layer_height, $self->_vertex_shader_variable_layer_height)) {
|
||||
# Compilation or linking of the shaders failed.
|
||||
$error_message = "Cannot compile an OpenGL Shader, therefore the Variable Layer Editing will be disabled.\n\n"
|
||||
. $info;
|
||||
. $shader->last_error;
|
||||
$shader = undef;
|
||||
} else {
|
||||
$self->{layer_height_edit_shader} = $shader;
|
||||
($self->{layer_preview_z_texture_id}) = glGenTextures_p(1);
|
||||
glBindTexture(GL_TEXTURE_2D, $self->{layer_preview_z_texture_id});
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
@ -212,11 +210,6 @@ sub layer_editing_enabled {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
} else {
|
||||
# Cannot initialize the Shader object, some of the OpenGL capabilities are missing.
|
||||
$error_message = "Cannot instantiate an OpenGL Shader, therefore the Variable Layer Editing will be disabled.\n\n"
|
||||
. $shader;
|
||||
}
|
||||
if (defined($error_message)) {
|
||||
# Don't enable the layer editing tool.
|
||||
$self->{layer_editing_enabled} = 0;
|
||||
@ -361,6 +354,7 @@ sub mouse_event {
|
||||
# Index 2 means no editing, just wait for mouse up event.
|
||||
$self->_layer_height_edited(2);
|
||||
$self->Refresh;
|
||||
$self->Update;
|
||||
} else {
|
||||
# Select volume in this 3D canvas.
|
||||
# Don't deselect a volume if layer editing is enabled. We want the object to stay selected
|
||||
@ -380,6 +374,7 @@ sub mouse_event {
|
||||
}
|
||||
|
||||
$self->Refresh;
|
||||
$self->Update;
|
||||
}
|
||||
|
||||
# propagate event through callback
|
||||
@ -421,6 +416,7 @@ sub mouse_event {
|
||||
$self->_drag_start_pos($cur_pos);
|
||||
$self->_dragged(1);
|
||||
$self->Refresh;
|
||||
$self->Update;
|
||||
} elsif ($e->Dragging) {
|
||||
if ($self->_layer_height_edited && $object_idx_selected != -1) {
|
||||
$self->_variable_layer_thickness_action($e) if ($self->_layer_height_edited == 1);
|
||||
@ -445,6 +441,7 @@ sub mouse_event {
|
||||
}
|
||||
$self->on_viewport_changed->() if $self->on_viewport_changed;
|
||||
$self->Refresh;
|
||||
$self->Update;
|
||||
}
|
||||
$self->_drag_start_pos($pos);
|
||||
} elsif ($e->MiddleIsDown || $e->RightIsDown) {
|
||||
@ -459,6 +456,7 @@ sub mouse_event {
|
||||
);
|
||||
$self->on_viewport_changed->() if $self->on_viewport_changed;
|
||||
$self->Refresh;
|
||||
$self->Update;
|
||||
}
|
||||
$self->_drag_start_xy($pos);
|
||||
}
|
||||
@ -488,7 +486,10 @@ sub mouse_event {
|
||||
$self->_mouse_pos($pos);
|
||||
# Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor
|
||||
# hovers over.
|
||||
$self->Refresh if ($self->enable_picking);
|
||||
if ($self->enable_picking) {
|
||||
$self->Update;
|
||||
$self->Refresh;
|
||||
}
|
||||
} else {
|
||||
$e->Skip();
|
||||
}
|
||||
@ -540,8 +541,8 @@ sub mouse_wheel_event {
|
||||
# Reset selection.
|
||||
sub reset_objects {
|
||||
my ($self) = @_;
|
||||
if ($self->{use_VBOs}) {
|
||||
$self->GetContext;
|
||||
if ($self->GetContext) {
|
||||
$self->SetCurrent($self->GetContext);
|
||||
$self->volumes->release_geometry;
|
||||
}
|
||||
$self->volumes->erase;
|
||||
@ -898,6 +899,24 @@ sub SetCurrent {
|
||||
}
|
||||
}
|
||||
|
||||
sub UseVBOs {
|
||||
my ($self) = @_;
|
||||
|
||||
if (! defined ($self->{use_VBOs})) {
|
||||
# Don't use VBOs if anything fails.
|
||||
$self->{use_VBOs} = 0;
|
||||
if ($self->GetContext) {
|
||||
$self->SetCurrent($self->GetContext);
|
||||
my @gl_version = split(/\./, glGetString(GL_VERSION));
|
||||
$self->{use_VBOs} = int($gl_version[0]) >= 2;
|
||||
# print "InitGL $self OpenGL major: $gl_version[0], minor: $gl_version[1]. Use VBOs: ", $self->{use_VBOs}, "\n";
|
||||
}
|
||||
#FIXME
|
||||
$self->{use_VBOs} = 0;
|
||||
}
|
||||
return $self->{use_VBOs};
|
||||
}
|
||||
|
||||
sub Resize {
|
||||
my ($self, $x, $y) = @_;
|
||||
|
||||
@ -948,10 +967,6 @@ sub InitGL {
|
||||
return unless $self->GetContext;
|
||||
$self->init(1);
|
||||
|
||||
my @gl_version = split(/\./, glGetString(GL_VERSION));
|
||||
$self->{use_VBOs} = int($gl_version[0]) >= 2;
|
||||
# print "OpenGL major: $gl_version[0], minor: $gl_version[1]. Use VBOs: ", $self->{use_VBOs}, "\n";
|
||||
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glColor3f(1, 0, 0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -982,10 +997,10 @@ sub InitGL {
|
||||
# Enables Smooth Color Shading; try GL_FLAT for (lack of) fun.
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glMaterialfv_p(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 0.5, 0.3, 0.3, 1);
|
||||
glMaterialfv_p(GL_FRONT_AND_BACK, GL_SPECULAR, 1, 1, 1, 1);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50);
|
||||
glMaterialfv_p(GL_FRONT_AND_BACK, GL_EMISSION, 0.1, 0, 0, 0.9);
|
||||
# glMaterialfv_p(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 0.5, 0.3, 0.3, 1);
|
||||
# glMaterialfv_p(GL_FRONT_AND_BACK, GL_SPECULAR, 1, 1, 1, 1);
|
||||
# glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50);
|
||||
# glMaterialfv_p(GL_FRONT_AND_BACK, GL_EMISSION, 0.1, 0, 0, 0.9);
|
||||
|
||||
# A handy trick -- have surface material mirror the color.
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
@ -993,12 +1008,31 @@ sub InitGL {
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
Slic3r::GUI::_3DScene::_glew_init;
|
||||
|
||||
if ($self->UseVBOs) {
|
||||
my $shader = new Slic3r::GUI::_3DScene::GLShader;
|
||||
if (! $shader->load($self->_fragment_shader_Gouraud, $self->_vertex_shader_Gouraud)) {
|
||||
# if (! $shader->load($self->_fragment_shader_Phong, $self->_vertex_shader_Phong)) {
|
||||
print "Compilaton of path shader failed: \n" . $shader->last_error . "\n";
|
||||
$shader = undef;
|
||||
} else {
|
||||
$self->{plain_shader} = $shader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub DestroyGL {
|
||||
my $self = shift;
|
||||
if ($self->init && $self->GetContext) {
|
||||
delete $self->{shader};
|
||||
if ($self->GetContext) {
|
||||
$self->SetCurrent($self->GetContext);
|
||||
if ($self->{plain_shader}) {
|
||||
$self->{plain_shader}->release;
|
||||
delete $self->{plain_shader};
|
||||
}
|
||||
if ($self->{layer_height_edit_shader}) {
|
||||
$self->{layer_height_edit_shader}->release;
|
||||
delete $self->{layer_height_edit_shader};
|
||||
}
|
||||
$self->volumes->release_geometry;
|
||||
}
|
||||
}
|
||||
@ -1173,7 +1207,15 @@ sub Render {
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
# draw objects
|
||||
if ($self->enable_picking) {
|
||||
$self->draw_volumes;
|
||||
} elsif ($self->UseVBOs) {
|
||||
$self->{plain_shader}->enable if $self->{plain_shader};
|
||||
$self->volumes->render_VBOs;
|
||||
$self->{plain_shader}->disable;
|
||||
} else {
|
||||
$self->volumes->render_legacy;
|
||||
}
|
||||
|
||||
# draw cutting plane
|
||||
if (defined $self->cutting_plane_z) {
|
||||
@ -1199,7 +1241,7 @@ sub Render {
|
||||
$self->SwapBuffers();
|
||||
|
||||
# Calling glFinish has a performance penalty, but it seems to fix some OpenGL driver hang-up with extremely large scenes.
|
||||
glFinish();
|
||||
# glFinish();
|
||||
}
|
||||
|
||||
sub draw_volumes {
|
||||
@ -1217,23 +1259,15 @@ sub draw_volumes {
|
||||
my $volume = $self->volumes->[$volume_idx];
|
||||
|
||||
my $shader_active = 0;
|
||||
if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{shader} && $volume->has_layer_height_texture) {
|
||||
if ($self->layer_editing_enabled && ! $fakecolor && $volume->selected && $self->{layer_height_edit_shader} && $volume->has_layer_height_texture) {
|
||||
# Update the height texture if the ModelObject::layer_height_texture is invalid.
|
||||
$volume->generate_layer_height_texture(
|
||||
$self->{print}->get_object(int($volume->select_group_id / 1000000)), 0);
|
||||
$self->{shader}->Enable;
|
||||
my $z_to_texture_row_id = $self->{shader}->Map('z_to_texture_row');
|
||||
my $z_texture_row_to_normalized_id = $self->{shader}->Map('z_texture_row_to_normalized');
|
||||
my $z_cursor_id = $self->{shader}->Map('z_cursor');
|
||||
my $z_cursor_band_width_id = $self->{shader}->Map('z_cursor_band_width');
|
||||
die if ! defined($z_to_texture_row_id);
|
||||
die if ! defined($z_texture_row_to_normalized_id);
|
||||
die if ! defined($z_cursor_id);
|
||||
die if ! defined($z_cursor_band_width_id);
|
||||
glUniform1fARB($z_to_texture_row_id, $volume->layer_height_texture_z_to_row_id);
|
||||
glUniform1fARB($z_texture_row_to_normalized_id, 1. / $volume->layer_height_texture_height);
|
||||
glUniform1fARB($z_cursor_id, $volume->bounding_box->z_max * $z_cursor_relative);
|
||||
glUniform1fARB($z_cursor_band_width_id, $self->{layer_height_edit_band_width});
|
||||
$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);
|
||||
@ -1266,7 +1300,7 @@ sub draw_volumes {
|
||||
|
||||
if ($shader_active) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
$self->{shader}->Disable;
|
||||
$self->{layer_height_edit_shader}->disable;
|
||||
}
|
||||
}
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
@ -1356,7 +1390,7 @@ sub draw_active_object_annotations {
|
||||
# $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking.
|
||||
my ($self) = @_;
|
||||
|
||||
return if (! $self->{shader} || ! $self->layer_editing_enabled);
|
||||
return if (! $self->{layer_height_edit_shader} || ! $self->layer_editing_enabled);
|
||||
|
||||
my $volume;
|
||||
foreach my $volume_idx (0..$#{$self->volumes}) {
|
||||
@ -1374,13 +1408,11 @@ sub draw_active_object_annotations {
|
||||
my ($reset_left, $reset_bottom, $reset_right, $reset_top) = $self->_variable_layer_thickness_reset_rect_viewport;
|
||||
my $z_cursor_relative = $self->_variable_layer_thickness_bar_mouse_cursor_z_relative;
|
||||
|
||||
$self->{shader}->Enable;
|
||||
my $z_to_texture_row_id = $self->{shader}->Map('z_to_texture_row');
|
||||
my $z_texture_row_to_normalized_id = $self->{shader}->Map('z_texture_row_to_normalized');
|
||||
my $z_cursor_id = $self->{shader}->Map('z_cursor');
|
||||
glUniform1fARB($z_to_texture_row_id, $volume->layer_height_texture_z_to_row_id);
|
||||
glUniform1fARB($z_texture_row_to_normalized_id, 1. / $volume->layer_height_texture_height);
|
||||
glUniform1fARB($z_cursor_id, $volume->bounding_box->z_max * $z_cursor_relative);
|
||||
$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});
|
||||
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);
|
||||
@ -1405,7 +1437,7 @@ sub draw_active_object_annotations {
|
||||
glVertex3f($bar_left, $bar_top, $volume->bounding_box->z_max);
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
$self->{shader}->Disable;
|
||||
$self->{layer_height_edit_shader}->disable;
|
||||
|
||||
# Paint the tooltip.
|
||||
if ($self->_variable_layer_thickness_load_overlay_image) {
|
||||
@ -1455,9 +1487,7 @@ sub opengl_info
|
||||
my $gl_version = glGetString(GL_VERSION);
|
||||
my $gl_vendor = glGetString(GL_VENDOR);
|
||||
my $gl_renderer = glGetString(GL_RENDERER);
|
||||
my $glsl_version_ARB = glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) // '';
|
||||
my $glsl_version = glGetString(GL_SHADING_LANGUAGE_VERSION) // $glsl_version_ARB;
|
||||
$glsl_version .= 'ARB(' . $glsl_version_ARB . ')' if ($glsl_version_ARB ne '' && $glsl_version ne $glsl_version_ARB);
|
||||
my $glsl_version = glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
|
||||
my $out = '';
|
||||
$out .= "$tag{h2start}OpenGL installation$tag{h2end}$tag{eol}";
|
||||
@ -1467,25 +1497,15 @@ sub opengl_info
|
||||
$out .= " $tag{bstart}renderer: $tag{bend}${gl_renderer}$tag{eol}";
|
||||
$out .= " $tag{bstart}GLSL version: $tag{bend}${glsl_version}$tag{eol}";
|
||||
|
||||
# Check for required OpenGL extensions
|
||||
$out .= "$tag{h2start}Required extensions (* implemented):$tag{h2end}$tag{eol}";
|
||||
my @extensions_required = qw(GL_ARB_shader_objects GL_ARB_fragment_shader GL_ARB_vertex_shader GL_ARB_shading_language_100);
|
||||
foreach my $ext (sort @extensions_required) {
|
||||
my $stat = glpCheckExtension($ext);
|
||||
$out .= sprintf("%s ${ext}$tag{eol}", $stat?' ':'*');
|
||||
$out .= sprintf(" ${stat}$tag{eol}") if ($stat && $stat !~ m|^$ext |);
|
||||
}
|
||||
# Check for other OpenGL extensions
|
||||
$out .= "$tag{h2start}Installed extensions (* implemented in the module):$tag{h2end}$tag{eol}";
|
||||
my $extensions = glGetString(GL_EXTENSIONS);
|
||||
my @extensions = split(' ',$extensions);
|
||||
foreach my $ext (sort @extensions) {
|
||||
if(! grep(/^$extensions$/, @extensions_required)) {
|
||||
my $stat = glpCheckExtension($ext);
|
||||
$out .= sprintf("%s ${ext}$tag{eol}", $stat?' ':'*');
|
||||
$out .= sprintf(" ${stat}$tag{eol}") if ($stat && $stat !~ m|^$ext |);
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
@ -1519,17 +1539,167 @@ sub _report_opengl_state
|
||||
}
|
||||
}
|
||||
|
||||
sub _vertex_shader {
|
||||
sub _vertex_shader_Gouraud {
|
||||
return <<'VERTEX';
|
||||
#version 110
|
||||
|
||||
#define INTENSITY_CORRECTION 0.7
|
||||
|
||||
#define LIGHT_TOP_DIR -0.6/1.31, 0.6/1.31, 1./1.31
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.5 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 50.
|
||||
|
||||
#define LIGHT_FRONT_DIR 1./1.43, 0.2/1.43, 1./1.43
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SHININESS 50.
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 eye, normal, lightDir, viewVector, halfVector;
|
||||
float NdotL, NdotHV;
|
||||
|
||||
eye = vec3(0., 0., 1.);
|
||||
|
||||
// First transform the normal into eye space and normalize the result.
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Now normalize the light's direction. Note that according to the OpenGL specification, the light is stored in eye space.
|
||||
// Also since we're talking about a directional light, the position field is actually direction.
|
||||
lightDir = vec3(LIGHT_TOP_DIR);
|
||||
halfVector = normalize(lightDir + eye);
|
||||
|
||||
// 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.
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
|
||||
intensity_tainted = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
intensity_specular = 0.;
|
||||
|
||||
if (NdotL > 0.0)
|
||||
intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source.
|
||||
lightDir = vec3(LIGHT_FRONT_DIR);
|
||||
// halfVector = normalize(lightDir + eye);
|
||||
NdotL = max(dot(normal, lightDir), 0.0);
|
||||
intensity_tainted += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
// compute the specular term if NdotL is larger than zero
|
||||
// if (NdotL > 0.0)
|
||||
// intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_FRONT_SHININESS);
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
||||
VERTEX
|
||||
}
|
||||
|
||||
sub _fragment_shader_Gouraud {
|
||||
return <<'FRAGMENT';
|
||||
#version 110
|
||||
|
||||
varying float intensity_specular;
|
||||
varying float intensity_tainted;
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor =
|
||||
vec4(intensity_specular, intensity_specular, intensity_specular, 0.) + uniform_color * intensity_tainted;
|
||||
gl_FragColor.a = uniform_color.a;
|
||||
}
|
||||
|
||||
FRAGMENT
|
||||
}
|
||||
|
||||
sub _vertex_shader_Phong {
|
||||
return <<'VERTEX';
|
||||
#version 110
|
||||
|
||||
varying vec3 normal;
|
||||
varying vec3 eye;
|
||||
void main(void)
|
||||
{
|
||||
eye = normalize(vec3(gl_ModelViewMatrix * gl_Vertex));
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
VERTEX
|
||||
}
|
||||
|
||||
sub _fragment_shader_Phong {
|
||||
return <<'FRAGMENT';
|
||||
#version 110
|
||||
|
||||
#define INTENSITY_CORRECTION 0.7
|
||||
|
||||
#define LIGHT_TOP_DIR -0.6/1.31, 0.6/1.31, 1./1.31
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.5 * INTENSITY_CORRECTION)
|
||||
//#define LIGHT_TOP_SHININESS 50.
|
||||
#define LIGHT_TOP_SHININESS 10.
|
||||
|
||||
#define LIGHT_FRONT_DIR 1./1.43, 0.2/1.43, 1./1.43
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_FRONT_SHININESS 50.
|
||||
|
||||
#define INTENSITY_AMBIENT 0.0
|
||||
|
||||
varying vec3 normal;
|
||||
varying vec3 eye;
|
||||
uniform vec4 uniform_color;
|
||||
void main() {
|
||||
|
||||
float intensity_specular = 0.;
|
||||
float intensity_tainted = 0.;
|
||||
float intensity = max(dot(normal,vec3(LIGHT_TOP_DIR)), 0.0);
|
||||
// if the vertex is lit compute the specular color
|
||||
if (intensity > 0.0) {
|
||||
intensity_tainted = LIGHT_TOP_DIFFUSE * intensity;
|
||||
// compute the half vector
|
||||
vec3 h = normalize(vec3(LIGHT_TOP_DIR) + eye);
|
||||
// compute the specular term into spec
|
||||
intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(h, normal), 0.0), LIGHT_TOP_SHININESS);
|
||||
}
|
||||
intensity = max(dot(normal,vec3(LIGHT_FRONT_DIR)), 0.0);
|
||||
// if the vertex is lit compute the specular color
|
||||
if (intensity > 0.0) {
|
||||
intensity_tainted += LIGHT_FRONT_DIFFUSE * intensity;
|
||||
// compute the half vector
|
||||
// vec3 h = normalize(vec3(LIGHT_FRONT_DIR) + eye);
|
||||
// compute the specular term into spec
|
||||
// intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(h,normal), 0.0), LIGHT_FRONT_SHININESS);
|
||||
}
|
||||
gl_FragColor = max(
|
||||
vec4(intensity_specular, intensity_specular, intensity_specular, 0.) + uniform_color * intensity_tainted,
|
||||
INTENSITY_AMBIENT * uniform_color);
|
||||
gl_FragColor.a = uniform_color.a;
|
||||
}
|
||||
FRAGMENT
|
||||
}
|
||||
|
||||
sub _vertex_shader_variable_layer_height {
|
||||
return <<'VERTEX';
|
||||
#version 110
|
||||
|
||||
#define LIGHT_TOP_DIR 0., 1., 0.
|
||||
#define LIGHT_TOP_DIFFUSE 0.2
|
||||
#define LIGHT_TOP_SPECULAR 0.3
|
||||
#define LIGHT_TOP_SHININESS 50.
|
||||
|
||||
#define LIGHT_FRONT_DIR 0., 0., 1.
|
||||
#define LIGHT_FRONT_DIFFUSE 0.5
|
||||
#define LIGHT_FRONT_SPECULAR 0.3
|
||||
#define LIGHT_FRONT_SHININESS 50.
|
||||
|
||||
#define INTENSITY_AMBIENT 0.1
|
||||
|
||||
@ -1562,7 +1732,7 @@ void main()
|
||||
intensity_specular = 0.;
|
||||
|
||||
// if (NdotL > 0.0)
|
||||
// intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), gl_FrontMaterial.shininess);
|
||||
// intensity_specular = LIGHT_TOP_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source.
|
||||
lightDir = vec3(LIGHT_FRONT_DIR);
|
||||
@ -1572,7 +1742,7 @@ void main()
|
||||
|
||||
// compute the specular term if NdotL is larger than zero
|
||||
if (NdotL > 0.0)
|
||||
intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(normal, halfVector), 0.0), gl_FrontMaterial.shininess);
|
||||
intensity_specular += LIGHT_FRONT_SPECULAR * pow(max(dot(normal, halfVector), 0.0), LIGHT_FRONT_SHININESS);
|
||||
|
||||
// Scaled to widths of the Z texture.
|
||||
object_z = gl_Vertex.z / gl_Vertex.w;
|
||||
@ -1583,7 +1753,7 @@ void main()
|
||||
VERTEX
|
||||
}
|
||||
|
||||
sub _fragment_shader {
|
||||
sub _fragment_shader_variable_layer_height {
|
||||
return <<'FRAGMENT';
|
||||
#version 110
|
||||
|
||||
@ -1662,6 +1832,8 @@ sub new {
|
||||
sub load_object {
|
||||
my ($self, $model, $print, $obj_idx, $instance_idxs) = @_;
|
||||
|
||||
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||
|
||||
my $model_object;
|
||||
if ($model->isa('Slic3r::Model::Object')) {
|
||||
$model_object = $model;
|
||||
@ -1672,7 +1844,9 @@ sub load_object {
|
||||
}
|
||||
|
||||
$instance_idxs ||= [0..$#{$model_object->instances}];
|
||||
my $volume_indices = $self->volumes->load_object($model_object, $obj_idx, $instance_idxs, $self->color_by, $self->select_by, $self->drag_by);
|
||||
my $volume_indices = $self->volumes->load_object(
|
||||
$model_object, $obj_idx, $instance_idxs, $self->color_by, $self->select_by, $self->drag_by,
|
||||
$self->UseVBOs);
|
||||
return @{$volume_indices};
|
||||
}
|
||||
|
||||
@ -1681,8 +1855,8 @@ sub load_object {
|
||||
sub load_print_toolpaths {
|
||||
my ($self, $print) = @_;
|
||||
|
||||
$self->GetContext if ($self->{use_VBOs});
|
||||
Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $self->{use_VBOs})
|
||||
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||
Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $self->UseVBOs)
|
||||
if ($print->step_done(STEP_SKIRT) && $print->step_done(STEP_BRIM));
|
||||
}
|
||||
|
||||
@ -1692,8 +1866,8 @@ sub load_print_toolpaths {
|
||||
sub load_print_object_toolpaths {
|
||||
my ($self, $object) = @_;
|
||||
|
||||
$self->GetContext if ($self->{use_VBOs});
|
||||
Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $self->{use_VBOs});
|
||||
$self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||
Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $self->UseVBOs);
|
||||
}
|
||||
|
||||
sub set_toolpaths_range {
|
||||
|
@ -1,193 +0,0 @@
|
||||
############################################################
|
||||
#
|
||||
# Stripped down from the Perl OpenGL::Shader package by Vojtech Bubnik
|
||||
# to only support the GLSL shaders. The original source was not maintained
|
||||
# and did not install properly through the CPAN archive, and it was unnecessary
|
||||
# complex.
|
||||
#
|
||||
# Original copyright:
|
||||
#
|
||||
# Copyright 2007 Graphcomp - ALL RIGHTS RESERVED
|
||||
# Author: Bob "grafman" Free - grafman@graphcomp.com
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
#
|
||||
############################################################
|
||||
|
||||
package Slic3r::GUI::GLShader;
|
||||
use OpenGL(':all');
|
||||
|
||||
# Avoid cloning this class by the worker threads.
|
||||
sub CLONE_SKIP { 1 }
|
||||
|
||||
# Shader constructor
|
||||
sub new
|
||||
{
|
||||
# Check for required OpenGL extensions
|
||||
my $error_message = '';
|
||||
my $extensions_valid = 1;
|
||||
foreach my $i (map "GL_ARB_$_", qw(shader_objects fragment_shader vertex_shader shading_language_100)) {
|
||||
if (OpenGL::glpCheckExtension($i)) {
|
||||
$error_message .= "Missing OpenGL extension: $i\n";
|
||||
$extensions_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $extensions_valid) {
|
||||
# Cannot create a shader object, because some of the necessary OpenGL extensions are missing.
|
||||
# Form an error message.
|
||||
my $gl_version = glGetString(GL_VERSION);
|
||||
my $gl_vendor = glGetString(GL_VENDOR);
|
||||
my $gl_renderer = glGetString(GL_RENDERER);
|
||||
my $glsl_version_ARB = glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) // '';
|
||||
my $glsl_version = glGetString(GL_SHADING_LANGUAGE_VERSION) // $glsl_version_ARB;
|
||||
$glsl_version .= 'ARB(' . $glsl_version_ARB . ')' if ($glsl_version_ARB ne '' && $glsl_version ne $glsl_version_ARB);
|
||||
my $out = '';
|
||||
if ($^O eq 'MSWin32' && $gl_vendor eq 'Microsoft Corporation' && $gl_renderer eq 'GDI Generic') {
|
||||
$out .= "Windows is using a software OpenGL renderer.\n";
|
||||
$out .= "You are either connected over remote desktop,\n";
|
||||
$out .= "or a hardware acceleration is not available.\n";
|
||||
}
|
||||
$out .= "GL version: ${gl_version}\n";
|
||||
$out .= "vendor: ${gl_vendor}\n";
|
||||
$out .= "renderer: ${gl_renderer}\n";
|
||||
$out .= "GLSL version: ${glsl_version}\n";
|
||||
$error_message = $out . $error_message;
|
||||
return $error_message;
|
||||
}
|
||||
|
||||
my $this = shift;
|
||||
my $class = ref($this) || $this;
|
||||
my($type) = @_;
|
||||
my $self = {type => uc($type)};
|
||||
bless($self, $class);
|
||||
|
||||
# Get GL_SHADING_LANGUAGE_VERSION_ARB
|
||||
my $shader_ver = glGetString(0x8B8C);
|
||||
$shader_ver =~ m|([\d\.]+)|;
|
||||
$self->{version} = $1 || '0';
|
||||
# print "Shader version: $self->{version}\n";
|
||||
return $self;
|
||||
}
|
||||
|
||||
# Shader destructor
|
||||
# Must be disabled first
|
||||
sub DESTROY
|
||||
{
|
||||
my($self) = @_;
|
||||
|
||||
if ($self->{program}) {
|
||||
glDetachObjectARB($self->{program},$self->{fragment_id}) if ($self->{fragment_id});
|
||||
glDetachObjectARB($self->{program},$self->{vertex_id}) if ($self->{vertex_id});
|
||||
glDeleteProgramsARB_p($self->{program});
|
||||
}
|
||||
|
||||
glDeleteProgramsARB_p($self->{fragment_id}) if ($self->{fragment_id});
|
||||
glDeleteProgramsARB_p($self->{vertex_id}) if ($self->{vertex_id});
|
||||
}
|
||||
|
||||
# Load shader strings
|
||||
sub Load
|
||||
{
|
||||
my($self, $fragment, $vertex) = @_;
|
||||
|
||||
# Load fragment code
|
||||
if ($fragment) {
|
||||
$self->{fragment_id} = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
|
||||
return "glCreateShaderObjectARB failed." if (!$self->{fragment_id});
|
||||
glShaderSourceARB_p($self->{fragment_id}, $fragment);
|
||||
glCompileShaderARB($self->{fragment_id});
|
||||
my $stat = glGetInfoLogARB_p($self->{fragment_id});
|
||||
return "Fragment shader compilation failed:\n$stat" if ($stat);
|
||||
}
|
||||
|
||||
# Load vertex code
|
||||
if ($vertex) {
|
||||
$self->{vertex_id} = glCreateShaderObjectARB(GL_VERTEX_SHADER);
|
||||
return "glCreateShaderObjectARB failed." if (!$self->{vertex_id});
|
||||
glShaderSourceARB_p($self->{vertex_id}, $vertex);
|
||||
glCompileShaderARB($self->{vertex_id});
|
||||
$stat = glGetInfoLogARB_p($self->{vertex_id});
|
||||
return "Vertex shader compilation failed:\n$stat" if ($stat);
|
||||
}
|
||||
|
||||
# Link shaders
|
||||
my $sp = glCreateProgramObjectARB();
|
||||
return "glCreateProgramObjectARB failed." if (!sp);
|
||||
glAttachObjectARB($sp, $self->{fragment_id}) if ($fragment);
|
||||
glAttachObjectARB($sp, $self->{vertex_id}) if ($vertex);
|
||||
glLinkProgramARB($sp);
|
||||
my $linked = glGetObjectParameterivARB_p($sp, GL_OBJECT_LINK_STATUS_ARB);
|
||||
if (!$linked) {
|
||||
$stat = glGetInfoLogARB_p($sp);
|
||||
return "Shader linking failed:\n$stat" if ($stat);
|
||||
return 'Unable to link the shader.';
|
||||
}
|
||||
|
||||
$self->{program} = $sp;
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Enable shader
|
||||
sub Enable
|
||||
{
|
||||
my($self) = @_;
|
||||
glUseProgramObjectARB($self->{program}) if ($self->{program});
|
||||
}
|
||||
|
||||
# Disable shader
|
||||
sub Disable
|
||||
{
|
||||
my($self) = @_;
|
||||
glUseProgramObjectARB(0) if ($self->{program});
|
||||
}
|
||||
|
||||
# Return shader vertex attribute ID
|
||||
sub MapAttr
|
||||
{
|
||||
my($self,$attr) = @_;
|
||||
return undef if (!$self->{program});
|
||||
my $id = glGetAttribLocationARB_p($self->{program},$attr);
|
||||
return undef if ($id < 0);
|
||||
return $id;
|
||||
}
|
||||
|
||||
# Return shader uniform variable ID
|
||||
sub Map
|
||||
{
|
||||
my($self,$var) = @_;
|
||||
return undef if (!$self->{program});
|
||||
my $id = glGetUniformLocationARB_p($self->{program},$var);
|
||||
return undef if ($id < 0);
|
||||
return $id;
|
||||
}
|
||||
|
||||
# Set shader vector
|
||||
sub SetVector
|
||||
{
|
||||
my($self,$var,@values) = @_;
|
||||
|
||||
my $id = $self->Map($var);
|
||||
return 'Unable to map $var' if (!defined($id));
|
||||
|
||||
my $count = scalar(@values);
|
||||
eval('glUniform'.$count.'fARB($id,@values)');
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
# Set shader 4x4 matrix
|
||||
sub SetMatrix
|
||||
{
|
||||
my($self,$var,$oga) = @_;
|
||||
|
||||
my $id = $self->Map($var);
|
||||
return 'Unable to map $var' if (!defined($id));
|
||||
|
||||
glUniformMatrix4fvARB_c($id,1,0,$oga->ptr());
|
||||
return '';
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
@ -247,6 +247,9 @@ sub new {
|
||||
);
|
||||
}
|
||||
|
||||
package Slic3r::GUI::_3DScene::GLShader;
|
||||
sub CLONE_SKIP { 1 }
|
||||
|
||||
package Slic3r::GUI::_3DScene::GLVolume::Collection;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
|
@ -60,6 +60,7 @@ REGISTER_CLASS(Surface, "Surface");
|
||||
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
|
||||
REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2");
|
||||
REGISTER_CLASS(TriangleMesh, "TriangleMesh");
|
||||
REGISTER_CLASS(GLShader, "GUI::_3DScene::GLShader");
|
||||
REGISTER_CLASS(GLVolume, "GUI::_3DScene::GLVolume");
|
||||
REGISTER_CLASS(GLVolumeCollection, "GUI::_3DScene::GLVolume::Collection");
|
||||
|
||||
|
@ -34,8 +34,6 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z);
|
||||
}
|
||||
|
||||
vertices_and_normals_interleaved_size = this->vertices_and_normals_interleaved.size();
|
||||
}
|
||||
|
||||
void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
|
||||
@ -85,11 +83,20 @@ void GLIndexedVertexArray::release_geometry()
|
||||
|
||||
void GLIndexedVertexArray::render() const
|
||||
{
|
||||
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, this->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);
|
||||
} else {
|
||||
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3);
|
||||
glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data());
|
||||
}
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (this->indexed()) {
|
||||
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||
// Render using the Vertex Buffer Objects.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||
if (this->triangle_indices_size > 0) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
|
||||
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr);
|
||||
@ -98,32 +105,21 @@ void GLIndexedVertexArray::render() const
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
|
||||
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
} else {
|
||||
// Render in an immediate mode.
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||
// Due to issues with the Intel drivers, rather limit the amount of vertices processed per draw command.
|
||||
if (! this->triangle_indices.empty())
|
||||
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data());
|
||||
if (! this->quad_indices.empty())
|
||||
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data());
|
||||
}
|
||||
} else {
|
||||
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||
// Render using the Vertex Buffer Objects.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||
} else
|
||||
glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
} else {
|
||||
// Render in an immediate mode.
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||
glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6));
|
||||
}
|
||||
}
|
||||
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||
if (this->vertices_and_normals_interleaved_VBO_id)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
void GLIndexedVertexArray::render(
|
||||
@ -137,7 +133,10 @@ void GLIndexedVertexArray::render(
|
||||
if (this->vertices_and_normals_interleaved_VBO_id) {
|
||||
// Render using the Vertex Buffer Objects.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
|
||||
glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (this->triangle_indices_size > 0) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
|
||||
glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4));
|
||||
@ -150,22 +149,26 @@ void GLIndexedVertexArray::render(
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
} else {
|
||||
// Render in an immediate mode.
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, this->vertices_and_normals_interleaved.data());
|
||||
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3);
|
||||
glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data());
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (! this->triangle_indices.empty())
|
||||
glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first));
|
||||
if (! this->quad_indices.empty())
|
||||
glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first));
|
||||
}
|
||||
|
||||
glInterleavedArrays(GL_N3F_V3F, 0, nullptr);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
void GLVolume::set_range(double min_z, double max_z)
|
||||
{
|
||||
this->qverts_range.first = 0;
|
||||
this->qverts_range.second = this->indexed_vertex_array.quad_indices.size();
|
||||
this->qverts_range.second = this->indexed_vertex_array.quad_indices_size;
|
||||
this->tverts_range.first = 0;
|
||||
this->tverts_range.second = this->indexed_vertex_array.triangle_indices.size();
|
||||
this->tverts_range.second = this->indexed_vertex_array.triangle_indices_size;
|
||||
if (! this->print_zs.empty()) {
|
||||
// The Z layer range is specified.
|
||||
// First test whether the Z span of this object is not out of (min_z, max_z) completely.
|
||||
@ -246,7 +249,8 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by)
|
||||
const std::string &drag_by,
|
||||
bool use_VBOs)
|
||||
{
|
||||
static float colors[4][4] = {
|
||||
{ 1.0f, 1.0f, 0.0f, 1.f },
|
||||
@ -272,7 +276,9 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
v.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||
v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx;
|
||||
if (select_by == "object")
|
||||
v.select_group_id = obj_idx * 1000000;
|
||||
@ -292,6 +298,74 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
void GLVolumeCollection::render_VBOs() const
|
||||
{
|
||||
// glEnable(GL_BLEND);
|
||||
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glCullFace(GL_BACK);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
GLint current_program_id;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id);
|
||||
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
|
||||
|
||||
for (GLVolume *volume : this->volumes) {
|
||||
if (! volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
|
||||
continue;
|
||||
GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
continue;
|
||||
if (color_id >= 0)
|
||||
glUniform4fv(color_id, 1, (const GLfloat*)volume->color);
|
||||
else
|
||||
glColor4f(volume->color[0], volume->color[1], volume->color[2], volume->color[3]);
|
||||
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);
|
||||
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));
|
||||
}
|
||||
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_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
// glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void GLVolumeCollection::render_legacy() const
|
||||
{
|
||||
glCullFace(GL_BACK);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
for (GLVolume *volume : this->volumes) {
|
||||
assert(! volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
|
||||
GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
continue;
|
||||
glColor4f(volume->color[0], volume->color[1], volume->color[2], volume->color[3]);
|
||||
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data() + 3);
|
||||
glNormalPointer(GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data());
|
||||
if (n_triangles > 0)
|
||||
glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, volume->indexed_vertex_array.triangle_indices.data() + volume->tverts_range.first);
|
||||
if (n_quads > 0)
|
||||
glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, volume->indexed_vertex_array.quad_indices.data() + volume->qverts_range.first);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
// caller is responsible for supplying NO lines with zero length
|
||||
static void thick_lines_to_indexed_vertex_array(
|
||||
const Lines &lines,
|
||||
|
@ -189,10 +189,7 @@ public:
|
||||
selected(false),
|
||||
hover(false),
|
||||
qverts_range(0, size_t(-1)),
|
||||
tverts_range(0, size_t(-1)),
|
||||
name_vertex_buffer(0),
|
||||
name_normal_buffer(0),
|
||||
name_index_buffer(0)
|
||||
tverts_range(0, size_t(-1))
|
||||
{
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
@ -238,12 +235,6 @@ public:
|
||||
// Offset into qverts & tverts, or offsets into indices stored into an OpenGL name_index_buffer.
|
||||
std::vector<size_t> offsets;
|
||||
|
||||
// OpenGL buffers for vertices and their normals.
|
||||
int name_vertex_buffer;
|
||||
int name_normal_buffer;
|
||||
// OpenGL buffer of the indices.
|
||||
int name_index_buffer;
|
||||
|
||||
int object_idx() const { return this->composite_id / 1000000; }
|
||||
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
|
||||
int instance_idx() const { return this->composite_id % 1000; }
|
||||
@ -296,8 +287,12 @@ public:
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by);
|
||||
const std::string &drag_by,
|
||||
bool use_VBOs);
|
||||
|
||||
// Render the volumes by OpenGL.
|
||||
void render_VBOs() const;
|
||||
void render_legacy() const;
|
||||
// Release the geometry data assigned to the volumes.
|
||||
// If OpenGL VBOs were allocated, an OpenGL context has to be active to release them.
|
||||
void release_geometry() { for (auto *v : volumes) v->release_geometry(); }
|
||||
|
@ -1,8 +1,28 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
#include <xsinit.h>
|
||||
#include "slic3r/GUI/GLShader.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
%name{Slic3r::GUI::_3DScene::GLShader} class GLShader {
|
||||
GLShader();
|
||||
~GLShader();
|
||||
|
||||
bool load(const char *fragment_shader, const char *vertex_shader);
|
||||
void release();
|
||||
|
||||
int get_attrib_location(const char *name) const;
|
||||
int get_uniform_location(const char *name) const;
|
||||
|
||||
bool set_uniform(const char *name, float value) const;
|
||||
|
||||
void enable() const;
|
||||
void disable() const;
|
||||
|
||||
std::string last_error() const
|
||||
%code%{ RETVAL = THIS->last_error; %};
|
||||
};
|
||||
|
||||
%name{Slic3r::GUI::_3DScene::GLVolume} class GLVolume {
|
||||
GLVolume();
|
||||
~GLVolume();
|
||||
@ -55,7 +75,7 @@
|
||||
GLVolumeCollection();
|
||||
~GLVolumeCollection();
|
||||
|
||||
std::vector<int> load_object(ModelObject *object, int obj_idx, std::vector<int> instance_idxs, std::string color_by, std::string select_by, std::string drag_by);
|
||||
std::vector<int> load_object(ModelObject *object, int obj_idx, std::vector<int> instance_idxs, std::string color_by, std::string select_by, std::string drag_by, bool use_VBOs);
|
||||
|
||||
void erase()
|
||||
%code{% THIS->clear(); %};
|
||||
@ -65,6 +85,8 @@
|
||||
|
||||
void set_range(double low, double high);
|
||||
|
||||
void render_VBOs() const;
|
||||
void render_legacy() const;
|
||||
void release_geometry();
|
||||
%{
|
||||
|
||||
@ -97,16 +119,16 @@ void
|
||||
_load_print_toolpaths(print, volumes, use_VBOs)
|
||||
Print *print;
|
||||
GLVolumeCollection *volumes;
|
||||
bool use_VBOs;
|
||||
int use_VBOs;
|
||||
CODE:
|
||||
_3DScene::_load_print_toolpaths(print, volumes, use_VBOs);
|
||||
_3DScene::_load_print_toolpaths(print, volumes, use_VBOs != 0);
|
||||
|
||||
void
|
||||
_load_print_object_toolpaths(print_object, volumes, use_VBOs)
|
||||
PrintObject *print_object;
|
||||
GLVolumeCollection *volumes;
|
||||
bool use_VBOs;
|
||||
int use_VBOs;
|
||||
CODE:
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, use_VBOs);
|
||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, use_VBOs != 0);
|
||||
|
||||
%}
|
||||
|
@ -233,6 +233,8 @@ PrintObjectSupportMaterial* O_OBJECT_SLIC3R
|
||||
Ref<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
|
||||
Clone<PrintObjectSupportMaterial> O_OBJECT_SLIC3R_T
|
||||
|
||||
GLShader* O_OBJECT_SLIC3R
|
||||
Ref<GLShader> O_OBJECT_SLIC3R_T
|
||||
GLVolume* O_OBJECT_SLIC3R
|
||||
Ref<GLVolume> O_OBJECT_SLIC3R_T
|
||||
GLVolumeCollection* O_OBJECT_SLIC3R
|
||||
|
@ -211,6 +211,8 @@
|
||||
%typemap{ModelInstancePtrs*};
|
||||
%typemap{Ref<ModelInstancePtrs>}{simple};
|
||||
%typemap{Clone<ModelInstancePtrs>}{simple};
|
||||
%typemap{GLShader*};
|
||||
%typemap{Ref<GLShader>}{simple};
|
||||
%typemap{GLVolume*};
|
||||
%typemap{Ref<GLVolume>}{simple};
|
||||
%typemap{GLVolumeCollection*};
|
||||
|
Loading…
Reference in New Issue
Block a user