Skip to main content

OpenGLMeshRenderer.ixx File

OpenGL implementation of the MeshRenderer interface for rendering mesh geometry. More...

Included Headers

#include <cassert> #include <glad/gl.h> #include <ostream> #include <ranges> #include <helios.ext.opengl.rendering.model> #include <helios.ext.opengl.rendering.shader> #include <helios.ext.opengl.rendering.OpenGLEnumMapper> #include <helios.rendering>

Namespaces Index

namespacehelios
namespaceext

Platform-specific extensions and backend implementations. More...

namespaceopengl

OpenGL-specific implementations. More...

namespacerendering

OpenGL rendering implementations. More...

Classes Index

classOpenGLMeshRenderer

OpenGL implementation of the MeshRenderer interface. More...

Description

OpenGL implementation of the MeshRenderer interface for rendering mesh geometry.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file OpenGLMeshRenderer.ixx
3 * @brief OpenGL implementation of the MeshRenderer interface for rendering mesh geometry.
4 */
5module;
6
7#include <cassert>
8#include <glad/gl.h>
9#include <ostream>
10#include <ranges>
11
12
13
14export module helios.ext.opengl.rendering.OpenGLMeshRenderer;
15
16import helios.rendering;
17import helios.ext.opengl.rendering.OpenGLEnumMapper;
18import helios.ext.opengl.rendering.shader;
19import helios.ext.opengl.rendering.model;
20
21
22export namespace helios::ext::opengl::rendering {
23
24
25 /**
26 * @brief OpenGL implementation of the MeshRenderer interface.
27 *
28 * `OpenGLMeshRenderer` provides the concrete rendering logic for mesh geometry using
29 * the OpenGL graphics API. It translates abstract `MeshRenderCommand` objects into
30 * OpenGL-specific draw calls, handling shader binding, uniform application, and
31 * VAO state management.
32 *
33 * ## State Caching
34 *
35 * This class implements state caching to minimize redundant OpenGL state changes:
36 * - Shader programs are only activated when they differ from the previously used shader.
37 * - VAO bindings are only updated when rendering a mesh with a different VAO.
38 *
39 * ## Usage
40 *
41 * ```cpp
42 * OpenGLMeshRenderer renderer;
43 * MeshRenderCommand command = createRenderCommand();
44 * UniformValueMap frameUniforms = {{"viewMatrix", viewMat}, {"projMatrix", projMat}};
45 * renderer.render(command, frameUniforms);
46 * ```
47 *
48 * ## Ownership
49 *
50 * This class is typically owned by `OpenGLDevice` and should not be instantiated
51 * directly in most use cases.
52 *
53 * @note The renderer expects all shaders and meshes to be OpenGL-specific implementations
54 * (`OpenGLShader` and `OpenGLMesh`). Using incompatible types will trigger assertions.
55 *
56 * @see helios::rendering::mesh::MeshRenderer
57 * @see helios::rendering::mesh::MeshRenderCommand
58 * @see OpenGLDevice
59 */
61
62
63
64 friend class OpenGLDevice;
65
66 /**
67 * @brief Cached pointer to the last used shader for state optimization.
68 *
69 * Used to avoid redundant shader program activations. Reset at the beginning
70 * of each render pass.
71 */
72 mutable const helios::ext::opengl::rendering::shader::OpenGLShader* lastShader_ = nullptr;
73
74 /**
75 * @brief Cached VAO ID for state optimization.
76 *
77 * Used to avoid redundant VAO bindings. Reset at the beginning of each render pass.
78 */
79 mutable unsigned int lastVao_ = 0;
80
81 /**
82 * @brief Initializes the renderer.
83 *
84 * Currently a no-op placeholder for future initialization logic.
85 */
86 void init() {
87
88 }
89
90
91 /**
92 * @brief Resets cached rendering state at the beginning of a render pass.
93 *
94 * This ensures proper shader and VAO binding even when the render queue
95 * contents change between frames. Called internally by `OpenGLDevice` before
96 * processing the render queue.
97 *
98 * @param renderPass The render pass being started (currently unused, reserved for future use).
99 */
100 void beginRenderPass(helios::rendering::RenderPass& renderPass) const noexcept {
101 // Reset cached state at the beginning of each render pass
102 // to ensure proper shader and VAO binding even when render queue contents change
103
104 lastShader_ = nullptr;
105 lastVao_ = 0;
106 }
107
108 public:
109
110
111 /**
112 * @brief Destructor that unbinds any currently bound VAO.
113 *
114 * Ensures clean OpenGL state upon destruction.
115 */
117
118 glBindVertexArray(0);
119 }
120
121
122 /**
123 * @brief Renders a mesh using the provided render command and frame-level uniforms.
124 *
125 * This method performs the following steps:
126 * 1 Extracts the shader and mesh from the render command's prototype.
127 * 2 Activates the shader if it differs from the previously used shader (state caching).
128 * 3 Applies frame-level, object-level, and material-level uniform values.
129 * 4 Binds the mesh's VAO if it differs from the previously bound VAO (state caching).
130 * 5 Issues a `glDrawElements` call with the appropriate primitive type.
131 *
132 * @param command The render command containing the render prototype with mesh,
133 * material, and per-object uniform data.
134 * @param frameUniformValues Frame-level uniform values shared across all objects
135 * (e.g., view and projection matrices).
136 *
137 * @note If the render command does not contain a valid render prototype, the
138 * method returns without issuing any draw calls.
139 *
140 * @see MeshRenderCommand
141 * @see UniformValueMap
142 */
143 void render(
145 const helios::rendering::shader::UniformValueMap& frameUniformValues) noexcept {
146
147 if (const auto renderPrototype_ptr = command.renderPrototype()) {
148 const auto& baseShader = renderPrototype_ptr->material().shader();
149 const auto& baseMesh = renderPrototype_ptr->mesh();
150
151 const auto* shader = static_cast<const helios::ext::opengl::rendering::shader::OpenGLShader*>(&baseShader);
152 assert(shader && "Unexpected failure when casting to OpenGLShader.");
153
154 if (shader != lastShader_) {
155 shader->use();
156 lastShader_ = shader;
157 }
158
159 shader->applyUniformValues(frameUniformValues);
160 shader->applyUniformValues(command.objectUniformValues());
161 shader->applyUniformValues(command.materialUniformValues());
162
163 const auto* mesh = static_cast<const helios::ext::opengl::rendering::model::OpenGLMesh*>(&baseMesh);
164 assert(mesh && "Unexpected failure when casting to OpenGLMesh.");
165
166 const auto [primitiveType] = mesh->meshConfig();
167
168 if (mesh->vao() != lastVao_) {
169 glBindVertexArray(mesh->vao());
170 lastVao_ = mesh->vao();
171 }
172
173 glDrawElements(helios::ext::opengl::rendering::OpenGLEnumMapper::toOpenGL(primitiveType), mesh->indexCount(), GL_UNSIGNED_INT, nullptr);
174 }
175
176 };
177
178
179
180
181 };
182}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.