mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Initial experiments with vertex / fragment shaders,
prototype to visualize layer thickness.
This commit is contained in:
		
							parent
							
								
									946b36bb4d
								
							
						
					
					
						commit
						7e1af658b6
					
				
					 3 changed files with 288 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -14,6 +14,7 @@ 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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -720,6 +720,13 @@ sub InitGL {
 | 
			
		|||
    return if $self->init;
 | 
			
		||||
    return unless $self->GetContext;
 | 
			
		||||
    $self->init(1);
 | 
			
		||||
 | 
			
		||||
    my $shader;
 | 
			
		||||
#    $shader = $self->{shader} = new Slic3r::GUI::GLShader;
 | 
			
		||||
    if ($self->{shader}) {
 | 
			
		||||
        my $info = $shader->Load($self->_fragment_shader, $self->_vertex_shader);
 | 
			
		||||
        print $info if $info;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    glClearColor(0, 0, 0, 1);
 | 
			
		||||
    glColor3f(1, 0, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -957,6 +964,8 @@ sub draw_volumes {
 | 
			
		|||
    # $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking.
 | 
			
		||||
    my ($self, $fakecolor) = @_;
 | 
			
		||||
    
 | 
			
		||||
    $self->{shader}->Enable if (! $fakecolor && $self->{shader});
 | 
			
		||||
 | 
			
		||||
    glEnable(GL_BLEND);
 | 
			
		||||
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -1017,15 +1026,33 @@ sub draw_volumes {
 | 
			
		|||
        if ($qverts_begin < $qverts_end) {
 | 
			
		||||
            glVertexPointer_c(3, GL_FLOAT, 0, $volume->qverts->verts_ptr);
 | 
			
		||||
            glNormalPointer_c(GL_FLOAT, 0, $volume->qverts->norms_ptr);
 | 
			
		||||
            glDrawArrays(GL_QUADS, $qverts_begin / 3, ($qverts_end-$qverts_begin) / 3);
 | 
			
		||||
            $qverts_begin /= 3;
 | 
			
		||||
            $qverts_end /= 3;
 | 
			
		||||
            my $nvertices = $qverts_end-$qverts_begin;
 | 
			
		||||
            while ($nvertices > 0) {
 | 
			
		||||
                my $nvertices_this = ($nvertices > 4096) ? 4096 : $nvertices;
 | 
			
		||||
                glDrawArrays(GL_QUADS, $qverts_begin, $nvertices_this);
 | 
			
		||||
                $qverts_begin += $nvertices_this;
 | 
			
		||||
                $nvertices -= $nvertices_this;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if ($tverts_begin < $tverts_end) {
 | 
			
		||||
            glVertexPointer_c(3, GL_FLOAT, 0, $volume->tverts->verts_ptr);
 | 
			
		||||
            glNormalPointer_c(GL_FLOAT, 0, $volume->tverts->norms_ptr);
 | 
			
		||||
            glDrawArrays(GL_TRIANGLES, $tverts_begin / 3, ($tverts_end-$tverts_begin) / 3);
 | 
			
		||||
            $tverts_begin /= 3;
 | 
			
		||||
            $tverts_end /= 3;
 | 
			
		||||
            my $nvertices = $tverts_end-$tverts_begin;
 | 
			
		||||
            while ($nvertices > 0) {
 | 
			
		||||
                my $nvertices_this = ($nvertices > 4095) ? 4095 : $nvertices;
 | 
			
		||||
                glDrawArrays(GL_TRIANGLES, $tverts_begin, $nvertices_this);
 | 
			
		||||
                $tverts_begin += $nvertices_this;
 | 
			
		||||
                $nvertices -= $nvertices_this;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        glVertexPointer_c(3, GL_FLOAT, 0, 0);
 | 
			
		||||
        glNormalPointer_c(GL_FLOAT, 0, 0);        
 | 
			
		||||
        glPopMatrix();
 | 
			
		||||
    }
 | 
			
		||||
    glDisableClientState(GL_NORMAL_ARRAY);
 | 
			
		||||
| 
						 | 
				
			
			@ -1036,8 +1063,11 @@ sub draw_volumes {
 | 
			
		|||
        glColor3f(0, 0, 0);
 | 
			
		||||
        glVertexPointer_p(3, $self->cut_lines_vertices);
 | 
			
		||||
        glDrawArrays(GL_LINES, 0, $self->cut_lines_vertices->elements / 3);
 | 
			
		||||
        glVertexPointer_c(3, GL_FLOAT, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
    glDisableClientState(GL_VERTEX_ARRAY);
 | 
			
		||||
 | 
			
		||||
    $self->{shader}->Disable if (! $fakecolor && $self->{shader});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _report_opengl_state
 | 
			
		||||
| 
						 | 
				
			
			@ -1069,6 +1099,86 @@ sub _report_opengl_state
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _vertex_shader {
 | 
			
		||||
    return <<'VERTEX';
 | 
			
		||||
#version 110
 | 
			
		||||
 | 
			
		||||
varying float object_z;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    vec3 normal, lightDir, viewVector, halfVector;
 | 
			
		||||
    vec4 diffuse, ambient, globalAmbient, specular = vec4(0.0);
 | 
			
		||||
    float NdotL,NdotHV;
 | 
			
		||||
    
 | 
			
		||||
    // 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 = normalize(vec3(gl_LightSource[0].position));
 | 
			
		||||
    
 | 
			
		||||
    // 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);
 | 
			
		||||
    
 | 
			
		||||
    // Compute the diffuse, ambient and globalAmbient terms.
 | 
			
		||||
//    diffuse = NdotL * (gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse);
 | 
			
		||||
//    ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
 | 
			
		||||
    diffuse = NdotL * (gl_Color * gl_LightSource[0].diffuse);
 | 
			
		||||
    ambient = gl_Color * gl_LightSource[0].ambient;
 | 
			
		||||
    globalAmbient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
 | 
			
		||||
    
 | 
			
		||||
    // compute the specular term if NdotL is  larger than zero
 | 
			
		||||
    if (NdotL > 0.0) {
 | 
			
		||||
        NdotHV = max(dot(normal, normalize(gl_LightSource[0].halfVector.xyz)),0.0);
 | 
			
		||||
        specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV,gl_FrontMaterial.shininess);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Perform the same lighting calculation for the 2nd light source.
 | 
			
		||||
    lightDir = normalize(vec3(gl_LightSource[1].position));
 | 
			
		||||
    NdotL = max(dot(normal, lightDir), 0.0);
 | 
			
		||||
//    diffuse += NdotL * (gl_FrontMaterial.diffuse * gl_LightSource[1].diffuse);
 | 
			
		||||
//    ambient += gl_FrontMaterial.ambient * gl_LightSource[1].ambient;
 | 
			
		||||
    diffuse += NdotL * (gl_Color * gl_LightSource[1].diffuse);
 | 
			
		||||
    ambient += gl_Color * gl_LightSource[1].ambient;
 | 
			
		||||
    
 | 
			
		||||
    // compute the specular term if NdotL is  larger than zero
 | 
			
		||||
    if (NdotL > 0.0) {
 | 
			
		||||
        NdotHV = max(dot(normal, normalize(gl_LightSource[1].halfVector.xyz)),0.0);
 | 
			
		||||
        specular += gl_FrontMaterial.specular * gl_LightSource[1].specular * pow(NdotHV,gl_FrontMaterial.shininess);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    gl_FrontColor = globalAmbient + diffuse + ambient + specular;
 | 
			
		||||
    gl_FrontColor.a = 1.;
 | 
			
		||||
    
 | 
			
		||||
    gl_Position = ftransform();  
 | 
			
		||||
    object_z = gl_Vertex.z / gl_Vertex.w;
 | 
			
		||||
} 
 | 
			
		||||
 | 
			
		||||
VERTEX
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _fragment_shader {
 | 
			
		||||
    return <<'FRAGMENT';
 | 
			
		||||
#version 110
 | 
			
		||||
#define M_PI 3.1415926535897932384626433832795
 | 
			
		||||
 | 
			
		||||
varying float object_z;
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    float layer_height = 0.25;
 | 
			
		||||
    float layer_height2 = 0.5 * layer_height;
 | 
			
		||||
    float layer_center = floor(object_z / layer_height) * layer_height + layer_height2;
 | 
			
		||||
    float intensity = cos(M_PI * 0.7 * (layer_center - object_z) / layer_height);
 | 
			
		||||
    gl_FragColor = gl_Color * intensity;
 | 
			
		||||
    gl_FragColor.a = 1.;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FRAGMENT
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Container for object geometry and selection status.
 | 
			
		||||
package Slic3r::GUI::3DScene::Volume;
 | 
			
		||||
use Moo;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										174
									
								
								lib/Slic3r/GUI/GLShader.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								lib/Slic3r/GUI/GLShader.pm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,174 @@
 | 
			
		|||
############################################################
 | 
			
		||||
#
 | 
			
		||||
# OpenGL::Shader::Objects - 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');
 | 
			
		||||
 | 
			
		||||
# Shader constructor
 | 
			
		||||
sub new
 | 
			
		||||
{
 | 
			
		||||
  # Check for required OpenGL extensions
 | 
			
		||||
  return undef if (OpenGL::glpCheckExtension('GL_ARB_shader_objects'));
 | 
			
		||||
  return undef if (OpenGL::glpCheckExtension('GL_ARB_fragment_shader'));
 | 
			
		||||
  return undef if (OpenGL::glpCheckExtension('GL_ARB_vertex_shader'));
 | 
			
		||||
  return undef if (OpenGL::glpCheckExtension('GL_ARB_shading_language_100'));
 | 
			
		||||
#  my $glsl_version = glGetString(GL_SHADING_LANGUAGE_VERSION);
 | 
			
		||||
#  my $glsl_version_ARB = glGetString(GL_SHADING_LANGUAGE_VERSION_ARB );
 | 
			
		||||
#  print "GLSL version: $glsl_version, ARB: $glsl_version_ARB\n";
 | 
			
		||||
 | 
			
		||||
  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 
 | 
			
		||||
  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 undef if (!$self->{fragment_id});
 | 
			
		||||
 | 
			
		||||
    glShaderSourceARB_p($self->{fragment_id}, $fragment);
 | 
			
		||||
    #my $frag = glGetShaderSourceARB_p($self->{fragment_id});
 | 
			
		||||
    #print STDERR "Loaded fragment:\n$frag\n";
 | 
			
		||||
 | 
			
		||||
    glCompileShaderARB($self->{fragment_id});
 | 
			
		||||
    my $stat = glGetInfoLogARB_p($self->{fragment_id});
 | 
			
		||||
    return "Fragment shader: $stat" if ($stat);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  # Load vertex code
 | 
			
		||||
  if ($vertex)
 | 
			
		||||
  {
 | 
			
		||||
    $self->{vertex_id} = glCreateShaderObjectARB(GL_VERTEX_SHADER);
 | 
			
		||||
    return undef if (!$self->{vertex_id});
 | 
			
		||||
 | 
			
		||||
    glShaderSourceARB_p($self->{vertex_id}, $vertex);
 | 
			
		||||
    #my $vert = glGetShaderSourceARB_p($self->{vertex_id});
 | 
			
		||||
    #print STDERR "Loaded vertex:\n$vert\n";
 | 
			
		||||
 | 
			
		||||
    glCompileShaderARB($self->{vertex_id});
 | 
			
		||||
    $stat = glGetInfoLogARB_p($self->{vertex_id});
 | 
			
		||||
    return "Vertex shader: $stat" if ($stat);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  # Link shaders
 | 
			
		||||
  my $sp = glCreateProgramObjectARB();
 | 
			
		||||
  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);
 | 
			
		||||
    #print STDERR "Load shader: $stat\n";
 | 
			
		||||
    return "Link shader: $stat" if ($stat);
 | 
			
		||||
    return 'Unable to link shader';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $self->{program} = $sp;
 | 
			
		||||
 | 
			
		||||
  return '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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__
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue