Visual Computing Library  devel
Loading...
Searching...
No Matches
mesh_render_buffers.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2026 *
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/algorithms/core/create.h>
29#include <vclib/bgfx/buffers.h>
30#include <vclib/bgfx/context.h>
31#include <vclib/bgfx/drawable/uniforms/drawable_mesh_uniforms.h>
32#include <vclib/bgfx/drawable/uniforms/material_uniforms.h>
33#include <vclib/bgfx/primitives/lines.h>
34#include <vclib/bgfx/texture.h>
35#include <vclib/io/image/load.h>
36#include <vclib/render/drawable/mesh/mesh_render_data.h>
37#include <vclib/render/drawable/mesh/mesh_render_settings.h>
38#include <vclib/space/core/image.h>
39
40#include <bgfx/bgfx.h>
41#include <bimg/bimg.h>
42
43namespace vcl {
44
45template<MeshConcept Mesh>
46class MeshRenderBuffers : public MeshRenderData<MeshRenderBuffers<Mesh>>
47{
48 using MeshType = Mesh;
50 using MRI = MeshRenderInfo;
51
52 friend Base;
53
54 inline static const uint N_TEXTURE_TYPES =
55 toUnderlying(Material::TextureType::COUNT);
56
57 VertexBuffer mVertexPositionsBuffer;
58 VertexBuffer mVertexNormalsBuffer;
59 VertexBuffer mVertexColorsBuffer;
60 VertexBuffer mVertexUVBuffer;
61 VertexBuffer mVertexWedgeUVBuffer;
62 VertexBuffer mVertexTangentsBuffer;
63
64 // point splatting
65 IndexBuffer mVertexQuadIndexBuffer;
66 DynamicVertexBuffer mVertexQuadBuffer;
67 mutable bool mVertexQuadBufferGenerated = false;
68
69 IndexBuffer mTriangleIndexBuffer;
70 IndexBuffer mTriangleNormalBuffer;
71 IndexBuffer mTriangleColorBuffer;
72
73 Lines mEdgeLines;
74
75 Lines mWireframeLines;
76 Color mMeshColor; // todo: find better way to store mesh color
77
78 // map of textures
79 // for each texture path of each material, store its texture
80 std::map<std::string, Texture> mMaterialTextures;
81
82 static inline std::array<Uniform, N_TEXTURE_TYPES> sTextureSamplerUniforms;
83
84public:
85 MeshRenderBuffers() = default;
86
88 const MeshType& mesh,
89 MRI::BuffersBitSet buffersToFill = MRI::BUFFERS_ALL) :
91 {
92 Base::update(mesh, buffersToFill);
93 }
94
96
98
99 MeshRenderBuffers& operator=(const MeshRenderBuffers& other) = delete;
100
102 {
103 swap(other);
104 return *this;
105 }
106
107 void swap(MeshRenderBuffers& other)
108 {
109 using std::swap;
110 Base::swap(other);
111 swap(mVertexPositionsBuffer, other.mVertexPositionsBuffer);
112 swap(mVertexNormalsBuffer, other.mVertexNormalsBuffer);
113 swap(mVertexColorsBuffer, other.mVertexColorsBuffer);
114 swap(mVertexUVBuffer, other.mVertexUVBuffer);
115 swap(mVertexWedgeUVBuffer, other.mVertexWedgeUVBuffer);
116 swap(mVertexTangentsBuffer, other.mVertexTangentsBuffer);
117 swap(mVertexQuadIndexBuffer, other.mVertexQuadIndexBuffer);
118 swap(mVertexQuadBuffer, other.mVertexQuadBuffer);
119 swap(mVertexQuadBufferGenerated, other.mVertexQuadBufferGenerated);
120 swap(mTriangleIndexBuffer, other.mTriangleIndexBuffer);
121 swap(mTriangleNormalBuffer, other.mTriangleNormalBuffer);
122 swap(mTriangleColorBuffer, other.mTriangleColorBuffer);
123 swap(mEdgeLines, other.mEdgeLines);
124 swap(mWireframeLines, other.mWireframeLines);
125 swap(mMaterialTextures, other.mMaterialTextures);
126 }
127
128 friend void swap(MeshRenderBuffers& a, MeshRenderBuffers& b) { a.swap(b); }
129
130 // to generate splats
131 void computeQuadVertexBuffers(
132 const MeshType& mesh,
133 const bgfx::ViewId viewId) const
134 {
135 if (!mVertexQuadBuffer.isValid() || mVertexQuadBufferGenerated) {
136 return;
137 }
138
139 // fill the buffer using compute shader
140 mVertexPositionsBuffer.bindCompute(
141 VCL_MRB_VERTEX_POSITION_STREAM, bgfx::Access::Read);
142 mVertexNormalsBuffer.bindCompute(
143 VCL_MRB_VERTEX_NORMAL_STREAM, bgfx::Access::Read);
144 mVertexColorsBuffer.bindCompute(
145 VCL_MRB_VERTEX_COLOR_STREAM, bgfx::Access::Read);
146
147 mVertexQuadBuffer.bindCompute(4, bgfx::Access::Write);
148
149 auto& pm = Context::instance().programManager();
150 bgfx::dispatch(
151 viewId,
152 pm.getComputeProgram<ComputeProgram::DRAWABLE_MESH_POINTS>(),
153 mesh.vertexCount(),
154 1,
155 1);
156
157 mVertexQuadBufferGenerated = true;
158 }
159
160 void bindVertexBuffers(const MeshRenderSettings& mrs) const
161 {
162 // TODO: streams cannot be higher than
163 // "bgfx::getCaps()->limits.maxVertexStreams". Buffers must be bound
164 // only if necessary (using MeshRenderSettings) right now, this is
165 // managed only for uvs (per vertex or per wedge, not both).
166 // We MUST be sure that the limit is not exceeded.
167
168 using enum MeshRenderInfo::Surface;
169
170 uint stream = 0;
171
172 // streams MUST be consecutive starting from 0
173 // otherwise on metal it won't work
174 mVertexPositionsBuffer.bindVertex(stream++);
175
176 if (mVertexNormalsBuffer.isValid()) {
177 // bgfx limitation
178 assert(stream < bgfx::getCaps()->limits.maxVertexStreams);
179 mVertexNormalsBuffer.bindVertex(stream++);
180 }
181
182 if (mVertexTangentsBuffer.isValid()) {
183 // bgfx limitation
184 assert(stream < bgfx::getCaps()->limits.maxVertexStreams);
185 mVertexTangentsBuffer.bind(stream++);
186 }
187
188 if (mVertexColorsBuffer.isValid()) {
189 // bgfx limitation
190 assert(stream < bgfx::getCaps()->limits.maxVertexStreams);
191 mVertexColorsBuffer.bindVertex(stream++);
192 }
193
194 if (mVertexUVBuffer.isValid() && mrs.isSurface(COLOR_VERTEX_TEX)) {
195 // bgfx limitation
196 assert(stream < bgfx::getCaps()->limits.maxVertexStreams);
197 mVertexUVBuffer.bind(stream++);
198 }
199
200 if (mVertexWedgeUVBuffer.isValid() && mrs.isSurface(COLOR_WEDGE_TEX)) {
201 // bgfx limitation
202 assert(stream < bgfx::getCaps()->limits.maxVertexStreams);
203 mVertexWedgeUVBuffer.bind(stream++);
204 }
205 }
206
207 // to draw splats
208 void bindVertexQuadBuffer() const
209 {
210 mVertexQuadBuffer.bind(VCL_MRB_VERTEX_POSITION_STREAM);
211 mVertexQuadIndexBuffer.bind();
212 }
213
214 void bindIndexBuffers(
215 const MeshRenderSettings& mrs,
216 uint chunkToBind = UINT_NULL) const
217 {
218 using enum MRI::Buffers;
219
220 if (chunkToBind == UINT_NULL) {
221 mTriangleIndexBuffer.bind();
222 }
223 else {
224 const auto& chunk = Base::triangleChunk(chunkToBind);
225 mTriangleIndexBuffer.bind(
226 chunk.startIndex * 3, chunk.indexCount * 3);
227 }
228
229 mTriangleNormalBuffer.bind(VCL_MRB_PRIMITIVE_NORMAL_BUFFER);
230
231 mTriangleColorBuffer.bind(VCL_MRB_PRIMITIVE_COLOR_BUFFER);
232 }
233
234 void drawEdgeLines(uint viewId) const { mEdgeLines.draw(viewId); }
235
236 void drawWireframeLines(uint viewId) const { mWireframeLines.draw(viewId); }
237
238 void bindTextures(
239 const MeshRenderSettings& mrs,
240 uint chunkNumber,
241 const MeshType& m) const
242 {
243 uint materialId = Base::materialIndex(mrs, chunkNumber);
244
245 if (materialId != UINT_NULL) {
246 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
247 const auto& td = m.material(materialId).textureDescriptor(j);
248 const std::string& path = td.path();
249 if (!path.empty()) {
250 const Texture& tex = mMaterialTextures.at(path);
251 if (tex.isValid()) {
253 tex.bind(
254 VCL_MRB_TEXTURE0 + j,
255 sTextureSamplerUniforms[j].handle(),
256 flags);
257 }
258 }
259 }
260 }
261 }
262
263 std::array<bool, N_TEXTURE_TYPES> textureAvailableArray(
264 const MeshType& m,
265 uint materialId) const
266 {
267 std::array<bool, N_TEXTURE_TYPES> textureAvailable = {false};
268 if (materialId == UINT_NULL) {
269 return textureAvailable;
270 }
271 else {
272 assert(materialId < m.materialCount());
273 const Material& mat = m.material(materialId);
274
275 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
276 const auto& td = m.material(materialId).textureDescriptor(j);
277 const std::string& path = td.path();
278 if (!path.empty()) {
279 const Texture& tex = mMaterialTextures.at(path);
280 textureAvailable[j] = tex.isValid();
281 }
282 }
283 }
284 return textureAvailable;
285 }
286
287 void updateEdgeSettings(const MeshRenderSettings& mrs)
288 {
289 using enum MeshRenderInfo::Edges;
290 using enum Lines::ColorToUse;
291
292 mEdgeLines.thickness() = mrs.edgesWidth();
293 mEdgeLines.setShading(mrs.isEdges(SHADING_SMOOTH));
294
295 if (mrs.isEdges(COLOR_USER)) {
296 mEdgeLines.generalColor() = mrs.edgesUserColor();
297 mEdgeLines.setColorToUse(GENERAL);
298 }
299 else if (mrs.isEdges(COLOR_MESH)) {
300 mEdgeLines.generalColor() = mMeshColor;
301 mEdgeLines.setColorToUse(GENERAL);
302 }
303 else if (mrs.isEdges(COLOR_VERTEX)) {
304 mEdgeLines.setColorToUse(PER_VERTEX);
305 }
306 else if (mrs.isEdges(COLOR_EDGE)) {
307 mEdgeLines.setColorToUse(PER_EDGE);
308 }
309 }
310
311 void updateWireframeSettings(const MeshRenderSettings& mrs)
312 {
313 using enum MeshRenderInfo::Wireframe;
314 using enum Lines::ColorToUse;
315
316 mWireframeLines.thickness() = mrs.wireframeWidth();
317 mWireframeLines.setShading(mrs.isWireframe(SHADING_VERT));
318
319 if (mrs.isWireframe(COLOR_USER)) {
320 mWireframeLines.generalColor() = mrs.wireframeUserColor();
321 mWireframeLines.setColorToUse(GENERAL);
322 }
323 else if (mrs.isWireframe(COLOR_MESH)) {
324 mWireframeLines.generalColor() = mMeshColor;
325 mWireframeLines.setColorToUse(GENERAL);
326 }
327 else if (mrs.isWireframe(COLOR_VERTEX)) {
328 mWireframeLines.setColorToUse(PER_VERTEX);
329 }
330 }
331
332private:
333 void setVertexPositionsBuffer(const MeshType& mesh) // override
334 {
335 uint nv = Base::numVerts();
336
337 auto [buffer, releaseFn] =
338 Context::getAllocatedBufferAndReleaseFn<float>(nv * 3);
339
340 Base::fillVertexPositions(mesh, buffer);
341
342 mVertexPositionsBuffer.createForCompute(
343 buffer,
344 nv,
345 bgfx::Attrib::Position,
346 3,
347 PrimitiveType::FLOAT,
348 false,
349 bgfx::Access::Read,
350 releaseFn);
351
352 // Creates the buffers to be used with compute for splatting
353 if (Context::instance().supportsCompute()) {
354 // create a layout <coordinates, colors, normals, float>
355 // 2 X vec4
356 bgfx::VertexLayout layout;
357 layout.begin()
358 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
359 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
360 .add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float)
361 .add(bgfx::Attrib::TexCoord0, 1, bgfx::AttribType::Float)
362 .end();
363
364 // create the dynamic vertex buffer for splatting
365 mVertexQuadBuffer.create(
366 mesh.vertexCount() * 4, layout, BGFX_BUFFER_COMPUTE_WRITE);
367
368 // create the index buffer for splatting
370
371 // record that the vertex quad buffer must be generated
372 mVertexQuadBufferGenerated = false;
373 }
374 }
375
383 {
384 const uint totalIndices = mesh.vertexCount() * 6;
385
386 auto [buffer, releaseFn] =
387 Context::getAllocatedBufferAndReleaseFn<uint>(totalIndices);
388
389 Base::fillVertexQuadIndices(mesh, buffer);
390
391 mVertexQuadIndexBuffer.create(buffer, totalIndices, true, releaseFn);
392
393 // if number of vertices is not zero, the index buffer must be valid
394 assert(mVertexQuadIndexBuffer.isValid() || totalIndices == 0);
395 }
396
397 void setVertexNormalsBuffer(const MeshType& mesh) // override
398 {
399 uint nv = Base::numVerts();
400
401 auto [buffer, releaseFn] =
402 Context::getAllocatedBufferAndReleaseFn<float>(nv * 3);
403
404 Base::fillVertexNormals(mesh, buffer);
405
406 mVertexNormalsBuffer.createForCompute(
407 buffer,
408 nv,
409 bgfx::Attrib::Normal,
410 3,
411 PrimitiveType::FLOAT,
412 false,
413 bgfx::Access::Read,
414 releaseFn);
415 }
416
417 void setVertexColorsBuffer(const MeshType& mesh) // override
418 {
419 uint nv = Base::numVerts();
420
421 auto [buffer, releaseFn] =
422 Context::getAllocatedBufferAndReleaseFn<uint>(nv);
423
424 Base::fillVertexColors(mesh, buffer, Color::Format::ABGR);
425
426 mVertexColorsBuffer.createForCompute(
427 buffer,
428 nv,
429 bgfx::Attrib::Color0,
430 4,
431 PrimitiveType::UCHAR,
432 true,
433 bgfx::Access::Read,
434 releaseFn);
435 }
436
437 void setVertexTexCoordsBuffer(const MeshType& mesh) // override
438 {
439 uint nv = Base::numVerts();
440
441 auto [buffer, releaseFn] =
442 Context::getAllocatedBufferAndReleaseFn<float>(nv * 2);
443
444 Base::fillVertexTexCoords(mesh, buffer);
445
446 mVertexUVBuffer.create(
447 buffer,
448 nv,
449 bgfx::Attrib::TexCoord0,
450 2,
451 PrimitiveType::FLOAT,
452 false,
453 releaseFn);
454 }
455
456 void setVertexTangentsBuffer(const MeshType& mesh) // override
457 {
458 uint nv = Base::numVerts();
459
460 auto [buffer, releaseFn] =
461 Context::getAllocatedBufferAndReleaseFn<float>(nv * 4);
462
463 Base::fillVertexTangents(mesh, buffer);
464
465 mVertexTangentsBuffer.create(
466 buffer,
467 nv,
468 bgfx::Attrib::Tangent,
469 4,
470 PrimitiveType::FLOAT,
471 false,
472 releaseFn);
473 }
474
475 void setWedgeTexCoordsBuffer(const MeshType& mesh) // override
476 {
477 uint nv = Base::numVerts();
478
479 auto [buffer, releaseFn] =
480 Context::getAllocatedBufferAndReleaseFn<float>(nv * 2);
481
482 Base::fillWedgeTexCoords(mesh, buffer);
483
484 mVertexWedgeUVBuffer.create(
485 buffer,
486 nv,
487 bgfx::Attrib::TexCoord1,
488 2,
489 PrimitiveType::FLOAT,
490 false,
491 releaseFn);
492 }
493
494 void setTriangleIndicesBuffer(const MeshType& mesh) // override
495 {
496 uint nt = Base::numTris();
497
498 auto [buffer, releaseFn] =
499 Context::getAllocatedBufferAndReleaseFn<uint>(nt * 3);
500
501 Base::fillTriangleIndices(mesh, buffer);
502
503 mTriangleIndexBuffer.create(buffer, nt * 3, true, releaseFn);
504 }
505
506 void setTriangleNormalsBuffer(const MeshType& mesh) // override
507 {
508 uint nt = Base::numTris();
509
510 auto [buffer, releaseFn] =
511 Context::getAllocatedBufferAndReleaseFn<float>(nt * 3);
512
513 Base::fillTriangleNormals(mesh, buffer);
514
515 mTriangleNormalBuffer.createForCompute(
516 buffer,
517 nt * 3,
518 PrimitiveType::FLOAT,
519 bgfx::Access::Read,
520 releaseFn);
521 }
522
523 void setTriangleColorsBuffer(const MeshType& mesh) // override
524 {
525 uint nt = Base::numTris();
526
527 auto [buffer, releaseFn] =
528 Context::getAllocatedBufferAndReleaseFn<uint>(nt);
529
530 Base::fillTriangleColors(mesh, buffer, Color::Format::ABGR);
531
532 mTriangleColorBuffer.createForCompute(
533 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
534 }
535
536 void setEdgeIndicesBuffer(const MeshType& mesh) // override
537 {
538 computeEdgeLines(mesh);
539 }
540
541 void setWireframeIndicesBuffer(const MeshType& mesh) // override
542 {
543 computeWireframeLines(mesh);
544 }
545
546 void setTextures(const MeshType& mesh) // override
547 {
548 // lambda that sets a texture
549 auto setTexture = [&](const Image& img,
550 const std::string& path,
551 bool generateMips) {
552 const uint size = img.width() * img.height();
553 assert(size > 0);
554
555 uint sizeWithMips = bimg::imageGetSize(
556 nullptr,
557 img.width(),
558 img.height(),
559 1,
560 false,
561 generateMips,
562 1,
563 bimg::TextureFormat::RGBA8) /
564 4; // in uints
565 uint numMips = 1;
566 if (generateMips)
567 numMips = bimg::imageGetNumMips(
568 bimg::TextureFormat::RGBA8, img.width(), img.height());
569
570 auto [buffer, releaseFn] =
571 Context::getAllocatedBufferAndReleaseFn<uint>(sizeWithMips);
572
573 const uint* tdata = reinterpret_cast<const uint*>(img.data());
574
575 std::copy(tdata, tdata + size, buffer); // mip level 0
576
577 if (numMips > 1) {
578 uint* source = buffer;
579 uint* dest;
580 uint offset = size;
581 for (uint mip = 1; mip < numMips; mip++) {
582 dest = source + offset;
583 uint mipSize = (img.width() >> mip) * (img.height() >> mip);
584 bimg::imageRgba8Downsample2x2(
585 dest, // output location
586 img.width() >> (mip - 1), // input width
587 img.height() >> (mip - 1), // input height
588 1, // depth, always 1 for 2D textures
589 (img.width() >> (mip - 1)) * 4, // input pitch
590 (img.width() >> mip) * 4, // output pitch
591 source // input location
592 );
593 source = dest;
594 offset = mipSize;
595 }
596 }
597
598 uint64_t flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE;
599
600 if (img.colorSpace() == Image::ColorSpace::SRGB)
601 flags |= BGFX_TEXTURE_SRGB;
602
603 Texture tex;
604 tex.set(
605 buffer,
606 vcl::Point2i(img.width(), img.height()),
607 generateMips,
608 flags,
609 bgfx::TextureFormat::RGBA8,
610 false,
611 releaseFn);
612
613 // at() does not insert if already present, thus safe in parallel
614 mMaterialTextures.at(path) = std::move(tex);
615 };
616
617 auto loadImageAndSetTexture =
618 [&](const std::pair<std::string, uint>& pathPair) {
619 const std::string& path = pathPair.first;
620
621 uint materialId = pathPair.second / N_TEXTURE_TYPES;
622 uint textureType = pathPair.second % N_TEXTURE_TYPES;
623 // copy the image because it could be not loaded,
624 // and at the end it needs to be mirrored.
625 vcl::Image txtImg = mesh.textureImage(path);
626 if (txtImg.isNull()) { // try to load it just for rendering
627 try {
628 txtImg = vcl::loadImage(mesh.meshBasePath() + path);
630 static_cast<Material::TextureType>(textureType));
631 }
632 catch (...) {
633 // do nothing
634 }
635 if (txtImg.isNull()) {
636 // still null, use a dummy texture
637 txtImg = createCheckBoardImage(512);
638 }
639 }
640
641 // if loading succeeded (or dummy texture has been created)
642 if (!txtImg.isNull()) {
643 const TextureDescriptor& tex =
644 mesh.material(materialId)
645 .textureDescriptor(textureType);
647
649 tex.minFilter();
650
651 bool hasMips =
652 minFilter >= NEAREST_MIPMAP_NEAREST ||
653 minFilter == NONE; // default LINEAR_MIPMAP_LINEAR
654
655 txtImg.mirror();
656 setTexture(txtImg, path, hasMips);
657 }
658 };
659
660 mMaterialTextures.clear();
661
662 if constexpr (vcl::HasMaterials<MeshType>) {
663 // textures could be missing from the textureImages of the mesh
664 // setting the texture paths in a map - key is the path and value is
665 // an uint where materialIndex and textureType are encoded
666 // map is used to avoid duplicates, then is moved to a vector for
667 // parallel processing
668 std::map<std::string, uint> texturePaths;
669 for (uint i = 0; i < mesh.materialCount(); ++i) {
670 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
671 const vcl::TextureDescriptor& td =
672 mesh.material(i).textureDescriptor(j);
673 if (!td.path().empty()) {
674 texturePaths[td.path()] = i * N_TEXTURE_TYPES + j;
675
676 // create a null texture in the map
677 // this is crucial to avoid insertions during the
678 // actual creation, that is done in parallel
679 mMaterialTextures[td.path()] = Texture();
680 }
681 }
682 }
683
684 // move to vector for parallel processing
685 std::vector<std::pair<std::string, uint>> texturePathVec;
686 texturePathVec.reserve(texturePaths.size());
687 for (const auto& tp : texturePaths) {
688 texturePathVec.push_back(tp);
689 }
690
691 parallelFor(texturePathVec, loadImageAndSetTexture);
692
693 createTextureSamplerUniforms();
694 }
695 }
696
697 void setMeshAdditionalData(const MeshType& mesh) // override
698 {
699 if constexpr (HasColor<MeshType>) {
700 mMeshColor = mesh.color();
701 }
702 }
703
704 void computeEdgeLines(const MeshType& mesh)
705 {
706 // if cpu lines, do this...
707
708 // positions
709 const uint nv = Base::numVerts();
710 std::vector<float> positions(nv * 3);
711 Base::fillVertexPositions(mesh, positions.data());
712
713 // indices
714 const uint ne = Base::numEdges();
715 std::vector<uint> indices(ne * 2);
716 Base::fillEdgeIndices(mesh, indices.data());
717
718 // v normals
719 std::vector<float> normals;
720 if (mVertexNormalsBuffer.isValid()) {
721 normals.resize(nv * 3);
722 Base::fillVertexNormals(mesh, normals.data());
723 }
724
725 // todo - edge normals
726
727 // vcolors
728 std::vector<uint> vcolors;
729 if (mVertexColorsBuffer.isValid()) {
730 vcolors.resize(nv);
731 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
732 }
733
734 std::vector<uint> ecolors;
735 if constexpr (vcl::HasPerEdgeColor<MeshType>) {
737 // if (btu[toUnderlying(EDGE_COLORS)]) {
738 // edge color buffer
739 ecolors.resize(ne);
740 Base::fillEdgeColors(mesh, ecolors.data(), Color::Format::ABGR);
741 //}
742 }
743 }
744
745 mEdgeLines.setPoints(positions, indices, normals, vcolors, ecolors);
746
747 // otherwise, already computed buffers should do the job
748 }
749
750 // to generate wireframe lines
751 void computeWireframeLines(const MeshType& mesh)
752 {
753 // if cpu lines, do this...
754
755 // positions
756 const uint nv = Base::numVerts();
757 std::vector<float> positions(nv * 3);
758 Base::fillVertexPositions(mesh, positions.data());
759
760 // indices
761 const uint nw = Base::numWireframeLines();
762 std::vector<uint> indices(nw * 2);
763 Base::fillWireframeIndices(mesh, indices.data());
764
765 // v normals
766 std::vector<float> normals;
767 if (mVertexNormalsBuffer.isValid()) {
768 normals.resize(nv * 3);
769 Base::fillVertexNormals(mesh, normals.data());
770 }
771
772 // vcolors
773 std::vector<uint> vcolors;
774 if (mVertexColorsBuffer.isValid()) {
775 vcolors.resize(nv);
776 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
777 }
778
779 mWireframeLines.setPoints(positions, indices, normals, vcolors, {});
780
781 // otherwise, already computed buffers should do the job
782 }
783
784 static void createTextureSamplerUniforms()
785 {
786 // lazy initialization
787 // to avoid creating uniforms before bgfx is initialized
788 if (!sTextureSamplerUniforms[0].isValid()) {
789 for (uint i = 0; i < sTextureSamplerUniforms.size(); ++i) {
790 sTextureSamplerUniforms[i] = Uniform(
791 Material::TEXTURE_TYPE_NAMES[i].c_str(),
792 bgfx::UniformType::Sampler);
793 }
794 }
795 }
796};
797
798} // namespace vcl
799
800#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:52
The Color class represents a 32 bit color.
Definition color.h:48
static Context & instance(void *windowHandle=nullptr, void *displayHandle=nullptr)
Return the context instance.
Definition context.cpp:371
The DynamicVertexBuffer manages the lifetime of a bgfx::DynamicVertexBufferHandle.
Definition dynamic_vertex_buffer.h:48
void bindCompute(uint stage, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the vertex buffer to the compute shader.
Definition dynamic_vertex_buffer.h:264
void create(uint vertNum, bgfx::Attrib::Enum attrib, uint attribNumPerVertex, PrimitiveType attribType, bool normalize=false, bool allowResize=true)
Creates the dynamic vertex buffer data for rendering, with the layout given by the vertex attributes ...
Definition dynamic_vertex_buffer.h:101
void bind(uint stream, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the dynamic vertex buffer to the rendering pipeline.
Definition dynamic_vertex_buffer.h:242
A class for representing and manipulating 2D images.
Definition image.h:48
void mirror(bool horizontal=false, bool vertical=true)
Flips the image horizontally and/or vertically in-place.
Definition image.h:189
ColorSpace colorSpace() const
Gets the color space of the image.
Definition image.h:151
bool isNull() const
Checks if the image is null or empty.
Definition image.h:127
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:194
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
The Lines class provides an abstraction for rendering 3D lines with variable thickness and different ...
Definition lines.h:56
void draw(uint viewId) const
Draws in the given view the lines with the current settings.
Definition lines.h:428
void setColorToUse(ColorToUse color)
Sets which color to use for rendering the lines.
Definition lines.h:412
float thickness() const
Returns the thickness of the lines (in pixels).
Definition lines.h:336
Color generalColor() const
Returns the general color that is used to render the lines when colorToUse() is set to ColorToUse::GE...
Definition lines.h:363
void setPoints(const std::vector< float > &vertCoords, const std::vector< float > &vertNormals, const std::vector< uint > &vertColors, const std::vector< uint > &lineColors, ImplementationType type=ImplementationType::COUNT)
Sets the points of the lines.
Definition lines.h:237
void setShading(bool perVertex)
Sets wether to use per vertex shading (using vertex normals) or not.
Definition lines.h:392
Represents a Physically-Based Rendering (PBR) material.
Definition material.h:45
TextureType
Defines the types of textures used in the PBR material model.
Definition material.h:62
@ COUNT
Utility value to get the number of texture types.
static Image::ColorSpace textureTypeToColorSpace(TextureType type)
Determines the appropriate color space for a given texture type.
Definition material.h:375
Definition mesh_render_buffers.h:47
void setVertexQuadIndexBuffer(const MeshType &mesh)
The function allocates and fills a GPU index buffer to render a quad for each vertex of the mesh.
Definition mesh_render_buffers.h:382
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
Wireframe
List of possible settings for the wireframe primitive.
Definition mesh_render_info.h:166
Surface
List of possible settings for the surface primitive.
Definition mesh_render_info.h:148
Edges
List of possible settings for the edges primitive.
Definition mesh_render_info.h:180
The MeshRenderSettings class allows an easy management of render settings of a Mesh....
Definition mesh_render_settings.h:70
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:55
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:41
Describes the properties of a texture, such as its source path and rendering parameters.
Definition texture_descriptor.h:42
MinificationFilter
Defines the texture minification filter modes, following the glTF 2.0 specification....
Definition texture_descriptor.h:50
const std::string & path() const
Gets the file path of the texture.
Definition texture_descriptor.h:126
Manages a BGFX texture.
Definition texture.h:45
static uint samplerFlagsFromTexture(const TextureDescriptor &tex)
Generates BGFX sampler flags based on the texture's filtering and wrapping modes.
Definition texture.h:336
The VertexBuffer manages the lifetime of a bgfx::VertexBufferHandle.
Definition vertex_buffer.h:43
void bindCompute(uint stage, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the vertex buffer to the compute shader.
Definition vertex_buffer.h:254
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 createForCompute(const void *bufferData, const uint vertNum, bgfx::Attrib::Enum attrib, uint attribNumPerVertex, PrimitiveType attribType, bool normalize=false, bgfx::Access::Enum access=bgfx::Access::Read, bgfx::ReleaseFn releaseFn=nullptr)
Creates the vertex buffer and sets the data for compute shaders.
Definition vertex_buffer.h:160
void bind(uint stream, bgfx::Access::Enum access=bgfx::Access::Read) const
Bind the vertex buffer to the rendering pipeline.
Definition vertex_buffer.h:232
Concept that is evaluated true if a Mesh has the Materials component.
Definition mesh_requirements.h:88
Concept that checks if a Mesh has the per Edge Color component.
Definition edge_requirements.h:118
constexpr uint UINT_NULL
The UINT_NULL value represent a null value of uint that is the maximum value that can be represented ...
Definition base.h:49
Image createCheckBoardImage(uint imageSize, uint checkNum=8)
Create a checkboard image.
Definition create.h:109
bool isPerEdgeColorAvailable(const MeshType &m)
Returns true if the Color component is available (enabled) in the Edge element of the input mesh m.
Definition edge_requirements.h:370