Class ShaderProgramManager
Defined in File ShaderProgramManager.h
Class Documentation
-
class ShaderProgramManager
Manages the lifecycle and caching of OpenGL shader programs.
This class centralizes shader program management for the entire rendering system. It provides:
Lazy loading: Shaders are compiled on first use
Caching: Each shader is compiled once and reused
Automatic cleanup: Programs are destroyed when manager is destroyed
Thread safety: All operations must be on the OpenGL context thread
Custom shader support: Load shaders from source code or files
The manager handles both built-in default shaders (from DefaultShaders.h) and user-defined custom shaders.
Typical usage:
ShaderProgramManager shaderMgr; // Get a built-in shader (compiled on first request): auto pointsShader = shaderMgr.getProgram(DefaultShaderID::POINTS); pointsShader->use(); // Load a custom shader: auto customShader = shaderMgr.loadCustomProgram( "myShader", vertexShaderSource, fragmentShaderSource);
Thread safety:
This class is NOT thread-safe
All operations must be called from the OpenGL context thread
Violating this will cause OpenGL errors or crashes
See also
Program, Shader, DefaultShaders.h, CompiledScene
Built-in Shader Access
-
Program::Ptr getProgram(shader_id_t id)
Retrieves a built-in shader program by ID.
If the shader hasn’t been compiled yet, it is compiled on first access. Subsequent calls return the cached program.
Note
This must be called from the OpenGL context thread
Note
The returned pointer remains valid as long as this manager exists
- Parameters:
id – The shader ID (from DefaultShaderID enum)
- Throws:
std::runtime_error – if shader compilation fails
- Returns:
Shared pointer to the program, or nullptr on compilation failure
-
bool hasProgram(shader_id_t id) const
Checks if a shader program has been compiled and cached.
- Parameters:
id – The shader ID to check
- Returns:
true if program exists in cache, false otherwise
-
void overrideBuiltinProgram(shader_id_t id, Program::Ptr program)
Replaces (or installs) a built-in shader slot with a custom compiled program.
Use this to override one of the standard MRPT shaders (e.g. DefaultShaderID::TRIANGLES_NO_LIGHT) with a custom Program you have compiled yourself. The new program will be used for all subsequent render calls that request id.
Note
Must be called from the OpenGL context thread.
-
size_t preloadAllDefaultShaders(std::vector<std::string> *outErrors = nullptr)
Preloads all default shaders.
By default, shaders are compiled lazily. Call this to compile all built-in shaders at initialization time, which can help avoid stuttering during first render.
Note
This can take 100-500ms depending on GPU/driver
- Parameters:
outErrors – Optional vector to receive compilation errors
- Returns:
Number of shaders successfully compiled
Custom Shader Management
-
Program::Ptr loadCustomProgram(const std::string &name, const std::string &vertexShaderSource, const std::string &fragmentShaderSource, const std::string &geometryShaderSource = "", std::string *outErrorMsg = nullptr)
Loads a custom shader program from source code.
The shader is compiled and linked immediately. If successful, it is cached and can be retrieved later by name.
Example:
const char* vertSrc = R"( #version 330 core layout(location = 0) in vec3 position; uniform mat4 pmv_matrix; void main() { gl_Position = pmv_matrix * vec4(position, 1.0); } )"; const char* fragSrc = R"( #version 330 core out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } )"; auto prog = shaderMgr.loadCustomProgram("redShader", vertSrc, fragSrc);
- Parameters:
name – Unique name for this custom shader
vertexShaderSource – GLSL source code for vertex shader
fragmentShaderSource – GLSL source code for fragment shader
geometryShaderSource – Optional GLSL source for geometry shader
outErrorMsg – Optional string to receive compilation/link errors
- Throws:
std::runtime_error – if name already exists
- Returns:
Shared pointer to program, or nullptr on failure
-
Program::Ptr loadCustomProgramFromFiles(const std::string &name, const std::string &vertexShaderFile, const std::string &fragmentShaderFile, const std::string &geometryShaderFile = "", std::string *outErrorMsg = nullptr)
Loads a custom shader program from files.
Convenience wrapper that reads shader source from files.
- Parameters:
name – Unique name for this custom shader
vertexShaderFile – Path to vertex shader (.vert, .vs, etc.)
fragmentShaderFile – Path to fragment shader (.frag, .fs, etc.)
geometryShaderFile – Optional path to geometry shader (.geom, .gs)
outErrorMsg – Optional string to receive errors
- Returns:
Shared pointer to program, or nullptr on failure
-
Program::Ptr getCustomProgram(const std::string &name) const
Retrieves a custom shader by name.
- Parameters:
name – The name given when loading the shader
- Returns:
Shared pointer to program, or nullptr if not found
-
bool hasCustomProgram(const std::string &name) const
Checks if a custom shader exists.
- Parameters:
name – The shader name to check
- Returns:
true if custom shader exists, false otherwise
-
bool removeCustomProgram(const std::string &name)
Removes a custom shader from the cache.
The program is destroyed if no other references exist.
- Parameters:
name – Name of shader to remove
- Returns:
true if shader was found and removed, false if not found
Shader Variants (for Shadow Mapping)
-
shader_id_t getShaderVariant(shader_id_t baseShaderID, bool isShadowMapPass) const
Retrieves the appropriate shader variant for the current render pass.
Shadow rendering requires different shaders for different passes:
1st pass (shadow map generation): depth-only shaders
2nd pass (normal rendering): shaders that sample shadow map
This method automatically selects the right variant based on the base shader ID and render pass.
Example mappings:
TRIANGLES_LIGHT + shadowMapPass=true → TRIANGLES_SHADOW_1ST
TRIANGLES_LIGHT + shadowMapPass=false → TRIANGLES_SHADOW_2ND
POINTS + shadowMapPass=true → NONE (points don’t cast shadows)
WIREFRAME + shadowMapPass=false → WIREFRAME (no shadow variant)
- Parameters:
baseShaderID – The base shader (e.g., TRIANGLES_LIGHT)
isShadowMapPass – true for 1st pass, false for 2nd pass
- Returns:
The appropriate shader variant
Utility Methods
-
void clear()
Clears all cached programs (built-in and custom).
Forces recompilation on next access. Useful for shader hot-reloading during development.
Warning
All existing Program::Ptr references become invalid
-
inline size_t getBuiltinProgramCount() const
Returns number of cached built-in programs
-
inline size_t getCustomProgramCount() const
Returns number of cached custom programs
-
inline size_t getTotalProgramCount() const
Returns total number of cached programs
-
std::vector<shader_id_t> getLoadedShaderIDs() const
Lists all loaded shader IDs (built-in).
- Returns:
Vector of shader IDs currently in cache
-
std::vector<std::string> getLoadedCustomShaderNames() const
Lists all loaded custom shader names.
- Returns:
Vector of custom shader names currently in cache
-
inline void setVerbose(bool verbose)
Enables/disables verbose logging of shader compilation.
When enabled, compilation success/failure is logged to stdout. Default: false
-
inline bool isVerbose() const
Returns current verbose setting
Public Functions
-
ShaderProgramManager()
Constructor.
Does not compile any shaders yet - they are loaded lazily on first use.
-
~ShaderProgramManager()
Destructor.
Automatically cleans up all shader programs. Must be called from the same thread that created the shaders (OpenGL context thread).
-
ShaderProgramManager(const ShaderProgramManager&) = delete
-
ShaderProgramManager &operator=(const ShaderProgramManager&) = delete
-
ShaderProgramManager(ShaderProgramManager&&) = delete
-
ShaderProgramManager &operator=(ShaderProgramManager&&) = delete