Skip to main content

OpenGLMeshUploadManager.ixx File

OpenGL manager that uploads mesh data and creates VAO/VBO/EBO objects. More...

Included Headers

#include <glad/gl.h> #include <GLFW/glfw3.h> #include <cassert> #include <iostream> #include <memory> #include <ostream> #include <ranges> #include <unordered_map> #include <vector> #include <helios.engine.runtime.world.tags> #include <helios.engine.util.log> #include <helios.opengl.OpenGLEnumMapper> #include <helios.engine.rendering.common.types.Vertex> #include <helios.engine.util.io> #include <helios.engine.runtime.messaging.command.concepts> #include <helios.engine.rendering.mesh.commands> #include <helios.engine.rendering.mesh.components> #include <helios.engine.rendering.mesh.types> #include <helios.engine.rendering.mesh.MeshEntity> #include <helios.engine.runtime.world> #include <helios.engine.rendering.mesh.concepts> #include <helios.opengl.components.OpenGLMeshComponent> #include <helios.engine.runtime.world.EngineWorld> #include <helios.engine.runtime.messaging.command.NullCommandBuffer> #include <helios.engine.runtime.messaging.command.CommandHandlerRegistry> #include <helios.engine.runtime.concepts>

Namespaces Index

namespacehelios
namespaceopengl
namespaceio
namespacetags
namespacecommands
namespacemesh
namespaceconcepts
namespaceconcepts
namespacecommand

Classes Index

classOpenGLMeshUploadManager<THandle, TCommandBuffer>

Manager that consumes mesh-upload commands and performs OpenGL buffer setup. More...

structAttributeFormat

Derived OpenGL attribute layout information for one engine attribute type. More...

Macro Definitions Index

#defineHELIOS_LOG_SCOPE   "helios::opengl::OpenGLMeshUploadManager"

Description

OpenGL manager that uploads mesh data and creates VAO/VBO/EBO objects.

Macro Definitions

HELIOS_LOG_SCOPE

#define HELIOS_LOG_SCOPE   "helios::opengl::OpenGLMeshUploadManager"

Definition at line 58 of file OpenGLMeshUploadManager.ixx.

