Skip to main content

OpenGLBackend Class

Applies render-pass state and executes OpenGL draw calls. More...

Declaration

class helios::opengl::OpenGLBackend { ... }

Public Constructors Index

OpenGLBackend (EngineWorld &engineWorld)

Constructs the backend bound to the engine world. More...

Public Member Functions Index

voidbeginRenderTargetBatch (const RenderTargetHandle renderTargetHandle) noexcept

Begins processing for one render-target batch. More...

voidendRenderTargetBatch (const RenderTargetHandle renderTargetHandle) noexcept

Ends processing for one render-target batch. More...

voidbeginViewportBatch (const ViewportHandle viewportHandle) noexcept

Begins processing for one viewport batch. More...

voidendViewportBatch (const ViewportHandle viewportHandle) noexcept

Ends processing for one viewport batch. More...

voidbeginShaderBatch (ShaderHandle shaderHandle) noexcept

Begins processing for one shader batch. More...

voidendShaderBatch (ShaderHandle handle) noexcept

Ends processing for one shader batch. More...

voidbeginMaterialBatch (MaterialHandle materialHandle) noexcept

Begins processing for one material batch. More...

voidendMaterialBatch (MaterialHandle handle) noexcept

Ends processing for one material batch. More...

voidbeginMeshBatch (MeshHandle meshHandle) noexcept

Begins processing for one mesh batch. More...

voidendMeshBatch (MeshHandle handle) noexcept

Ends processing for one mesh batch. More...

template <typename THandle>
voidrenderBatch (std::span< SceneMemberRenderContext< THandle > > sceneMemberRenderContexts) noexcept

Renders all draw contexts of the current mesh batch. More...

voidprovideWindowHints () noexcept

Applies window hints for an OpenGL core-profile context. More...

boolinit () noexcept

Initializes OpenGL function pointers through GLFW. More...

boolisInitialized () const noexcept

Reports whether OpenGL function loading completed successfully. More...

Private Member Functions Index

std::optional< ViewProjection >viewProjection (const ViewportEntity &vieportEntity) const noexcept

Resolves view and projection matrices for a viewport's bound camera. More...

template <typename TUniformScope>
voidwriteUniformValues (ShaderEntity shaderEntity, UniformValueBag< TUniformScope > &uniformValueBag) noexcept

Uploads cached uniform values for a specific uniform scope. More...

Private Member Attributes Index

boolisInitialized_ = false

Tracks whether GL function pointers were initialized. More...

OpenGLMeshComponent< MeshHandle > *currentOpenGLMesh_ = nullptr

Cached pointer to the currently bound OpenGL mesh component. More...

UniformValueBag< UniformScope::Pass >passUniformValueBag_ {}

Cached pass-scope uniforms (typically view/projection). More...

UniformValueBag< UniformScope::Draw >drawUniformValueBag_ {}

Cached draw-scope uniforms (for example model matrix/material color). More...

RenderTargetHandlecurrentRenderTargetHandle_ {}

Currently active render target for nested viewport processing. More...

ShaderHandlecurrentShaderHandle_ {}

Currently bound shader to avoid redundant glUseProgram calls. More...

EngineWorld &engineWorld_

Engine world used to resolve render entities and components. More...

Private Static Attributes Index

static const helios::engine::util::log::Logger &logger_ = ...

Description

Applies render-pass state and executes OpenGL draw calls.

OpenGLBackend is intentionally thin and stateful: it references existing worlds and translates ECS render data into OpenGL state changes.

Definition at line 87 of file OpenGLBackend.ixx.

Public Constructors

OpenGLBackend()

helios::opengl::OpenGLBackend::OpenGLBackend (EngineWorld & engineWorld)
inline explicit

Constructs the backend bound to the engine world.

Parameters
engineWorld

Engine world providing render resources and targets.

Definition at line 213 of file OpenGLBackend.ixx.

213 explicit OpenGLBackend(EngineWorld& engineWorld) : engineWorld_(engineWorld){}

