355 lines
8.5 KiB
Ada
355 lines
8.5 KiB
Ada
with
|
|
openGL.Tasks,
|
|
|
|
GL.Pointers,
|
|
GL.lean,
|
|
|
|
ada.Characters.latin_1,
|
|
interfaces.C.Strings;
|
|
|
|
|
|
package body openGL.Program
|
|
is
|
|
use gl.lean,
|
|
Interfaces;
|
|
|
|
compiling_in_debug_Mode : constant Boolean := True;
|
|
|
|
type Shader_view is access all Shader.item'Class;
|
|
|
|
|
|
--------------
|
|
-- Parameters
|
|
--
|
|
|
|
procedure Program_is (Self : in out Parameters; Now : in openGL.Program.view)
|
|
is
|
|
begin
|
|
Self.Program := Now;
|
|
end Program_is;
|
|
|
|
|
|
function Program (Self : in Parameters) return openGL.Program.view
|
|
is
|
|
begin
|
|
return Self.Program;
|
|
end Program;
|
|
|
|
|
|
---------
|
|
--- Forge
|
|
--
|
|
|
|
procedure define (Self : in out Item; use_vertex_Shader : in Shader.view;
|
|
use_fragment_Shader : in Shader.view)
|
|
is
|
|
begin
|
|
Tasks.check;
|
|
|
|
Self.gl_Program := glCreateProgram;
|
|
|
|
glAttachShader (Self.gl_Program, use_vertex_Shader.gl_Shader);
|
|
glAttachShader (Self.gl_Program, use_fragment_Shader.gl_Shader);
|
|
|
|
Self. vertex_Shader := use_vertex_Shader;
|
|
Self.fragment_Shader := use_fragment_Shader;
|
|
|
|
glLinkProgram (Self.gl_Program);
|
|
|
|
declare
|
|
use type C.int;
|
|
Status : aliased gl.glInt;
|
|
begin
|
|
glGetProgramiv (Self.gl_Program,
|
|
GL_LINK_STATUS,
|
|
Status'unchecked_Access);
|
|
|
|
if Status = 0
|
|
then
|
|
declare
|
|
link_Log : constant String := Self.ProgramInfoLog;
|
|
begin
|
|
Self.destroy;
|
|
raise Error with "Program link error ~ " & link_Log;
|
|
end;
|
|
end if;
|
|
end;
|
|
|
|
if compiling_in_debug_Mode
|
|
then
|
|
glValidateProgram (Self.gl_Program);
|
|
end if;
|
|
end define;
|
|
|
|
|
|
|
|
procedure define (Self : in out Item; use_vertex_Shader_File : in String;
|
|
use_fragment_Shader_File : in String)
|
|
is
|
|
use openGL.Shader;
|
|
the_vertex_Shader : constant Shader_view := new openGL.Shader.item;
|
|
the_fragment_Shader : constant Shader_view := new openGL.Shader.item;
|
|
begin
|
|
the_vertex_Shader .define (openGL.Shader.vertex, use_vertex_Shader_File);
|
|
the_fragment_Shader.define (openGL.Shader.fragment, use_fragment_Shader_File);
|
|
|
|
Self.define ( the_vertex_Shader.all'Access,
|
|
the_fragment_Shader.all'Access);
|
|
end define;
|
|
|
|
|
|
|
|
procedure destroy (Self : in out Item)
|
|
is
|
|
begin
|
|
Tasks.check;
|
|
glDeleteProgram (Self.gl_Program);
|
|
end destroy;
|
|
|
|
|
|
--------------
|
|
-- Attributes
|
|
--
|
|
|
|
function Attribute (Self : access Item'Class; Named : in String) return openGL.Attribute.view
|
|
is
|
|
begin
|
|
for Each in 1 .. Self.attribute_Count
|
|
loop
|
|
if Self.Attributes (Each).Name = Named
|
|
then
|
|
return Self.Attributes (Each);
|
|
end if;
|
|
end loop;
|
|
|
|
raise Error with "'" & Named & "' is not a valid program attribute.";
|
|
end Attribute;
|
|
|
|
|
|
|
|
function attribute_Location (Self : access Item'Class; Named : in String) return gl.GLuint
|
|
is
|
|
use gl.Pointers;
|
|
use type gl.GLint;
|
|
|
|
attribute_Name : C.strings.chars_ptr := C.Strings.new_String (Named & ada.characters.Latin_1.NUL);
|
|
|
|
begin
|
|
Tasks.check;
|
|
|
|
declare
|
|
gl_Location : constant gl.GLint := glGetAttribLocation (Self.gl_Program,
|
|
to_GLchar_access (attribute_Name));
|
|
begin
|
|
if gl_Location = -1
|
|
then
|
|
raise Error with "Requested attribute '" & Named & "' has no gl location in program.";
|
|
end if;
|
|
|
|
C.Strings.free (attribute_Name);
|
|
|
|
return gl.GLuint (gl_Location);
|
|
end;
|
|
end attribute_Location;
|
|
|
|
|
|
|
|
function is_defined (Self : in Item'Class) return Boolean
|
|
is
|
|
use type a_gl_Program;
|
|
begin
|
|
return Self.gl_Program /= 0;
|
|
end is_defined;
|
|
|
|
|
|
|
|
function ProgramInfoLog (Self : in Item) return String
|
|
is
|
|
use C, GL;
|
|
|
|
info_log_Length : aliased glInt := 0;
|
|
chars_Written : aliased glSizei := 0;
|
|
|
|
begin
|
|
Tasks.check;
|
|
|
|
glGetProgramiv (Self.gl_Program,
|
|
GL_INFO_LOG_LENGTH,
|
|
info_log_Length'unchecked_Access);
|
|
|
|
if info_log_Length = 0 then
|
|
return "";
|
|
end if;
|
|
|
|
declare
|
|
use GL.Pointers;
|
|
info_Log : aliased C.char_array := C.char_array' [1 .. C.size_t (info_log_Length) => <>];
|
|
info_Log_ptr : constant C.strings.chars_ptr := C.strings.to_chars_ptr (info_Log'unchecked_Access);
|
|
begin
|
|
glGetProgramInfoLog (Self.gl_Program,
|
|
glSizei (info_log_Length),
|
|
chars_Written'unchecked_Access,
|
|
to_GLchar_access (info_Log_ptr));
|
|
return C.to_Ada (info_Log);
|
|
end;
|
|
end ProgramInfoLog;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.bool
|
|
is
|
|
the_Variable : Variable.uniform.bool;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.int
|
|
is
|
|
the_Variable : Variable.uniform.int;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.float
|
|
is
|
|
the_Variable : Variable.uniform.float;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.vec3
|
|
is
|
|
the_Variable : Variable.uniform.vec3;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.vec4
|
|
is
|
|
the_Variable : Variable.uniform.vec4;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.mat3
|
|
is
|
|
the_Variable : Variable.uniform.mat3;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.mat4
|
|
is
|
|
the_Variable : Variable.uniform.mat4;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
function uniform_Variable (Self : access Item'Class; Named : in String) return Variable.uniform.sampler2D
|
|
is
|
|
the_Variable : Variable.uniform.sampler2D;
|
|
begin
|
|
the_Variable.define (Self, Named);
|
|
return the_Variable;
|
|
end uniform_Variable;
|
|
|
|
|
|
--------------
|
|
-- Operations
|
|
--
|
|
|
|
procedure add (Self : in out Item; Attribute : in openGL.Attribute.view)
|
|
is
|
|
begin
|
|
Self.attribute_Count := Self.attribute_Count + 1;
|
|
Self.Attributes (Self.attribute_Count) := Attribute;
|
|
end add;
|
|
|
|
|
|
|
|
procedure enable (Self : in out Item)
|
|
is
|
|
use type gl.GLuint;
|
|
begin
|
|
Tasks.check;
|
|
|
|
if Self.gl_Program = 0
|
|
then
|
|
Item'Class (Self).define; -- TODO: This appears to do nothing.
|
|
end if;
|
|
|
|
glUseProgram (self.gl_Program);
|
|
end enable;
|
|
|
|
|
|
|
|
procedure enable_Attributes (Self : in Item)
|
|
is
|
|
begin
|
|
for Each in 1 .. Self.attribute_Count
|
|
loop
|
|
Self.Attributes (Each).enable;
|
|
end loop;
|
|
end enable_Attributes;
|
|
|
|
|
|
|
|
procedure mvp_Transform_is (Self : in out Item; Now : in Matrix_4x4)
|
|
is
|
|
begin
|
|
Self.mvp_Transform := Now;
|
|
end mvp_Transform_is;
|
|
|
|
|
|
|
|
procedure Scale_is (Self : in out Item; Now : in Vector_3)
|
|
is
|
|
begin
|
|
Self.Scale := Now;
|
|
end Scale_is;
|
|
|
|
|
|
|
|
procedure set_Uniforms (Self : in Item)
|
|
is
|
|
the_mvp_Uniform : constant Variable.uniform.mat4 := Self.uniform_Variable ("mvp_Transform");
|
|
the_scale_Uniform : constant Variable.uniform.vec3 := Self.uniform_Variable ("Scale");
|
|
begin
|
|
the_mvp_Uniform .Value_is (Self.mvp_Transform);
|
|
the_scale_Uniform.Value_is (Self.Scale);
|
|
end set_Uniforms;
|
|
|
|
|
|
|
|
-- Privvy
|
|
--
|
|
|
|
function gl_Program (Self : in Item) return a_gl_Program
|
|
is
|
|
begin
|
|
return Self.gl_Program;
|
|
end gl_Program;
|
|
|
|
|
|
end openGL.Program;
|