Visual Computing Library
Loading...
Searching...
No Matches
mesh_render_buffers.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_BGFX_DRAWABLE_MESH_MESH_RENDER_BUFFERS_H
24#define VCL_BGFX_DRAWABLE_MESH_MESH_RENDER_BUFFERS_H
25
26#include "mesh_render_buffers_macros.h"
27
28#include <vclib/bgfx/buffers.h>
29#include <vclib/bgfx/drawable/uniforms/drawable_mesh_uniforms.h>
30#include <vclib/bgfx/texture_unit.h>
31#include <vclib/render/drawable/mesh/mesh_render_data.h>
32#include <vclib/render/drawable/mesh/mesh_render_settings.h>
33#include <vclib/space/core/image.h>
34
35#include <bgfx/bgfx.h>
36
37namespace vcl {
38
39template<MeshConcept Mesh>
40class MeshRenderBuffers : public MeshRenderData<MeshRenderBuffers<Mesh>>
41{
42 using MeshType = Mesh;
44 using MRI = MeshRenderInfo;
45
46 friend Base;
47
48 VertexBuffer mVertexCoordsBuffer;
49 VertexBuffer mVertexNormalsBuffer;
50 VertexBuffer mVertexColorsBuffer;
51 VertexBuffer mVertexUVBuffer;
52 VertexBuffer mVertexWedgeUVBuffer;
53
54 IndexBuffer mTriangleIndexBuffer;
55 IndexBuffer mTriangleNormalBuffer;
56 IndexBuffer mTriangleColorBuffer;
57
58 IndexBuffer mVertexTextureIndexBuffer;
59 IndexBuffer mWedgeTextureIndexBuffer;
60
61 // TODO: manage wireframe with proper lines
62 IndexBuffer mEdgeIndexBuffer;
63 IndexBuffer mEdgeNormalBuffer;
64 IndexBuffer mEdgeColorBuffer;
65
66 // TODO: manage wireframe with proper lines
67 IndexBuffer mWireframeIndexBuffer;
68
69 std::vector<std::unique_ptr<TextureUnit>> mTextureUnits;
70
71 DrawableMeshUniforms mMeshUniforms;
72
73public:
74 MeshRenderBuffers() = default;
75
77 const MeshType& mesh,
78 MRI::BuffersBitSet buffersToFill = MRI::BUFFERS_ALL) :
80 {
81 Base::update(mesh, buffersToFill);
82 }
83
85
87
88 MeshRenderBuffers& operator=(const MeshRenderBuffers& other) = delete;
89
91 {
92 swap(other);
93 return *this;
94 }
95
96 void swap(MeshRenderBuffers& other)
97 {
98 using std::swap;
99 Base::swap(other);
100 swap(mVertexCoordsBuffer, other.mVertexCoordsBuffer);
101 swap(mVertexNormalsBuffer, other.mVertexNormalsBuffer);
102 swap(mVertexColorsBuffer, other.mVertexColorsBuffer);
103 swap(mVertexUVBuffer, other.mVertexUVBuffer);
104 swap(mVertexWedgeUVBuffer, other.mVertexWedgeUVBuffer);
105 swap(mTriangleIndexBuffer, other.mTriangleIndexBuffer);
106 swap(mTriangleNormalBuffer, other.mTriangleNormalBuffer);
107 swap(mTriangleColorBuffer, other.mTriangleColorBuffer);
108 swap(mVertexTextureIndexBuffer, other.mVertexTextureIndexBuffer);
109 swap(mWedgeTextureIndexBuffer, other.mWedgeTextureIndexBuffer);
110 swap(mEdgeIndexBuffer, other.mEdgeIndexBuffer);
111 swap(mEdgeNormalBuffer, other.mEdgeNormalBuffer);
112 swap(mEdgeColorBuffer, other.mEdgeColorBuffer);
113 swap(mWireframeIndexBuffer, other.mWireframeIndexBuffer);
114 swap(mTextureUnits, other.mTextureUnits);
115 swap(mMeshUniforms, other.mMeshUniforms);
116 }
117
118 friend void swap(MeshRenderBuffers& a, MeshRenderBuffers& b) { a.swap(b); }
119
120 void bindVertexBuffers(const MeshRenderSettings& mrs) const
121 {
122 // bgfx allows a maximum number of 4 vertex streams...
123
124 mVertexCoordsBuffer.bind(0);
125 mVertexNormalsBuffer.bind(1);
126 mVertexColorsBuffer.bind(2);
127
128 if (mrs.isSurface(MeshRenderInfo::Surface::COLOR_VERTEX_TEX)) {
129 mVertexUVBuffer.bind(3);
130 }
131 else if (mrs.isSurface(MeshRenderInfo::Surface::COLOR_WEDGE_TEX)) {
132 mVertexWedgeUVBuffer.bind(3);
133 }
134 }
135
136 void bindIndexBuffers(
137 const MeshRenderSettings& mrs,
138 MRI::Buffers indexBufferToBind = MRI::Buffers::TRIANGLES) const
139 {
140 using enum MRI::Buffers;
141
142 if (indexBufferToBind == TRIANGLES) {
143 mTriangleIndexBuffer.bind();
144
145 mTriangleNormalBuffer.bind(VCL_MRB_PRIMITIVE_NORMAL_BUFFER);
146
147 mTriangleColorBuffer.bind(VCL_MRB_PRIMITIVE_COLOR_BUFFER);
148
149 if (mrs.isSurface(MeshRenderInfo::Surface::COLOR_VERTEX_TEX)) {
150 mVertexTextureIndexBuffer.bind(
151 VCL_MRB_TRIANGLE_TEXTURE_ID_BUFFER);
152 }
153 else if (mrs.isSurface(MeshRenderInfo::Surface::COLOR_WEDGE_TEX)) {
154 mWedgeTextureIndexBuffer.bind(
155 VCL_MRB_TRIANGLE_TEXTURE_ID_BUFFER);
156 }
157 }
158 else if (indexBufferToBind == EDGES) {
159 mEdgeIndexBuffer.bind();
160
161 mEdgeNormalBuffer.bind(VCL_MRB_PRIMITIVE_NORMAL_BUFFER);
162
163 mEdgeColorBuffer.bind(VCL_MRB_PRIMITIVE_COLOR_BUFFER);
164 }
165 else if (indexBufferToBind == WIREFRAME) {
166 mWireframeIndexBuffer.bind();
167 }
168 }
169
170 void bindTextures() const
171 {
172 uint i = VCL_MRB_TEXTURE0; // first slot available is VCL_MRB_TEXTURE0
173 for (const auto& ptr : mTextureUnits) {
174 ptr->bind(i);
175 i++;
176 }
177 }
178
179 void bindUniforms() const { mMeshUniforms.bind(); }
180
181private:
182 void setVertexCoordsBuffer(const MeshType& mesh) // override
183 {
184 uint nv = Base::numVerts();
185
186 auto [buffer, releaseFn] =
188
189 Base::fillVertexCoords(mesh, buffer);
190
191 mVertexCoordsBuffer.create(
192 buffer,
193 nv,
194 bgfx::Attrib::Position,
195 3,
196 PrimitiveType::FLOAT,
197 false,
198 releaseFn);
199 }
200
201 void setVertexNormalsBuffer(const MeshType& mesh) // override
202 {
203 uint nv = Base::numVerts();
204
205 auto [buffer, releaseFn] =
207
208 Base::fillVertexNormals(mesh, buffer);
209
210 mVertexNormalsBuffer.create(
211 buffer,
212 nv,
213 bgfx::Attrib::Normal,
214 3,
215 PrimitiveType::FLOAT,
216 false,
217 releaseFn);
218 }
219
220 void setVertexColorsBuffer(const MeshType& mesh) // override
221 {
222 uint nv = Base::numVerts();
223
225
226 Base::fillVertexColors(mesh, buffer, Color::Format::ABGR);
227
228 mVertexColorsBuffer.create(
229 buffer,
230 nv,
231 bgfx::Attrib::Color0,
232 4,
233 PrimitiveType::UCHAR,
234 true,
235 releaseFn);
236 }
237
238 void setVertexTexCoordsBuffer(const MeshType& mesh) // override
239 {
240 uint nv = Base::numVerts();
241
242 auto [buffer, releaseFn] =
244
245 Base::fillVertexTexCoords(mesh, buffer);
246
247 mVertexUVBuffer.create(
248 buffer,
249 nv,
250 bgfx::Attrib::TexCoord0,
251 2,
252 PrimitiveType::FLOAT,
253 false,
254 releaseFn);
255 }
256
257 void setWedgeTexCoordsBuffer(const MeshType& mesh) // override
258 {
259 uint nv = Base::numVerts();
260
261 auto [buffer, releaseFn] =
263
264 Base::fillWedgeTexCoords(mesh, buffer);
265
266 mVertexWedgeUVBuffer.create(
267 buffer,
268 nv,
269 bgfx::Attrib::TexCoord1,
270 2,
271 PrimitiveType::FLOAT,
272 false,
273 releaseFn);
274 }
275
276 void setTriangleIndicesBuffer(const MeshType& mesh) // override
277 {
278 uint nt = Base::numTris();
279
281
282 Base::fillTriangleIndices(mesh, buffer);
283
284 mTriangleIndexBuffer.create(buffer, nt * 3, true, releaseFn);
285 }
286
287 void setTriangleNormalsBuffer(const MeshType& mesh) // override
288 {
289 uint nt = Base::numTris();
290
291 auto [buffer, releaseFn] =
293
294 Base::fillTriangleNormals(mesh, buffer);
295
296 mTriangleNormalBuffer.createForCompute(
297 buffer,
298 nt * 3,
299 PrimitiveType::FLOAT,
300 bgfx::Access::Read,
301 releaseFn);
302 }
303
304 void setTriangleColorsBuffer(const MeshType& mesh) // override
305 {
306 uint nt = Base::numTris();
307
309
310 Base::fillTriangleColors(mesh, buffer, Color::Format::ABGR);
311
312 mTriangleColorBuffer.createForCompute(
313 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
314 }
315
316 void setVertexTextureIndicesBuffer(const MeshType& mesh) // override
317 {
318 uint nt = Base::numTris();
319
321
322 Base::fillVertexTextureIndices(mesh, buffer);
323
324 mVertexTextureIndexBuffer.createForCompute(
325 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
326 }
327
328 void setWedgeTextureIndicesBuffer(const MeshType& mesh) // override
329 {
330 uint nt = Base::numTris();
331
333
334 Base::fillWedgeTextureIndices(mesh, buffer);
335
336 mWedgeTextureIndexBuffer.createForCompute(
337 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
338 }
339
340 void setEdgeIndicesBuffer(const MeshType& mesh) // override
341 {
342 uint ne = Base::numEdges();
343
345
346 Base::fillEdgeIndices(mesh, buffer);
347
348 mEdgeIndexBuffer.create(buffer, ne * 2);
349 }
350
351 void setEdgeNormalsBuffer(const MeshType& mesh) // override
352 {
353 uint ne = Base::numEdges();
354
355 auto [buffer, releaseFn] =
357
358 Base::fillEdgeNormals(mesh, buffer);
359
360 mEdgeNormalBuffer.createForCompute(
361 buffer,
362 ne * 3,
363 PrimitiveType::FLOAT,
364 bgfx::Access::Read,
365 releaseFn);
366 }
367
368 void setEdgeColorsBuffer(const MeshType& mesh) // override
369 {
370 uint ne = Base::numEdges();
371
373
374 Base::fillEdgeColors(mesh, buffer, Color::Format::ABGR);
375
376 mEdgeColorBuffer.createForCompute(
377 buffer, ne, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
378 }
379
380 void setWireframeIndicesBuffer(const MeshType& mesh) // override
381 {
382 const uint nw = Base::numWireframeLines();
383
385
386 Base::fillWireframeIndices(mesh, buffer);
387
388 mWireframeIndexBuffer.create(buffer, nw * 2, true, releaseFn);
389 }
390
391 void setTextureUnits(const MeshType& mesh) // override
392 {
393 mTextureUnits.clear();
394 mTextureUnits.reserve(mesh.textureNumber());
395 for (uint i = 0; i < mesh.textureNumber(); ++i) {
397 if constexpr (vcl::HasTextureImages<MeshType>) {
398 if (mesh.texture(i).image().isNull()) {
399 txt = vcl::Image(mesh.meshBasePath() + mesh.texturePath(i));
400 }
401 else {
402 txt = mesh.texture(i).image();
403 }
404 }
405 else {
406 txt = vcl::Image(mesh.meshBasePath() + mesh.texturePath(i));
407 }
408 txt.mirror();
409
410 const uint size = txt.width() * txt.height();
411
412 auto [buffer, releaseFn] =
414
415 const uint* tdata = reinterpret_cast<const uint*>(txt.data());
416
417 std::copy(tdata, tdata + size, buffer);
418
419 auto tu = std::make_unique<TextureUnit>();
420 tu->set(
421 buffer,
422 vcl::Point2i(txt.width(), txt.height()),
423 "s_tex" + std::to_string(i),
424 false,
425 releaseFn);
426
427 mTextureUnits.push_back(std::move(tu));
428 }
429 }
430
431 void setMeshUniforms(const MeshType& mesh) // override
432 {
433 mMeshUniforms.update(mesh);
434 }
435
436 template<typename T>
437 std::pair<T*, bgfx::ReleaseFn> getAllocatedBufferAndReleaseFn(uint size)
438 {
439 T* buffer = new T[size];
440
441 return std::make_pair(buffer, [](void* ptr, void*) {
442 delete[] static_cast<T*>(ptr);
443 });
444 }
445};
446
447} // namespace vcl
448
449#endif // VCL_BGFX_DRAWABLE_MESH_MESH_RENDER_BUFFERS_H
The BitSet class allows to treat an integral type as an array of booleans of a guaranteed size.
Definition bit_set.h:53
Definition drawable_mesh_uniforms.h:32
The Image class stores an Image in 4 bytes RGBA format.
Definition image.h:44
The IndexBuffer manages the lifetime of a bgfx::IndexBufferHandle.
Definition index_buffer.h:43
void create(const void *bufferIndices, const uint bufferSize, bool is32Bit=true, bgfx::ReleaseFn releaseFn=nullptr)
Creates the index buffer and sets the data for rendering.
Definition index_buffer.h:103
void bind(uint stage=UINT_NULL, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the index buffer to the rendering pipeline.
Definition index_buffer.h:193
void createForCompute(const void *bufferIndices, const uint bufferSize, PrimitiveType type, bgfx::Access::Enum access=bgfx::Access::Read, bgfx::ReleaseFn releaseFn=nullptr)
Creates the index buffer and sets the data for compute shaders.
Definition index_buffer.h:141
Definition mesh_render_buffers.h:41
The MeshRenderData class provides a common interface to automatically update the buffers used to rend...
Definition mesh_render_data.h:81
The MeshRenderInfo class is a collection of rendering settings for a Mesh.
Definition mesh_render_info.h:61
The MeshRenderSettings class allows an easy management of render settings of a Mesh....
Definition mesh_render_settings.h:71
The Mesh class represents a generic 3D mesh. A mesh is composed of a generic number of containers of ...
Definition mesh.h:68
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:58
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
The VertexBuffer manages the lifetime of a bgfx::VertexBufferHandle.
Definition vertex_buffer.h:43
void create(const void *bufferData, uint vertNum, bgfx::Attrib::Enum attrib, uint attribNumPerVertex, PrimitiveType attribType, bool normalize=false, bgfx::ReleaseFn releaseFn=nullptr)
Creates the vertex buffer and sets the data for rendering.
Definition vertex_buffer.h:106
void bind(uint stream, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the vertex buffer to the rendering pipeline.
Definition vertex_buffer.h:231
Concept that checks if a Mesh has the TextureImages component.
Definition per_mesh.h:103