Public Member Functions

beginMaterialBatch()

void helios::opengl::OpenGLBackend::beginMaterialBatch (MaterialHandle materialHandle)
inline noexcept

Begins processing for one material batch.

Loads material-scope values (for example base color) into draw-scope uniforms.

Parameters
materialHandle

Material handle for this batch.

Definition at line 384 of file OpenGLBackend.ixx.

384 void beginMaterialBatch(MaterialHandle materialHandle) noexcept {
385 auto materialEntity = engineWorld_.find(materialHandle);
386 if (!materialEntity) {
387 logger_.error("MaterialEntity expected, but not found");
388 assert(false && "MaterialEntity not found");
389 return;
390 }
391
392 auto* colorComponent = materialEntity->template get<ColorComponent<MaterialHandle>>();
393 if (colorComponent) {
394 drawUniformValueBag_.set<MaterialBaseColorUniform>(colorComponent->value());
395 }
396
397 }

beginMeshBatch()

void helios::opengl::OpenGLBackend::beginMeshBatch (MeshHandle meshHandle)
inline noexcept

Begins processing for one mesh batch.

Resolves and binds the mesh VAO used for all draw contexts in the batch.

Parameters
meshHandle

Mesh handle for this batch.

Definition at line 415 of file OpenGLBackend.ixx.

415 void beginMeshBatch(MeshHandle meshHandle) noexcept {
416
417 auto meshEntity = engineWorld_.find(meshHandle);
418 if (!meshEntity) {
419 logger_.error("MeshEntity expected, but not found");
420 assert(false && "MeshEntity not found");
421 return;
422 }
423
424 auto* openglMesh = meshEntity->template get<OpenGLMeshComponent<MeshHandle>>();
425 if (!openglMesh) {
426 logger_.error("OpenGLMesh expected, but not found");
427 assert(false && "OpenGLMesh not found");
428 return;
429 } else {
430 currentOpenGLMesh_ = openglMesh;
431 glBindVertexArray(openglMesh->vao);
432 }
433 }

beginRenderTargetBatch()

void helios::opengl::OpenGLBackend::beginRenderTargetBatch (const RenderTargetHandle renderTargetHandle)
inline noexcept

Begins processing for one render-target batch.

Binds the framebuffer, validates it in debug builds, and initializes pass-independent GL state such as blending and clear color.

Parameters
renderTargetHandle

Render-target handle for this batch.

Definition at line 224 of file OpenGLBackend.ixx.

224 void beginRenderTargetBatch(const RenderTargetHandle renderTargetHandle) noexcept {
225
226 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(renderTargetHandle);
227
228 #ifdef HELIOS_DEBUG
229 if (!renderTargetEntity) {
230 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetHandle.entityId);
231 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
232 }
233 #endif
234
235 currentRenderTargetHandle_ = renderTargetHandle;
236
237 const auto renderTargetId = renderTargetEntity->get<OpenGLRenderTargetIdComponent<RenderTargetHandle>>()->value();
238
239 glBindFramebuffer(GL_FRAMEBUFFER, renderTargetId);
240
241 #ifdef HELIOS_DEBUG
242 const auto isValidRenderTarget = renderTargetId == 0 ||
243 (glIsFramebuffer(renderTargetId) == GL_TRUE && glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
244 if (!isValidRenderTarget) {
245 logger_.error("RenderTargetEntity with EntityId {0} undefined.", renderTargetId);
246 assert(isValidRenderTarget && "RenderTargetEntity EntityId does not seem to be a valid id.");
247 }
248 #endif
249
250 // this is equally important for the GlpyhTextRenderer
251 // enable blending since the font's fragment shader uses the alpha channel
252 glEnable(GL_BLEND);
253 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
254
255 const auto clearColor = renderTargetEntity->get<ColorComponent<RenderTargetHandle>>()->value();
256 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
257 }

beginShaderBatch()

