Skip to content

Shaders

Shaders are compiled from GLSL source files and registered with ResourceManager as ShaderDescriptors. The actual backend compilation happens asynchronously during load_from_descriptors.

Registration

cpp
auto res = ResourceManager::get();

res->register_shader(ShaderDescriptor::create(
    "pbr",
    "shaders/vertex/pbr.axsl"_engine,
    "shaders/fragment/pbr.axsl"_engine
));

The string literal suffix _engine resolves paths relative to the engine asset root.

Descriptor Fields

FieldTypeDescription
idstd::stringUnique identifier used to look up the shader
vertex_pathPathEngine-relative path to the vertex stage source
fragment_pathPathEngine-relative path to the fragment stage source
geometry_pathPath (optional)Path to the geometry stage source
compute_pathPath (optional)Path to the compute stage source

Vertex and fragment paths are required for rasterization shaders. For compute-only shaders, only compute_path is needed.

Uploading

cpp
res->load_from_descriptors<ShaderDescriptor>(RendererBackend::OpenGL);

This triggers backend compilation. For OpenGL, each descriptor compiles and links the GLSL stages. For Vulkan, it compiles to SPIR-V and creates a VkShaderModule.

Attaching to an Entity

Shaders are referenced by id through ResourceComponent:

cpp
auto* obj = add_entity<Object>("Cube", glm::vec3(0, 0, -5));
obj->add_component<ResourceComponent>()->attach_shader("pbr");

The GeometryPass resolves the shader handle each frame and binds it before issuing draw calls.

Backend Specializations

The Shader base class is specialized per backend:

BackendType
OpenGLOpenGLShader
VulkanVulkanShader

Backend objects are created by ResourceManager during upload; consumers always work through the Shader interface.

Setting Uniforms

cpp
auto* shader = ResourceManager::get()->get_shader("pbr");
shader->bind();
shader->set_uniform("u_view", view_matrix);
shader->set_uniform("u_projection", projection_matrix);
shader->set_uniform("u_light_dir", glm::vec3(0, -1, 0));

Hot Reloading

INFO

Shader hot reloading is planned. Recompile a shader at runtime by calling res->reload_shader("pbr") - this recompiles the source files and swaps the backend object without destroying the handle.