Programs¶
Programs are objects which run one or more shaders on the GPU. A shader is a stage of the program that operates on a vertex, some geometry, or a fragment (a pixel on the screen). Programs that wish to read or write to buffers and textures arbitrarily use compute shaders.
Progams containing vertex and fragment shaders are launched by draw commands, while programs containing compute shaders are dispatched.
Info
The various objects described on this page are declared in
the package Orka.Rendering.Programs
and its child packages.
Creating a program¶
To create a program, call function Create_Program
, giving it a value of
the type Module
(defined in the child package Modules
):
Program_1 : Program := Create_Program (Module_1);
In this case Module_1
should contain either a vertex shader and a fragment shader,
or just a compute shader.
Another way is to create a program from multiple modules by giving Create_Program
a value of the type Module_Array
(also defined in the child package Modules
):
Program_2 : Program := Create_Program (Modules.Module_Array'
(Module_VS, Module_FS));
Modules¶
Modules contain one or more shaders, which are all retrieved from files
or from inline text.
A module is created by the function Create_Module
from the package
Orka.Rendering.Programs.Modules
:
Module_1 : Modules.Module := Modules.Create_Module
(Shader_Location,
VS => "tools/gltf.vert",
FS => "tools/gltf.frag")
In this example Shader_Location
is a pointer to an object implementing
the interface Location
. The location object is responsible for retrieving
the files given by the parameters VS
and FS
(for a vertex and fragment shader).
Implementations exist which can read files from a directory or from an archive file.
See Locations for more information.
For the example which creates Program_2
, the modules are created separately using calls to
the function Create_Module
:
Module_VS : Modules.Module :=
Modules.Create_Module (Shader_Location, VS => "oversized-triangle.vert");
To create a module from text instead of a file, use Create_Module_From_Sources
:
Module_FS : Modules.Module :=
Modules.Create_Module_From_Sources (FS => Text_Of_Fragment_Shader);
This can be useful if you need to programmatically construct a shader.
Uniforms¶
Programs may contain uniforms. A uniform is a variable that can be read by a shader and written to from Ada code prior to running the program. Uniforms should contain a small amount of data. For a larger amount of data, like a few matrices for cameras, a buffer binded as a UBO can be used. Very large buffers must be binded as an SSBO.
A uniform can be retrieved using the function Uniform
.
It return a type Uniform
from the child package Uniforms
:
Uniform_View : Uniforms.Uniform := Program_1.Uniform ("view");
Uniform_Proj : Uniforms.Uniform := Program_1.Uniform ("proj");
In the shader, the uniforms are declared as following:
uniform mat4 view;
uniform mat4 proj;
and then used in the main()
function of the shader:
gl_Position = proj * view * some_vertex;
Retrieving an unused uniform may raise an exception
If a uniform is defined by a shader, but is unused, retrieving it
may raise the exception Uniforms.Uniform_Inactive_Error
.
Textures and images¶
For textures and images it is sufficient to bind them by calling
Orka.Rendering.Textures.Bind
.
If it is needed to get the uniform of a texture or image so that
it can be verified that the kind and format of the sampler and texture
are compatible, call the functions Uniform_Sampler
or Uniform_Image
:
Uniform_Texture : Uniforms.Uniform_Sampler :=
Program_1.Uniform_Sampler ("diffuseTexture");
Type Uniform_Sampler
provides the procedure Verify_Compatibility
to
verify the kind and format:
Uniform_Texture.Verify_Compatibility (Texture_1);
Using a program¶
To use a program before executing a rendering command, call the
procedure Use_Program
:
Program_1.Use_Program;
After a program has been made active, rendering commands can be issued to render to a framebuffer.