58#define HELIOS_LOG_SCOPE "helios::opengl::OpenGLMeshUploadManager"

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <glad/gl.h>
8#include <GLFW/glfw3.h>
9#include <cassert>
10#include <iostream>
11#include <memory>
12#include <ostream>
13#include <ranges>
14#include <unordered_map>
15#include <vector>
16
17
18export module helios.opengl.OpenGLMeshUploadManager;
19
20import helios.engine.util.log;
21import helios.engine.util.io;
22
23import helios.engine.rendering.common.types.Vertex;
24import helios.engine.rendering.mesh.commands;
25import helios.engine.rendering.mesh.components;
26import helios.engine.rendering.mesh.MeshEntity;
27import helios.engine.rendering.mesh.types;
28import helios.engine.rendering.mesh.concepts;
29
30import helios.engine.runtime.world.EngineWorld;
31import helios.engine.runtime.messaging.command.concepts;
32import helios.engine.runtime.messaging.command.NullCommandBuffer;
33import helios.engine.runtime.messaging.command.CommandHandlerRegistry;
34import helios.engine.runtime.concepts;
35import helios.engine.runtime.world.tags;
36import helios.engine.runtime.world;
37
38
39import helios.opengl.components.OpenGLMeshComponent;
40import helios.opengl.OpenGLEnumMapper;
41
42using namespace helios::engine::runtime::world;
43using namespace helios::engine::util::log;
44using namespace helios::engine::util::io;
45using namespace helios::engine::runtime::world::tags;
46using namespace helios::engine::rendering::mesh::commands;
47using namespace helios::engine::rendering::mesh::components;
48using namespace helios::engine::rendering::mesh;
49using namespace helios::engine::rendering::mesh::types;
50using namespace helios::engine::rendering::mesh::concepts;
51using namespace helios::engine::rendering::mesh::commands;
52using namespace helios::engine::rendering::common::types;
53using namespace helios::opengl;
54using namespace helios::opengl::components;
55using namespace helios::engine::runtime::messaging::command::concepts;
56using namespace helios::engine::runtime::messaging::command;
57
58#define HELIOS_LOG_SCOPE "helios::opengl::OpenGLMeshUploadManager"
59export namespace helios::opengl {
60
67 template<typename THandle, typename TCommandBuffer = NullCommandBuffer>
68 requires IsMeshHandle<THandle> && IsCommandBufferLike<TCommandBuffer>
70
74 RenderResourceWorld& renderResourceWorld_;
75
79 std::vector<MeshHandle> meshHandles_;
80
81
82 inline static const Logger& logger_ = LogManager::loggerForScope(HELIOS_LOG_SCOPE);
83
87 struct AttributeFormat {
88 std::uint32_t locationCount;
89 std::uint32_t componentsPerLocation;
90 std::uint32_t locationStrideBytes;
91 };
92
99 template<typename TVertexInputRate>
100 void buildVertexAttributeLayout(const VertexAttributeLayoutComponent<THandle, TVertexInputRate>* layoutComponent) noexcept {
101
102 const auto& active = layoutComponent->active();
103 const auto& layouts = layoutComponent->layouts();
104
105 for (std::size_t idx = 0; idx < active.size(); idx++) {
106
107 if (!active.test(idx)) {
108 continue;
109 }
110
111 const auto& layout = layouts[idx];
112
113 const auto format = fromAttributeType(layout.attribute.type);
114
115 for (std::uint32_t i = 0; i < format.locationCount; i++) {
116 const auto location = layout.location + i;
117
118 glEnableVertexAttribArray(location);
119 glVertexAttribPointer(
120 location,
121 format.componentsPerLocation,
122 OpenGLEnumMapper::toOpenGLBaseType(layout.attribute.type),
123 GL_FALSE,
124 static_cast<GLsizei>(layout.stride),
125 reinterpret_cast<void*>(layout.offset + (i * format.locationStrideBytes))
126 );
127 glVertexAttribDivisor(location, layout.divisor);
128 }
129 }
130
131 }
132
133
140 [[nodiscard]] AttributeFormat fromAttributeType(VertexAttributeType attributeType) const noexcept {
141
142 switch (attributeType) {
143 case VertexAttributeType::Float:
144 return AttributeFormat{1, 1, 0};
145 case VertexAttributeType::Vec3f:
146 return AttributeFormat{1, 3, 0};
147 case VertexAttributeType::Vec4f:
148 return AttributeFormat{1, 4, 0};
149 case VertexAttributeType::Mat4f:
150 return AttributeFormat{4, 4, sizeof(float) * 4};
151 default:
152 std::unreachable();
153 }
154
155 }
156
163 bool upload(MeshEntity mesh) noexcept {
164
165 using Handle = typename MeshEntity::Handle_type;
166
167 logger_.info("Uploading mesh data for MeshEntity {0}...", mesh.handle().entityId);
168
169 if (!mesh.template get<MeshUploadRequestComponent<Handle>>()) {
170 logger_.error("MeshUpload not requested by this entity");
171 assert(false && "MeshUpload not requested by this entity");
172 return false;
173 }
174
175
176 if (mesh.template get<OpenGLMeshComponent<Handle>>()) {
177 logger_.error("Mesh already has a MeshComponent");
178 assert(false && "Mesh already has a MeshComponent");
179 return false;
180 }
181
182 auto* meshDataComponent = mesh.template get<MeshDataComponent<Handle>>();
183 auto& meshData = meshDataComponent->meshData;
184
185 auto& openglMesh = mesh.template add<OpenGLMeshComponent<Handle>>();
186
187 openglMesh.indexCount = meshData.indices.size();
188 openglMesh.primitiveType = OpenGLEnumMapper::toOpenGL(meshData.primitiveType);
189
190 auto* vertexAttributeLayoutComponent = mesh.template get<VertexAttributeLayoutComponent<Handle, PerVertex>>();
191 assert(vertexAttributeLayoutComponent && "Expected a VertexAttributeLayoutComponent for PerVertex attributes");
192 auto* instancedAttributeLayoutComponent = mesh.template get<VertexAttributeLayoutComponent<Handle, PerInstance>>();
193
194 glGenVertexArrays(1, &openglMesh.vao);
195 glGenBuffers(1, &openglMesh.vbo);
196 glGenBuffers(1, &openglMesh.ebo);
197
198 if (instancedAttributeLayoutComponent) {
199 glGenBuffers(1, &openglMesh.instanceVbo);
200 }
201
202 glBindVertexArray(openglMesh.vao);
203
204 // vertex buffer
205 glBindBuffer(GL_ARRAY_BUFFER, openglMesh.vbo);
206 glBufferData(
207 GL_ARRAY_BUFFER,
208 meshData.vertices.size() * sizeof(Vertex),
209 &(meshData.vertices)[0],
210 GL_STATIC_DRAW
211 );
212
213 // element buffer
214 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, openglMesh.ebo);
215 glBufferData(
216 GL_ELEMENT_ARRAY_BUFFER,
217 meshData.indices.size() * sizeof(unsigned int),
218 &(meshData.indices)[0],
219 GL_STATIC_DRAW
220 );
221
222 // per instance buffer
223 buildVertexAttributeLayout<PerVertex>(vertexAttributeLayoutComponent);
224 mesh.template remove<VertexAttributeLayoutComponent<Handle, PerVertex>>();
225
226 if (instancedAttributeLayoutComponent) {
227 glBindBuffer(GL_ARRAY_BUFFER, openglMesh.instanceVbo);
228 buildVertexAttributeLayout<PerInstance>(instancedAttributeLayoutComponent);
229 mesh.template remove<VertexAttributeLayoutComponent<Handle, PerInstance>>();
230 }
231
232
233 glBindVertexArray(0);
234 glBindBuffer(GL_ARRAY_BUFFER, 0);
235 return true;
236 }
237
238 public:
239
245 explicit OpenGLMeshUploadManager(RenderResourceWorld& renderResourceWorld)
246 :
247 renderResourceWorld_(renderResourceWorld)
248 { }
249
253 using EngineRoleTag = ManagerRole;
254
255
261 void flush(UpdateContext& updateContext) noexcept {
262
263 if (meshHandles_.empty()) {
264 return;
265 }
266
267 for (const auto& sourceHandle : meshHandles_) {
268 auto meshEntity = renderResourceWorld_.findEntity<THandle>(sourceHandle);
269
270 if (!meshEntity) {
271 logger_.error("Could not find mesh entity");
272 assert(false && "Could not find mesh entity");
273 continue;
274 }
275
276 if (!upload(*meshEntity)) {
277 logger_.error("Could not compile mesh");
278 } else {
279 meshEntity->template remove<MeshUploadRequestComponent<THandle>>();
280 }
281 }
282
283 meshHandles_.clear();
284 }
285
292 bool submit(MeshBatchUploadCommand<THandle>&& command) noexcept {
293 meshHandles_.reserve(meshHandles_.size() + command.meshHandles.size());
294
295 for (const auto& meshHandle : command.meshHandles) {
296 meshHandles_.push_back(std::move(meshHandle));
297 }
298 return true;
299 }
300
306 void init(helios::engine::runtime::messaging::command::CommandHandlerRegistry& commandHandlerRegistry) noexcept {
307 commandHandlerRegistry.registerHandler<MeshBatchUploadCommand<THandle>>(*this);
308 }
309 };
310
311
312}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.