2016-12-02 10:14:24 +00:00
|
|
|
############################################################
|
|
|
|
#
|
2016-12-02 10:19:27 +00:00
|
|
|
# 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
|
2016-12-02 10:14:24 +00:00
|
|
|
# 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');
|
|
|
|
|
2016-12-14 14:09:12 +00:00
|
|
|
# Avoid cloning this class by the worker threads.
|
|
|
|
sub CLONE_SKIP { 1 }
|
|
|
|
|
2016-12-02 10:14:24 +00:00
|
|
|
# Shader constructor
|
|
|
|
sub new
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
# 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') {
|
|
|
|
if ($gl_vendor eq 'Microsoft Corporation' && $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;
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Shader destructor
|
|
|
|
# Must be disabled first
|
|
|
|
sub DESTROY
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self) = @_;
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
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});
|
|
|
|
}
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
glDeleteProgramsARB_p($self->{fragment_id}) if ($self->{fragment_id});
|
|
|
|
glDeleteProgramsARB_p($self->{vertex_id}) if ($self->{vertex_id});
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Load shader strings
|
|
|
|
sub Load
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
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;
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Enable shader
|
|
|
|
sub Enable
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self) = @_;
|
|
|
|
glUseProgramObjectARB($self->{program}) if ($self->{program});
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Disable shader
|
|
|
|
sub Disable
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self) = @_;
|
|
|
|
glUseProgramObjectARB(0) if ($self->{program});
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return shader vertex attribute ID
|
|
|
|
sub MapAttr
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self,$attr) = @_;
|
|
|
|
return undef if (!$self->{program});
|
|
|
|
my $id = glGetAttribLocationARB_p($self->{program},$attr);
|
|
|
|
return undef if ($id < 0);
|
|
|
|
return $id;
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return shader uniform variable ID
|
|
|
|
sub Map
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self,$var) = @_;
|
|
|
|
return undef if (!$self->{program});
|
|
|
|
my $id = glGetUniformLocationARB_p($self->{program},$var);
|
|
|
|
return undef if ($id < 0);
|
|
|
|
return $id;
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Set shader vector
|
|
|
|
sub SetVector
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self,$var,@values) = @_;
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
my $id = $self->Map($var);
|
|
|
|
return 'Unable to map $var' if (!defined($id));
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
my $count = scalar(@values);
|
|
|
|
eval('glUniform'.$count.'fARB($id,@values)');
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
return '';
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# Set shader 4x4 matrix
|
|
|
|
sub SetMatrix
|
|
|
|
{
|
2017-02-19 17:01:03 +00:00
|
|
|
my($self,$var,$oga) = @_;
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
my $id = $self->Map($var);
|
|
|
|
return 'Unable to map $var' if (!defined($id));
|
2016-12-02 10:14:24 +00:00
|
|
|
|
2017-02-19 17:01:03 +00:00
|
|
|
glUniformMatrix4fvARB_c($id,1,0,$oga->ptr());
|
|
|
|
return '';
|
2016-12-02 10:14:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|
|
__END__
|