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...

template <typename THandle, typename TEntity>
voidclearColor (TEntity &entity) noexcept

ClearColor/Mask based on available components. 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 84 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 242 of file OpenGLBackend.ixx.

242 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 412 of file OpenGLBackend.ixx.

412 void beginMaterialBatch(MaterialHandle materialHandle) noexcept {
413 auto materialEntity = engineWorld_.find(materialHandle);
414 if (!materialEntity) {
415 logger_.error("MaterialEntity expected, but not found");
416 assert(false && "MaterialEntity not found");
417 return;
418 }
419
420 auto* colorComponent = materialEntity->template get<ColorComponent<MaterialHandle>>();
421 if (colorComponent) {
422 drawUniformValueBag_.set<MaterialBaseColorUniform>(colorComponent->value());
423 }
424
425 }

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 443 of file OpenGLBackend.ixx.

443 void beginMeshBatch(MeshHandle meshHandle) noexcept {
444
445 auto meshEntity = engineWorld_.find(meshHandle);
446 if (!meshEntity) {
447 logger_.error("MeshEntity expected, but not found");
448 assert(false && "MeshEntity not found");
449 return;
450 }
451
452 auto* openglMesh = meshEntity->template get<OpenGLMeshComponent<MeshHandle>>();
453 if (!openglMesh) {
454 logger_.error("OpenGLMesh expected, but not found");
455 assert(false && "OpenGLMesh not found");
456 return;
457 } else {
458 currentOpenGLMesh_ = openglMesh;
459 glBindVertexArray(openglMesh->vao);
460 }
461 }

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 253 of file OpenGLBackend.ixx.

253 void beginRenderTargetBatch(const RenderTargetHandle renderTargetHandle) noexcept {
254
255 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(renderTargetHandle);
256
257 #ifdef HELIOS_DEBUG
258 if (!renderTargetEntity) {
259 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetHandle.entityId);
260 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
261 }
262 #endif
263
264 currentRenderTargetHandle_ = renderTargetHandle;
265
266 const auto renderTargetId = renderTargetEntity->get<OpenGLRenderTargetIdComponent<RenderTargetHandle>>()->value();
267
268 glBindFramebuffer(GL_FRAMEBUFFER, renderTargetId);
269
270 #ifdef HELIOS_DEBUG
271 const auto isValidRenderTarget = renderTargetId == 0 ||
272 (glIsFramebuffer(renderTargetId) == GL_TRUE && glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
273 if (!isValidRenderTarget) {
274 logger_.error("RenderTargetEntity with EntityId {0} undefined.", renderTargetId);
275 assert(isValidRenderTarget && "RenderTargetEntity EntityId does not seem to be a valid id.");
276 }
277 #endif
278
279 auto renderTargetSize = renderTargetEntity->get<Size2DComponent<RenderTargetHandle>>()->value();
280
281 glViewport(0, 0,
282 static_cast<int>(renderTargetSize[0]),
283 static_cast<int>(renderTargetSize[1])
284 );
285
286 clearColor<RenderTargetHandle>(renderTargetEntity);
287
288 // this is equally important for the GlpyhTextRenderer
289 // enable blending since the font's fragment shader uses the alpha channel
290 glEnable(GL_BLEND);
291 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
292 }

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 374 of file OpenGLBackend.ixx.

374 void beginShaderBatch(ShaderHandle shaderHandle) noexcept {
375
376 auto shaderEntity = engineWorld_.find(shaderHandle);
377 if (!shaderEntity) {
378 logger_.error("ShaderEntity expected, but not found");
379 assert(false && "ShaderEntity not found");
380 return;
381 }
382
383 currentShaderHandle_ = shaderHandle;
384
385 auto* openglShader = shaderEntity->template get<OpenGLShaderComponent<ShaderHandle>>();
386 if (!openglShader) {
387 logger_.error("OpenGLShader expected, but not found");
388 assert(false && "OpenGLShader not found");
389 return;
390 }
391
392 glUseProgram(openglShader->programId);
393 writeUniformValues<UniformScope::Pass>(*shaderEntity, passUniformValueBag_);
394 }

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 316 of file OpenGLBackend.ixx.