void helios::opengl::OpenGLBackend::beginShaderBatch (ShaderHandle shaderHandle)
inline noexcept

Begins processing for one shader batch.

Binds the shader program and uploads pass-scope uniforms.

Parameters
shaderHandle

Shader handle for this batch.

Definition at line 346 of file OpenGLBackend.ixx.

346 void beginShaderBatch(ShaderHandle shaderHandle) noexcept {
347
348 auto shaderEntity = engineWorld_.find(shaderHandle);
349 if (!shaderEntity) {
350 logger_.error("ShaderEntity expected, but not found");
351 assert(false && "ShaderEntity not found");
352 return;
353 }
354
355 currentShaderHandle_ = shaderHandle;
356
357 auto* openglShader = shaderEntity->template get<OpenGLShaderComponent<ShaderHandle>>();
358 if (!openglShader) {
359 logger_.error("OpenGLShader expected, but not found");
360 assert(false && "OpenGLShader not found");
361 return;
362 }
363
364 glUseProgram(openglShader->programId);
365 writeUniformValues<UniformScope::Pass>(*shaderEntity, passUniformValueBag_);
366 }

beginViewportBatch()

void helios::opengl::OpenGLBackend::beginViewportBatch (const ViewportHandle viewportHandle)
inline noexcept

Begins processing for one viewport batch.

Resolves camera matrices, configures viewport/scissor rectangles, and performs optional clears according to the active render target clear flags.

Parameters
viewportHandle

Viewport handle for this batch.

Definition at line 281 of file OpenGLBackend.ixx.

281 void beginViewportBatch(const ViewportHandle viewportHandle) noexcept {
282
283 auto viewport = engineWorld_.find<ViewportHandle>(viewportHandle);
284 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(currentRenderTargetHandle_);
285
286 #ifdef HELIOS_DEBUG
287 if (!renderTargetEntity) {
288 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetEntity->handle().entityId);
289 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
290 }
291 if (!viewport) {
292 logger_.error("Missing Viewport for handle {0}.", viewportHandle.entityId);
293 assert(viewport && "Missing Viewport for handle.");
294 }
295 #endif
296
297 auto vp = viewProjection(*viewport);
298 if (!vp) {
299 logger_.warn("Could not determine View/Projection-matrices for RenderPass");
300 passUniformValueBag_.set<ProjectionMatrixUniform>(helios::math::mat4f{1.0f});
301 passUniformValueBag_.set<ViewMatrixUniform>(helios::math::mat4f{1.0f});
302 } else {
303 passUniformValueBag_.set<ProjectionMatrixUniform>(vp->projectionMatrix);
304 passUniformValueBag_.set<ViewMatrixUniform>(vp->viewMatrix);
305 }
306
307 auto viewportBounds = viewport->get<BoundsComponent<ViewportHandle>>()->value();
308 auto renderTargetSize = renderTargetEntity->get<Size2DComponent<RenderTargetHandle>>()->value();
309
310 const auto x = static_cast<int>(renderTargetSize[0] * viewportBounds[0]);
311 const auto y = static_cast<int>(renderTargetSize[1] * viewportBounds[1]);
312 const auto width = static_cast<int>(renderTargetSize[0] * viewportBounds[2]);
313 const auto height = static_cast<int>(renderTargetSize[1] * viewportBounds[3]);
314
315
316 glViewport(x, y, width, height);
317 glScissor(x, y, width, height);
318 glEnable(GL_SCISSOR_TEST);
319
320 const auto clearFlags = std::to_underlying(renderTargetEntity->get<ClearComponent<RenderTargetHandle>>()->flags);
321 const auto clearMask = ((clearFlags & std::to_underlying(ClearFlags::Color)) ? GL_COLOR_BUFFER_BIT : 0) |
322 ((clearFlags & std::to_underlying(ClearFlags::Depth)) ? GL_DEPTH_BUFFER_BIT : 0) |
323 ((clearFlags & std::to_underlying(ClearFlags::Stencil)) ? GL_STENCIL_BUFFER_BIT : 0);
324
325 if (clearMask != 0) {
326 glClear(clearMask);
327 }
328 }

