OpenGL backend for render-pass execution and indexed draw submission. More...
#include <glad/gl.h>
#include <GLFW/glfw3.h>
#include <memory>
#include <cassert>
#include <utility>
#include <type_traits>
#include <span>
#include "
helios-opengl-config.h"
#include <optional>
#include <helios.engine.runtime.world.EngineWorld>
#include <
helios.opengl.types>
#include <helios.engine.scene.components>
#include <helios.engine.util.Colors>
#include <helios.math>
#include <helios.engine.rendering.common.types>
#include <helios.engine.rendering.viewport>
#include <helios.engine.rendering.material>
#include <helios.engine.util.log>
#include <helios.engine.rendering.viewport.ViewportEntity>
#include <
helios.opengl.OpenGLUniformWriter>
#include <
helios.opengl.components>
#include <helios.engine.rendering.mesh>
#include <helios.engine.rendering.renderTarget.RenderTargetEntity>
#include <helios.engine.rendering.common.components>
#include <helios.engine.rendering.renderTarget>
#include <helios.engine.spatial.components>
#include <helios.engine.core.components>
#include <helios.engine.scene.types>
#include <helios.engine.rendering.shader>
Namespaces Index
| namespace | helios |
|
|
|
| namespace | opengl |
|
|
|
| namespace | rendering |
|
|
|
| namespace | components |
|
|
|
| namespace | shader |
|
|
|
| namespace | components |
|
|
|
| namespace | types |
|
|
|
| namespace | types |
|
|
|
| namespace | components |
|
|
|
| namespace | components |
|
|
|
| namespace | renderTarget |
|
|
|
| namespace | types |
|
|
|
| namespace | viewport |
|
|
|
| namespace | types |
|
|
|
| namespace | components |
|
|
|
| namespace | types |
|
|
|
| namespace | world |
|
|
|
| namespace | log |
|
|
|
Classes Index
Macro Definitions Index
Description
OpenGL backend for render-pass execution and indexed draw submission.
Macro Definitions
HELIOS_LOG_SCOPE
| #define HELIOS_LOG_SCOPE "helios::opengl" |
|
File Listing
The file content with the documentation metadata removed is:
17export module helios.opengl.OpenGLBackend;
21import helios.engine.util.log;
23import helios.engine.rendering.viewport.ViewportEntity;
25import helios.engine.rendering.renderTarget.RenderTargetEntity;
26import helios.engine.rendering.common.types;
27import helios.engine.rendering.common.components;
29import helios.engine.spatial.components;
31import helios.engine.core.components;
33import helios.opengl.OpenGLUniformWriter;
34import helios.opengl.components;
35import helios.opengl.types;
38import helios.engine.rendering.mesh;
39import helios.engine.rendering.shader;
40import helios.engine.rendering.material;
41import helios.engine.rendering.renderTarget;
42import helios.engine.rendering.viewport;
43import helios.engine.util.Colors;
45import helios.engine.scene.components;
46import helios.engine.scene.types;
48import helios.engine.runtime.world.EngineWorld;
50import helios.opengl.types;
52using namespace helios::engine::core::components;
53using namespace helios::engine::rendering;
54using namespace helios::engine::rendering::mesh::components;
55using namespace helios::engine::rendering::shader;
56using namespace helios::engine::rendering::shader::types;
60using namespace helios::engine::spatial::components;
61using namespace helios::engine::rendering::material::types;
62using namespace helios::engine::rendering::common::types;
63using namespace helios::engine::rendering::common::components;
64using namespace helios::engine::rendering::shader::components;
65using namespace helios::engine::rendering::mesh::types;
66using namespace helios::engine::rendering::renderTarget;
67using namespace helios::engine::rendering::renderTarget::types;
68using namespace helios::engine::rendering::viewport;
69using namespace helios::engine::rendering::viewport::types;
70using namespace helios::engine::scene::components;
71using namespace helios::engine::scene::types;
72using namespace helios::engine::runtime::world;
73using namespace helios::engine::util::log;
75#define HELIOS_LOG_SCOPE "helios::opengl"
91 bool isInitialized_ = false;
96 inline static const helios::engine::util::log::Logger& logger_ = helios::engine::util::log::LogManager::loggerForScope(
108 UniformValueBag<UniformScope::Pass> passUniformValueBag_{};
113 UniformValueBag<UniformScope::Draw> drawUniformValueBag_{};
118 UniformValueBag<UniformScope::Material> materialUniformValueBag_{};
123 RenderTargetHandle currentRenderTargetHandle_{};
128 ShaderHandle currentShaderHandle_{};
134 EngineWorld& engineWorld_;
139 struct ViewProjection {
140 helios::math::mat4f viewMatrix;
141 helios::math::mat4f projectionMatrix;
150 [[nodiscard]] std::optional<ViewProjection> viewProjection(const ViewportEntity& viewportEntity) const noexcept {
152 auto* cbc = viewportEntity.get<CameraBindingComponent<ViewportHandle>>();
154 logger_.error("Expected CameraBindingComponent on ViewportEntity, but couldn't find any.");
157 auto camera = engineWorld_.find(cbc->targetHandle());
159 logger_.error("Expected CameraEntity, but couldn't find any.");
162 using CameraHandleType = std::remove_cvref_t<decltype(cbc->targetHandle())>;
163 auto* vm = camera->get<ViewMatrixComponent<CameraHandleType>>();
165 logger_.error("Expected ViewMatrixComponent, but couldn't find any.");
169 auto* pm = camera->get<ProjectionMatrixComponent<CameraHandleType>>();
171 logger_.error("Expected ProjectionMatrixComponent, but couldn't find any.");
175 return ViewProjection{
176 vm->value(), pm->value()
193 template<typename TUniformScope>
194 void writeUniformValues(ShaderEntity shaderEntity, UniformValueBag<TUniformScope>& uniformValueBag) noexcept {
199 logger_.error("OpenGLUniformWriteOperationsComponent<{0}> expected, but not found", typeid(TUniformScope).name());
200 assert(false && "OpenGLUniformWriteOperationsComponent not found");
215 template<typename THandle, typename TEntity>
216 void clearColor(TEntity& entity) noexcept {
218 auto* colorComp = entity->template get<ColorComponent<THandle>>();
219 auto* clearComp = entity->template get<ClearComponent<THandle>>();
222 const auto clearColor = colorComp->value();
223 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
227 const auto clearFlags = std::to_underlying(clearComp->flags);
228 const auto clearMask = ((clearFlags & std::to_underlying(ClearFlags::Color)) ? GL_COLOR_BUFFER_BIT : 0) |
229 ((clearFlags & std::to_underlying(ClearFlags::Depth)) ? GL_DEPTH_BUFFER_BIT : 0) |
230 ((clearFlags & std::to_underlying(ClearFlags::Stencil)) ? GL_STENCIL_BUFFER_BIT : 0);
232 if (clearMask != 0) {
248 explicit OpenGLBackend(EngineWorld& engineWorld) : engineWorld_(engineWorld) {}
261 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(renderTargetHandle);
264 if (!renderTargetEntity) {
265 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetHandle.entityId);
266 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
270 currentRenderTargetHandle_ = renderTargetHandle;
274 glBindFramebuffer(GL_FRAMEBUFFER, renderTargetId);
277 const auto isValidRenderTarget = renderTargetId == 0 ||
278 (glIsFramebuffer(renderTargetId) == GL_TRUE && glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
279 if (!isValidRenderTarget) {
280 logger_.error("RenderTargetEntity with EntityId {0} undefined.", renderTargetId);
281 assert(isValidRenderTarget && "RenderTargetEntity EntityId does not seem to be a valid id.");
285 auto renderTargetSize = renderTargetEntity->get<Size2DComponent<RenderTargetHandle>>()->value();
288 static_cast<int>(renderTargetSize[0]),
289 static_cast<int>(renderTargetSize[1])
292 clearColor<RenderTargetHandle>(renderTargetEntity);
297 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
309 currentRenderTargetHandle_ = RenderTargetHandle{};
310 passUniformValueBag_.clearValues();
323 auto viewport = engineWorld_.find<ViewportHandle>(viewportHandle);
324 auto renderTargetEntity = engineWorld_.find<RenderTargetHandle>(currentRenderTargetHandle_);
327 if (!renderTargetEntity) {
328 logger_.error("Missing RenderTargetEntity for handle {0}.", renderTargetEntity->handle().entityId);
329 assert(renderTargetEntity && "Missing RenderTargetEntity for handle.");
332 logger_.error("Missing Viewport for handle {0}.", viewportHandle.entityId);
333 assert(viewport && "Missing Viewport for handle.");
337 auto vp = viewProjection(*viewport);
339 logger_.warn("Could not determine View/Projection-matrices for RenderPass");
340 passUniformValueBag_.set<ProjectionMatrixUniform>(helios::math::mat4f{1.0f});
341 passUniformValueBag_.set<ViewMatrixUniform>(helios::math::mat4f{1.0f});
343 passUniformValueBag_.set<ProjectionMatrixUniform>(vp->projectionMatrix);
344 passUniformValueBag_.set<ViewMatrixUniform>(vp->viewMatrix);
347 auto viewportBounds = viewport->get<RectComponent<ViewportHandle>>()->value();
348 auto renderTargetSize = renderTargetEntity->get<Size2DComponent<RenderTargetHandle>>()->value();
350 const auto x = static_cast<int>(renderTargetSize[0] * viewportBounds[0]);
351 const auto y = static_cast<int>(renderTargetSize[1] * viewportBounds[1]);
352 const auto width = static_cast<int>(renderTargetSize[0] * viewportBounds[2]);
353 const auto height = static_cast<int>(renderTargetSize[1] * viewportBounds[3]);
356 glViewport(x, y, width, height);
357 glScissor(x, y, width, height);
358 glEnable(GL_SCISSOR_TEST);
360 clearColor<ViewportHandle>(viewport);
369 glDisable(GL_SCISSOR_TEST);
381 auto shaderEntity = engineWorld_.find(shaderHandle);
383 logger_.error("ShaderEntity expected, but not found");
384 assert(false && "ShaderEntity not found");
388 currentShaderHandle_ = shaderHandle;
390 auto* openglShader = shaderEntity->template get<OpenGLShaderComponent<ShaderHandle>>();
392 logger_.error("OpenGLShader expected, but not found");
393 assert(false && "OpenGLShader not found");
397 glUseProgram(openglShader->programId);
398 writeUniformValues<UniformScope::Pass>(*shaderEntity, passUniformValueBag_);
407 currentShaderHandle_ = ShaderHandle{};
418 auto materialEntity = engineWorld_.find(materialHandle);
419 if (!materialEntity) {
420 logger_.error("MaterialEntity expected, but not found");
421 assert(false && "MaterialEntity not found");
425 auto* colorComponent = materialEntity->template get<ColorComponent<MaterialHandle>>();
426 if (colorComponent) {
427 materialUniformValueBag_.set<MaterialBaseColorUniform>(colorComponent->value());
428 const auto shaderEntity = engineWorld_.find(currentShaderHandle_);
429 assert(shaderEntity && "ShaderEntity expected, but not found");
430 writeUniformValues<UniformScope::Material>(*shaderEntity, materialUniformValueBag_);
441 materialUniformValueBag_.clearValues();
453 auto meshEntity = engineWorld_.find(meshHandle);
455 logger_.error("MeshEntity expected, but not found");
456 assert(false && "MeshEntity not found");
460 auto* openglMesh = meshEntity->template get<OpenGLMeshComponent<MeshHandle>>();
462 logger_.error("OpenGLMesh expected, but not found");
463 assert(false && "OpenGLMesh not found");
466 currentOpenGLMesh_ = openglMesh;
467 glBindVertexArray(openglMesh->vao);
477 currentOpenGLMesh_ = nullptr;
478 glBindVertexArray(0);
491 template<typename THandle>
492 void renderBatch(std::span<const SceneMemberRenderContext<THandle>> sceneMemberRenderContexts) noexcept {
494 if (!currentOpenGLMesh_) {
495 logger_.error("OpenGLMesh expected, but not available");
498 if (!currentShaderHandle_.isValid()) {
499 logger_.error("Expected valid currentShaderHandle_, but found {0}.", currentShaderHandle_.entityId);
503 const auto shaderEntity = engineWorld_.find(currentShaderHandle_);
505 assert(shaderEntity && "ShaderEntity expected, but not found");
506 assert(currentOpenGLMesh_ && "Current OpenGL mesh expected, but not found");
508 for (auto& renderContext : sceneMemberRenderContexts) {
510 drawUniformValueBag_.set<ModelMatrixUniform>(renderContext.worldMatrix);
511 writeUniformValues<UniformScope::Draw>(*shaderEntity, drawUniformValueBag_);
520 drawUniformValueBag_.clearValues();
532 template<typename THandle>
533 void renderBatch(std::span<const InstanceData<THandle>> instanceData) noexcept {
535 if (!currentOpenGLMesh_) {
536 logger_.error("OpenGLMesh expected, but not available");
540 assert(currentOpenGLMesh_ && "Current OpenGL mesh expected, but not found");
542 const auto instanceSize = instanceData.size();
544 assert(instanceSize <= 1000000 && "Instance data size seems unreasonably large.");
546 if (instanceSize <= 0) {
550 assert(currentOpenGLMesh_->instanceVbo && "Using instancing without configured instanceVbo");
551 glBindBuffer(GL_ARRAY_BUFFER, currentOpenGLMesh_->instanceVbo);
555 instanceSize * sizeof(InstanceData<THandle>),
560 glDrawElementsInstanced(
568 glBindBuffer(GL_ARRAY_BUFFER, 0);
579 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
580 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
581 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
592 [[nodiscard]] bool init() noexcept {
594 assert(!isInitialized_ && "Backend already initialized");
596 const GLADloadfunc procAddressLoader = glfwGetProcAddress;
597 const int gl_ver = gladLoadGL(procAddressLoader);
600 logger_.error("Failed to load OpenGL");
601 assert(false && "Failed to load OpenGL");
605 logger_.info("OpenGL {0}.{1} loaded", GLAD_VERSION_MAJOR(gl_ver), GLAD_VERSION_MINOR(gl_ver));
607 isInitialized_ = true;
616 return isInitialized_;
Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.