316 void beginViewportBatch(const ViewportHandle viewportHandle) noexcept {
317
318 auto viewport = engineWorld_.find<ViewportHandle>(viewportHandle);
319 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(currentRenderTargetHandle_);
320
321 #ifdef HELIOS_DEBUG
322 if (!renderTargetEntity) {
323 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetEntity->handle().entityId);
324 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
325 }
326 if (!viewport) {
327 logger_.error("Missing Viewport for handle {0}.", viewportHandle.entityId);
328 assert(viewport && "Missing Viewport for handle.");
329 }
330 #endif
331
332 auto vp = viewProjection(*viewport);
333 if (!vp) {
334 logger_.warn("Could not determine View/Projection-matrices for RenderPass");
335 passUniformValueBag_.set<ProjectionMatrixUniform>(helios::math::mat4f{1.0f});
336 passUniformValueBag_.set<ViewMatrixUniform>(helios::math::mat4f{1.0f});
337 } else {
338 passUniformValueBag_.set<ProjectionMatrixUniform>(vp->projectionMatrix);
339 passUniformValueBag_.set<ViewMatrixUniform>(vp->viewMatrix);
340 }
341
342 auto viewportBounds = viewport->get<RectComponent<ViewportHandle>>()->value();
343 auto renderTargetSize = renderTargetEntity->get<Size2DComponent<RenderTargetHandle>>()->value();
344
345 const auto x = static_cast<int>(renderTargetSize[0] * viewportBounds[0]);
346 const auto y = static_cast<int>(renderTargetSize[1] * viewportBounds[1]);
347 const auto width = static_cast<int>(renderTargetSize[0] * viewportBounds[2]);
348 const auto height = static_cast<int>(renderTargetSize[1] * viewportBounds[3]);
349
350
351 glViewport(x, y, width, height);
352 glScissor(x, y, width, height);
353 glEnable(GL_SCISSOR_TEST);
354
355 clearColor<ViewportHandle>(viewport);
356 }

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 432 of file OpenGLBackend.ixx.

432 void endMaterialBatch(MaterialHandle handle) noexcept {
433 // intentionally left empty
434 }

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 468 of file OpenGLBackend.ixx.

468 void endMeshBatch(MeshHandle handle) noexcept {
469 currentOpenGLMesh_ = nullptr;
470 glBindVertexArray(0);
471 }

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 301 of file OpenGLBackend.ixx.

301 void endRenderTargetBatch(const RenderTargetHandle renderTargetHandle) noexcept {
302
303 currentRenderTargetHandle_ = RenderTargetHandle{};
304 passUniformValueBag_.clearValues();
305 drawUniformValueBag_.clearValues();
306 }

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 401 of file OpenGLBackend.ixx.

401 void endShaderBatch(ShaderHandle handle) noexcept {
402 currentShaderHandle_ = ShaderHandle{};
403 }

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 363 of file OpenGLBackend.ixx.

363 void endViewportBatch(const ViewportHandle viewportHandle) noexcept {
364 glDisable(GL_SCISSOR_TEST);
365 }

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 534 of file OpenGLBackend.ixx.

534 [[nodiscard]] bool init() noexcept {
535
536 assert(!isInitialized_ && "Backend already initialized");
537
538 const GLADloadfunc procAddressLoader = glfwGetProcAddress;
539 const int gl_ver = gladLoadGL(procAddressLoader);
540
541 if (gl_ver == 0) {
542 logger_.error("Failed to load OpenGL");
543 assert(false && "Failed to load OpenGL");
544 return false;
545 }
546
547 logger_.info("OpenGL {0}.{1} loaded", GLAD_VERSION_MAJOR(gl_ver), GLAD_VERSION_MINOR(gl_ver));
548
549 isInitialized_ = true;
550 return true;
551
552 }

isInitialized()

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

Reports whether OpenGL function loading completed successfully.

Definition at line 557 of file OpenGLBackend.ixx.

557 [[nodiscard]] bool isInitialized() const noexcept {
558 return isInitialized_;
559 }

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 519 of file OpenGLBackend.ixx.