endMaterialBatch()

void helios::opengl::OpenGLBackend::endMaterialBatch (MaterialHandle handle)
inline noexcept

Ends processing for one material batch.

Parameters
handle

Material handle for this batch.

Definition at line 404 of file OpenGLBackend.ixx.

404 void endMaterialBatch(MaterialHandle handle) noexcept {
405 // intentionally left empty
406 }

endMeshBatch()

void helios::opengl::OpenGLBackend::endMeshBatch (MeshHandle handle)
inline noexcept

Ends processing for one mesh batch.

Parameters
handle

Mesh handle for this batch.

Definition at line 440 of file OpenGLBackend.ixx.

440 void endMeshBatch(MeshHandle handle) noexcept {
441 currentOpenGLMesh_ = nullptr;
442 glBindVertexArray(0);
443 }

endRenderTargetBatch()

void helios::opengl::OpenGLBackend::endRenderTargetBatch (const RenderTargetHandle renderTargetHandle)
inline noexcept

Ends processing for one render-target batch.

Clears current render-target state and resets cached pass/draw uniform values.

Parameters
renderTargetHandle

Render-target handle for this batch.

Definition at line 266 of file OpenGLBackend.ixx.

266 void endRenderTargetBatch(const RenderTargetHandle renderTargetHandle) noexcept {
267
268 currentRenderTargetHandle_ = RenderTargetHandle{};
269 passUniformValueBag_.clearValues();
270 drawUniformValueBag_.clearValues();
271 }

endShaderBatch()

void helios::opengl::OpenGLBackend::endShaderBatch (ShaderHandle handle)
inline noexcept

Ends processing for one shader batch.

Parameters
handle

Shader handle for this batch.

Definition at line 373 of file OpenGLBackend.ixx.

373 void endShaderBatch(ShaderHandle handle) noexcept {
374 currentShaderHandle_ = ShaderHandle{};
375 }

endViewportBatch()

void helios::opengl::OpenGLBackend::endViewportBatch (const ViewportHandle viewportHandle)
inline noexcept

Ends processing for one viewport batch.

Parameters
viewportHandle

Viewport handle for this batch.

Definition at line 335 of file OpenGLBackend.ixx.

335 void endViewportBatch(const ViewportHandle viewportHandle) noexcept {
336 glDisable(GL_SCISSOR_TEST);
337 }

init()

bool helios::opengl::OpenGLBackend::init ()
inline noexcept

Initializes OpenGL function pointers through GLFW.

Precondition

A valid, current OpenGL context exists on the calling thread.

Postcondition

isInitialized() returns true on success.

Returns

true if loading succeeded, otherwise false.

Definition at line 506 of file OpenGLBackend.ixx.

506 [[nodiscard]] bool init() noexcept {
507
508 assert(!isInitialized_ && "Backend already initialized");
509
510 const GLADloadfunc procAddressLoader = glfwGetProcAddress;
511 const int gl_ver = gladLoadGL(procAddressLoader);
512
513 if (gl_ver == 0) {
514 logger_.error("Failed to load OpenGL");
515 assert(false && "Failed to load OpenGL");
516 return false;
517 }
518
519 logger_.info("OpenGL {0}.{1} loaded", GLAD_VERSION_MAJOR(gl_ver), GLAD_VERSION_MINOR(gl_ver));
520
521 isInitialized_ = true;
522 return true;
523
524 }

isInitialized()

bool helios::opengl::OpenGLBackend::isInitialized ()
inline noexcept

Reports whether OpenGL function loading completed successfully.

Definition at line 529 of file OpenGLBackend.ixx.

529 [[nodiscard]] bool isInitialized() const noexcept {
530 return isInitialized_;
531 }

provideWindowHints()

void helios::opengl::OpenGLBackend::provideWindowHints ()
inline noexcept

