Error reporting on initialization of the Layer Editing OpenGL shaders.

The shaders are initialized when the layer editing button is pressed
for the first time. If the initialization fails, a message box
is shown and the layer editing will stay disabled.
This commit is contained in:
bubnikv 2017-02-19 18:01:03 +01:00
parent 70229be9bc
commit 898deb48c4
3 changed files with 174 additions and 117 deletions

View file

@ -24,160 +24,171 @@ sub CLONE_SKIP { 1 }
# 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";
# 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;
}
}
my $this = shift;
my $class = ref($this) || $this;
my($type) = @_;
my $self = {type => uc($type)};
bless($self,$class);
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;
}
# Get GL_SHADING_LANGUAGE_VERSION_ARB
my $shader_ver = glGetString(0x8B8C);
$shader_ver =~ m|([\d\.]+)|;
$self->{version} = $1 || '0';
print
return $self;
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) = @_;
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});
}
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});
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) = @_;
my($self, $fragment, $vertex) = @_;
# Load fragment code
if ($fragment)
{
$self->{fragment_id} = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
return undef if (!$self->{fragment_id});
# 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);
}
glShaderSourceARB_p($self->{fragment_id}, $fragment);
#my $frag = glGetShaderSourceARB_p($self->{fragment_id});
#print STDERR "Loaded fragment:\n$frag\n";
# 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);
}
glCompileShaderARB($self->{fragment_id});
my $stat = glGetInfoLogARB_p($self->{fragment_id});
return "Fragment shader: $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.';
}
# 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 '';
$self->{program} = $sp;
return undef;
}
# Enable shader
sub Enable
{
my($self) = @_;
glUseProgramObjectARB($self->{program}) if ($self->{program});
my($self) = @_;
glUseProgramObjectARB($self->{program}) if ($self->{program});
}
# Disable shader
sub Disable
{
my($self) = @_;
glUseProgramObjectARB(0) if ($self->{program});
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;
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;
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($self,$var,@values) = @_;
my $id = $self->Map($var);
return 'Unable to map $var' if (!defined($id));
my $id = $self->Map($var);
return 'Unable to map $var' if (!defined($id));
my $count = scalar(@values);
eval('glUniform'.$count.'fARB($id,@values)');
my $count = scalar(@values);
eval('glUniform'.$count.'fARB($id,@values)');
return '';
return '';
}
# Set shader 4x4 matrix
sub SetMatrix
{
my($self,$var,$oga) = @_;
my($self,$var,$oga) = @_;
my $id = $self->Map($var);
return 'Unable to map $var' if (!defined($id));
my $id = $self->Map($var);
return 'Unable to map $var' if (!defined($id));
glUniformMatrix4fvARB_c($id,1,0,$oga->ptr());
return '';
glUniformMatrix4fvARB_c($id,1,0,$oga->ptr());
return '';
}
1;