519 void provideWindowHints() noexcept {
520
521 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
522 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
523 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
524
525 }

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 483 of file OpenGLBackend.ixx.

483 void renderBatch(std::span<SceneMemberRenderContext<THandle>> sceneMemberRenderContexts) noexcept {
484
485 if (!currentOpenGLMesh_) {
486 logger_.error("OpenGLMesh expected, but not available");
487 return;
488 }
489 if (!currentShaderHandle_.isValid()) {
490 logger_.error("Expected valid currentShaderHandle_, but found {0}.", currentShaderHandle_.entityId);
491 return;
492 }
493
494 auto shaderEntity = engineWorld_.find(currentShaderHandle_);
495
496 assert(shaderEntity && "ShaderEntity expected, but not found");
497 assert(currentOpenGLMesh_ && "Current OpenGL mesh expected, but not found");
498
499 for (auto& renderContext : sceneMemberRenderContexts) {
500
501 drawUniformValueBag_.set<ModelMatrixUniform>(renderContext.worldMatrix);
502 writeUniformValues<UniformScope::Draw>(*shaderEntity, drawUniformValueBag_);
503 glDrawElements(
504 currentOpenGLMesh_->primitiveType,
505 currentOpenGLMesh_->indexCount,
506 GL_UNSIGNED_INT,
507 nullptr
508 );
509
510 }
511 }

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

Private Member Functions

clearColor()

template <typename THandle, typename TEntity>
void helios::opengl::OpenGLBackend::clearColor (TEntity & entity)
inline noexcept

ClearColor/Mask based on available components.

Template Parameters
THandle
TEntity
Parameters
entity

Definition at line 210 of file OpenGLBackend.ixx.

210 void clearColor(TEntity& entity) noexcept {
211
212 auto* colorComp = entity->template get<ColorComponent<THandle>>();
213 auto* clearComp = entity->template get<ClearComponent<THandle>>();
214
215 if (colorComp) {
216 const auto clearColor = colorComp->value();
217 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
218 }
219
220 if (clearComp) {
221 const auto clearFlags = std::to_underlying(clearComp->flags);
222 const auto clearMask = ((clearFlags & std::to_underlying(ClearFlags::Color)) ? GL_COLOR_BUFFER_BIT : 0) |
223 ((clearFlags & std::to_underlying(ClearFlags::Depth)) ? GL_DEPTH_BUFFER_BIT : 0) |
224 ((clearFlags & std::to_underlying(ClearFlags::Stencil)) ? GL_STENCIL_BUFFER_BIT : 0);
225
226 if (clearMask != 0) {
227 glClear(clearMask);
228 }
229 }
230 }

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 143 of file OpenGLBackend.ixx.

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

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 187 of file OpenGLBackend.ixx.

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

Private Member Attributes

currentOpenGLMesh_

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

Cached pointer to the currently bound OpenGL mesh component.

Definition at line 100 of file OpenGLBackend.ixx.

100 OpenGLMeshComponent<MeshHandle>* currentOpenGLMesh_ = nullptr;

currentRenderTargetHandle_

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

Currently active render target for nested viewport processing.

Definition at line 115 of file OpenGLBackend.ixx.

115 RenderTargetHandle currentRenderTargetHandle_{};

currentShaderHandle_

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

Currently bound shader to avoid redundant glUseProgram calls.

Definition at line 120 of file OpenGLBackend.ixx.

120 ShaderHandle currentShaderHandle_{};

drawUniformValueBag_

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

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

Definition at line 110 of file OpenGLBackend.ixx.

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

engineWorld_

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

Engine world used to resolve render entities and components.

Definition at line 126 of file OpenGLBackend.ixx.

126 EngineWorld& engineWorld_;

isInitialized_

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

Tracks whether GL function pointers were initialized.

Definition at line 91 of file OpenGLBackend.ixx.

91 bool isInitialized_ = false;

passUniformValueBag_

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

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

Definition at line 105 of file OpenGLBackend.ixx.

105 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 93 of file OpenGLBackend.ixx.

93 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.