Applies window hints for an OpenGL core-profile context.

The backend currently requests OpenGL 4.1 core profile for macOS compatibility.

Definition at line 491 of file OpenGLBackend.ixx.

491 void provideWindowHints() noexcept {
492
493 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
494 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
495 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
496
497 }

renderBatch()

template <typename THandle>
void helios::opengl::OpenGLBackend::renderBatch (std::span< SceneMemberRenderContext< THandle > > sceneMemberRenderContexts)
inline noexcept

Renders all draw contexts of the current mesh batch.

Writes draw-scope uniforms per context and submits one indexed glDrawElements call per entry.

Template Parameters
THandle

Scene member handle type.

Parameters
sceneMemberRenderContexts

Draw contexts belonging to the active mesh batch.

Definition at line 455 of file OpenGLBackend.ixx.

455 void renderBatch(std::span<SceneMemberRenderContext<THandle>> sceneMemberRenderContexts) noexcept {
456
457 if (!currentOpenGLMesh_) {
458 logger_.error("OpenGLMesh expected, but not available");
459 return;
460 }
461 if (!currentShaderHandle_.isValid()) {
462 logger_.error("Expected valid currentShaderHandle_, but found {0}.", currentShaderHandle_.entityId);
463 return;
464 }
465
466 auto shaderEntity = engineWorld_.find(currentShaderHandle_);
467
468 assert(shaderEntity && "ShaderEntity expected, but not found");
469 assert(currentOpenGLMesh_ && "Current OpenGL mesh expected, but not found");
470
471 for (auto& renderContext : sceneMemberRenderContexts) {
472
473 drawUniformValueBag_.set<ModelMatrixUniform>(renderContext.worldMatrix);
474 writeUniformValues<UniformScope::Draw>(*shaderEntity, drawUniformValueBag_);
475 glDrawElements(
476 currentOpenGLMesh_->primitiveType,
477 currentOpenGLMesh_->indexCount,
478 GL_UNSIGNED_INT,
479 nullptr
480 );
481
482 }
483 }

References helios::opengl::components::OpenGLMeshComponent< TOwnerHandle >::indexCount and helios::opengl::components::OpenGLMeshComponent< TOwnerHandle >::primitiveType.

Private Member Functions

viewProjection()

std::optional< ViewProjection > helios::opengl::OpenGLBackend::viewProjection (const ViewportEntity & vieportEntity)
inline noexcept

Resolves view and projection matrices for a viewport's bound camera.

Parameters
updateContext

Current frame update context.

viewportHandle

Viewport to resolve camera matrices for.

Returns

View/projection pair on success, otherwise std::nullopt.

Definition at line 146 of file OpenGLBackend.ixx.

146 [[nodiscard]] std::optional<ViewProjection> viewProjection(const ViewportEntity& vieportEntity) const noexcept {
147
148 auto* cbc = vieportEntity.get<CameraBindingComponent<ViewportHandle>>();
149 if (!cbc) {
150 logger_.error("Expected CameraBindingComponent on ViewportEntity, but couldn't find any.");
151 return std::nullopt;
152 }
153 auto camera = engineWorld_.find(cbc->targetHandle());
154 if (!camera) {
155 logger_.error("Expected CameraEntity, but couldn't find any.");
156 return std::nullopt;
157 }
158 using CameryHandleType = std::remove_cvref_t<decltype(cbc->targetHandle())>;
159 auto* vm = camera->get<ViewMatrixComponent<CameryHandleType>>();
160 if (!vm) {
161 logger_.error("Expected ViewMatrixComponent, but couldn't find any.");
162 return std::nullopt;
163 }
164
165 auto* pm = camera->get<ProjectionMatrixComponent<CameryHandleType>>();
166 if (!pm) {
167 logger_.error("Expected ProjectionMatrixComponent, but couldn't find any.");
168 return std::nullopt;
169 }
170
171 return ViewProjection{
172 vm->value(), pm->value()
173 };
174
175 }

writeUniformValues()

template <typename TUniformScope>
void helios::opengl::OpenGLBackend::writeUniformValues (ShaderEntity shaderEntity, UniformValueBag< TUniformScope > & uniformValueBag)
inline noexcept

Uploads cached uniform values for a specific uniform scope.

Resolves OpenGLUniformWriteOperationsComponent<ShaderHandle, TUniformScope> on the shader entity and forwards its operation list plus values from UniformValueBag to OpenGLUniformWriter. If no write-plan component exists, the method logs an error and asserts in debug builds.

Template Parameters
TUniformScope

Uniform lifetime scope (for example pass or draw).

Parameters
shaderEntity

Shader entity holding location cache and shader data.

uniformValueBag

Source values to upload for this scope.

Definition at line 190 of file OpenGLBackend.ixx.

190 void writeUniformValues(ShaderEntity shaderEntity, UniformValueBag<TUniformScope>& uniformValueBag) noexcept {
191
193
194 if (!ulc) {
195 logger_.error("OpenGLUniformWritePlanComponent<{0}> expected, but not found", typeid(TUniformScope).name());
196 assert(false && "OpenGLUniformWritePlanComponent not found");
197 return;
198 }
199
200 OpenGLUniformWriter::write(ulc->operations, uniformValueBag);
201 }

Private Member Attributes

currentOpenGLMesh_

OpenGLMeshComponent<MeshHandle>* helios::opengl::OpenGLBackend::currentOpenGLMesh_ = nullptr

Cached pointer to the currently bound OpenGL mesh component.

Definition at line 103 of file OpenGLBackend.ixx.

103 OpenGLMeshComponent<MeshHandle>* currentOpenGLMesh_ = nullptr;

currentRenderTargetHandle_

RenderTargetHandle helios::opengl::OpenGLBackend::currentRenderTargetHandle_ {}

Currently active render target for nested viewport processing.

Definition at line 118 of file OpenGLBackend.ixx.

118 RenderTargetHandle currentRenderTargetHandle_{};

currentShaderHandle_

ShaderHandle helios::opengl::OpenGLBackend::currentShaderHandle_ {}

Currently bound shader to avoid redundant glUseProgram calls.

Definition at line 123 of file OpenGLBackend.ixx.

123 ShaderHandle currentShaderHandle_{};

drawUniformValueBag_

UniformValueBag<UniformScope::Draw> helios::opengl::OpenGLBackend::drawUniformValueBag_ {}

Cached draw-scope uniforms (for example model matrix/material color).

Definition at line 113 of file OpenGLBackend.ixx.

113 UniformValueBag<UniformScope::Draw> drawUniformValueBag_{};

engineWorld_

EngineWorld& helios::opengl::OpenGLBackend::engineWorld_

Engine world used to resolve render entities and components.

Definition at line 129 of file OpenGLBackend.ixx.

129 EngineWorld& engineWorld_;

isInitialized_

bool helios::opengl::OpenGLBackend::isInitialized_ = false

Tracks whether GL function pointers were initialized.

Definition at line 94 of file OpenGLBackend.ixx.

94 bool isInitialized_ = false;

passUniformValueBag_

UniformValueBag<UniformScope::Pass> helios::opengl::OpenGLBackend::passUniformValueBag_ {}

Cached pass-scope uniforms (typically view/projection).

Definition at line 108 of file OpenGLBackend.ixx.

108 UniformValueBag<UniformScope::Pass> passUniformValueBag_{};

Private Static Attributes

logger_

const helios::engine::util::log::Logger& helios::opengl::OpenGLBackend::logger_
static
Initialiser
= helios::engine::util::log::LogManager::loggerForScope( HELIOS_LOG_SCOPE )

Definition at line 96 of file OpenGLBackend.ixx.

96 inline static const helios::engine::util::log::Logger& logger_ = helios::engine::util::log::LogManager::loggerForScope(

The documentation for this class was generated from the following file:


Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.