Visual Computing Library  devel
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/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 mutable DrawableMeshUniforms mMeshUniforms;
83 mutable MaterialUniforms mMaterialUniforms;
84 std::array<Uniform, N_TEXTURE_TYPES> mTextureSamplerUniforms;
85
86public:
87 MeshRenderBuffers() = default;
88
90 const MeshType& mesh,
91 MRI::BuffersBitSet buffersToFill = MRI::BUFFERS_ALL) :
93 {
94 Base::update(mesh, buffersToFill);
95 }
96
98
100
101 MeshRenderBuffers& operator=(const MeshRenderBuffers& other) = delete;
102
104 {
105 swap(other);
106 return *this;
107 }
108
109 void swap(MeshRenderBuffers& other)
110 {
111 using std::swap;
112 Base::swap(other);
113 swap(mVertexPositionsBuffer, other.mVertexPositionsBuffer);
114 swap(mVertexNormalsBuffer, other.mVertexNormalsBuffer);
115 swap(mVertexColorsBuffer, other.mVertexColorsBuffer);
116 swap(mVertexUVBuffer, other.mVertexUVBuffer);
117 swap(mVertexWedgeUVBuffer, other.mVertexWedgeUVBuffer);
118 swap(mVertexTangentsBuffer, other.mVertexTangentsBuffer);
119 swap(mVertexQuadIndexBuffer, other.mVertexQuadIndexBuffer);
120 swap(mVertexQuadBuffer, other.mVertexQuadBuffer);
121 swap(mVertexQuadBufferGenerated, other.mVertexQuadBufferGenerated);
122 swap(mTriangleIndexBuffer, other.mTriangleIndexBuffer);
123 swap(mTriangleNormalBuffer, other.mTriangleNormalBuffer);
124 swap(mTriangleColorBuffer, other.mTriangleColorBuffer);
125 swap(mEdgeLines, other.mEdgeLines);
126 swap(mWireframeLines, other.mWireframeLines);
127 swap(mMaterialTextures, other.mMaterialTextures);
128 swap(mMeshUniforms, other.mMeshUniforms);
129 swap(mMaterialUniforms, other.mMaterialUniforms);
130 swap(mTextureSamplerUniforms, other.mTextureSamplerUniforms);
131 }
132
133 friend void swap(MeshRenderBuffers& a, MeshRenderBuffers& b) { a.swap(b); }
134
135 uint triangleChunksNumber() const { return Base::mMaterialChunks.size(); }
136
137 // to generate splats
138 void computeQuadVertexBuffers(
139 const MeshType& mesh,
140 const bgfx::ViewId viewId) const
141 {
142 if (!mVertexQuadBuffer.isValid() || mVertexQuadBufferGenerated) {
143 return;
144 }
145
146 // fill the buffer using compute shader
147 mVertexPositionsBuffer.bindCompute(
148 VCL_MRB_VERTEX_POSITION_STREAM, bgfx::Access::Read);
149 mVertexNormalsBuffer.bindCompute(
150 VCL_MRB_VERTEX_NORMAL_STREAM, bgfx::Access::Read);
151 mVertexColorsBuffer.bindCompute(
152 VCL_MRB_VERTEX_COLOR_STREAM, bgfx::Access::Read);
153
154 mVertexQuadBuffer.bindCompute(4, bgfx::Access::Write);
155
156 auto& pm = Context::instance().programManager();
157 bgfx::dispatch(
158 viewId,
159 pm.getComputeProgram<ComputeProgram::DRAWABLE_MESH_POINTS>(),
160 mesh.vertexNumber(),
161 1,
162 1);
163
164 mVertexQuadBufferGenerated = true;
165 }
166
167 void bindVertexBuffers(const MeshRenderSettings& mrs) const
168 {
169 uint stream = 0;
170
171 // streams MUST be consecutive starting from 0
172 mVertexPositionsBuffer.bindVertex(stream++);
173
174 if (mVertexNormalsBuffer.isValid()) {
175 mVertexNormalsBuffer.bindVertex(stream++);
176 }
177
178 if (mVertexColorsBuffer.isValid()) {
179 mVertexColorsBuffer.bindVertex(stream++);
180 }
181
182 if (mVertexUVBuffer.isValid()) {
183 mVertexUVBuffer.bind(stream++);
184 }
185
186 if (mVertexWedgeUVBuffer.isValid()) {
187 mVertexWedgeUVBuffer.bind(stream++);
188 }
189
190 if (mVertexTangentsBuffer.isValid()) {
191 mVertexTangentsBuffer.bind(stream++);
192 }
193 }
194
195 // to draw splats
196 void bindVertexQuadBuffer() const
197 {
198 mVertexQuadBuffer.bind(VCL_MRB_VERTEX_POSITION_STREAM);
199 mVertexQuadIndexBuffer.bind();
200 }
201
202 void bindIndexBuffers(
203 const MeshRenderSettings& mrs,
204 uint chunkToBind = UINT_NULL) const
205 {
206 using enum MRI::Buffers;
207
208 if (chunkToBind == UINT_NULL) {
209 mTriangleIndexBuffer.bind();
210 mMeshUniforms.updateFirstChunkIndex(0);
211 }
212 else {
213 const auto& chunk = Base::mMaterialChunks[chunkToBind];
214 mMeshUniforms.updateFirstChunkIndex(chunk.startIndex);
215 mTriangleIndexBuffer.bind(
216 chunk.startIndex * 3, chunk.indexCount * 3);
217 }
218
219 mTriangleNormalBuffer.bind(VCL_MRB_PRIMITIVE_NORMAL_BUFFER);
220
221 mTriangleColorBuffer.bind(VCL_MRB_PRIMITIVE_COLOR_BUFFER);
222 }
223
224 void drawEdgeLines(uint viewId) const { mEdgeLines.draw(viewId); }
225
226 void drawWireframeLines(uint viewId) const { mWireframeLines.draw(viewId); }
227
228 void bindTextures(
229 const MeshRenderSettings& mrs,
230 uint chunkNumber,
231 const MeshType& m) const
232 {
233 uint materialId = Base::materialIndex(mrs, chunkNumber);
234
235 if (materialId != UINT_NULL) {
236 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
237 const auto& td = m.material(materialId).textureDescriptor(j);
238 const std::string& path = td.path();
239 if (!path.empty()) {
240 const Texture& tex = mMaterialTextures.at(path);
241 if (tex.isValid()) {
243 tex.bind(
244 VCL_MRB_TEXTURE0 + j,
245 mTextureSamplerUniforms[j].handle(),
246 flags);
247 }
248 }
249 }
250 }
251 }
252
264 const MeshRenderSettings& mrs,
265 uint chunkNumber,
266 const MeshType& m) const
267 {
268 static const Material DEFAULT_MATERIAL;
269
271
272 std::array<bool, N_TEXTURE_TYPES> textureAvailable = {false};
273
274 if constexpr (!HasMaterials<MeshType>) {
275 // fallback to default material
276 mMaterialUniforms.update(
278 isPerVertexColorAvailable(m),
280 isPerVertexTangentAvailable(m));
281 }
282 else {
283 using enum Material::AlphaMode;
284
285 uint materialId = Base::materialIndex(mrs, chunkNumber);
286
287 if (materialId == UINT_NULL) {
288 // fallback to default material
289 mMaterialUniforms.update(
291 isPerVertexColorAvailable(m),
293 isPerVertexTangentAvailable(m));
294 }
295 else {
296 assert(materialId < m.materialsNumber());
297 const Material& mat = m.material(materialId);
298
299 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
300 const auto& td =
301 m.material(materialId).textureDescriptor(j);
302 const std::string& path = td.path();
303 if (!path.empty()) {
304 const Texture& tex = mMaterialTextures.at(path);
305 textureAvailable[j] = tex.isValid();
306 }
307 }
308
309 mMaterialUniforms.update(
310 m.material(materialId),
311 isPerVertexColorAvailable(m),
313 isPerVertexTangentAvailable(m));
314
315 // set the state according to the material
316 if (!m.material(materialId).doubleSided()) {
317 // backface culling
319 }
320 if (m.material(materialId).alphaMode() == ALPHA_BLEND) {
322 }
323 }
324 }
325
326 mMaterialUniforms.bind();
327 return state;
328 }
329
330 void updateEdgeSettings(const MeshRenderSettings& mrs)
331 {
332 using enum MeshRenderInfo::Edges;
333 using enum Lines::ColorToUse;
334
335 mEdgeLines.thickness() = mrs.edgesWidth();
336 mEdgeLines.setShading(mrs.isEdges(SHADING_SMOOTH));
337
338 if (mrs.isEdges(COLOR_USER)) {
339 mEdgeLines.generalColor() = mrs.edgesUserColor();
340 mEdgeLines.setColorToUse(GENERAL);
341 }
342 else if (mrs.isEdges(COLOR_MESH)) {
343 mEdgeLines.generalColor() = mMeshColor;
344 mEdgeLines.setColorToUse(GENERAL);
345 }
346 else if (mrs.isEdges(COLOR_VERTEX)) {
347 mEdgeLines.setColorToUse(PER_VERTEX);
348 }
349 else if (mrs.isEdges(COLOR_EDGE)) {
350 mEdgeLines.setColorToUse(PER_EDGE);
351 }
352 }
353
354 void updateWireframeSettings(const MeshRenderSettings& mrs)
355 {
356 using enum MeshRenderInfo::Wireframe;
357 using enum Lines::ColorToUse;
358
359 mWireframeLines.thickness() = mrs.wireframeWidth();
360 mWireframeLines.setShading(mrs.isWireframe(SHADING_VERT));
361
362 if (mrs.isWireframe(COLOR_USER)) {
363 mWireframeLines.generalColor() = mrs.wireframeUserColor();
364 mWireframeLines.setColorToUse(GENERAL);
365 }
366 else if (mrs.isWireframe(COLOR_MESH)) {
367 mWireframeLines.generalColor() = mMeshColor;
368 mWireframeLines.setColorToUse(GENERAL);
369 }
370 else if (mrs.isWireframe(COLOR_VERTEX)) {
371 mWireframeLines.setColorToUse(PER_VERTEX);
372 }
373 }
374
375 void bindUniforms() const { mMeshUniforms.bind(); }
376
377private:
378 void setVertexPositionsBuffer(const MeshType& mesh) // override
379 {
380 uint nv = Base::numVerts();
381
382 auto [buffer, releaseFn] =
383 getAllocatedBufferAndReleaseFn<float>(nv * 3);
384
385 Base::fillVertexPositions(mesh, buffer);
386
387 mVertexPositionsBuffer.createForCompute(
388 buffer,
389 nv,
390 bgfx::Attrib::Position,
391 3,
392 PrimitiveType::FLOAT,
393 false,
394 bgfx::Access::Read,
395 releaseFn);
396
397 // Creates the buffers to be used with compute for splatting
398 if (Context::instance().supportsCompute()) {
399 // create a layout <coordinates, colors, normals, float>
400 // 2 X vec4
401 bgfx::VertexLayout layout;
402 layout.begin()
403 .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
404 .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
405 .add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float)
406 .add(bgfx::Attrib::TexCoord0, 1, bgfx::AttribType::Float)
407 .end();
408
409 // create the dynamic vertex buffer for splatting
410 mVertexQuadBuffer.create(
411 mesh.vertexNumber() * 4, layout, BGFX_BUFFER_COMPUTE_WRITE);
412
413 // create the index buffer for splatting
415
416 // record that the vertex quad buffer must be generated
417 mVertexQuadBufferGenerated = false;
418 }
419 }
420
428 {
429 const uint totalIndices = mesh.vertexNumber() * 6;
430
431 auto [buffer, releaseFn] =
433
434 Base::fillVertexQuadIndices(mesh, buffer);
435
436 mVertexQuadIndexBuffer.create(buffer, totalIndices, true, releaseFn);
437
438 // if number of vertices is not zero, the index buffer must be valid
439 assert(mVertexQuadIndexBuffer.isValid() || totalIndices == 0);
440 }
441
442 void setVertexNormalsBuffer(const MeshType& mesh) // override
443 {
444 uint nv = Base::numVerts();
445
446 auto [buffer, releaseFn] =
448
449 Base::fillVertexNormals(mesh, buffer);
450
451 mVertexNormalsBuffer.createForCompute(
452 buffer,
453 nv,
454 bgfx::Attrib::Normal,
455 3,
456 PrimitiveType::FLOAT,
457 false,
458 bgfx::Access::Read,
459 releaseFn);
460 }
461
462 void setVertexColorsBuffer(const MeshType& mesh) // override
463 {
464 uint nv = Base::numVerts();
465
466 auto [buffer, releaseFn] = getAllocatedBufferAndReleaseFn<uint>(nv);
467
468 Base::fillVertexColors(mesh, buffer, Color::Format::ABGR);
469
470 mVertexColorsBuffer.createForCompute(
471 buffer,
472 nv,
473 bgfx::Attrib::Color0,
474 4,
475 PrimitiveType::UCHAR,
476 true,
477 bgfx::Access::Read,
478 releaseFn);
479 }
480
481 void setVertexTexCoordsBuffer(const MeshType& mesh) // override
482 {
483 uint nv = Base::numVerts();
484
485 auto [buffer, releaseFn] =
486 getAllocatedBufferAndReleaseFn<float>(nv * 2);
487
488 Base::fillVertexTexCoords(mesh, buffer);
489
490 mVertexUVBuffer.create(
491 buffer,
492 nv,
493 bgfx::Attrib::TexCoord0,
494 2,
495 PrimitiveType::FLOAT,
496 false,
497 releaseFn);
498 }
499
500 void setVertexTangentsBuffer(const MeshType& mesh) // override
501 {
502 uint nv = Base::numVerts();
503
504 auto [buffer, releaseFn] =
505 getAllocatedBufferAndReleaseFn<float>(nv * 4);
506
507 Base::fillVertexTangents(mesh, buffer);
508
509 mVertexTangentsBuffer.create(
510 buffer,
511 nv,
512 bgfx::Attrib::Tangent,
513 4,
514 PrimitiveType::FLOAT,
515 false,
516 releaseFn);
517 }
518
519 void setWedgeTexCoordsBuffer(const MeshType& mesh) // override
520 {
521 uint nv = Base::numVerts();
522
523 auto [buffer, releaseFn] =
524 getAllocatedBufferAndReleaseFn<float>(nv * 2);
525
526 Base::fillWedgeTexCoords(mesh, buffer);
527
528 mVertexWedgeUVBuffer.create(
529 buffer,
530 nv,
531 bgfx::Attrib::TexCoord1,
532 2,
533 PrimitiveType::FLOAT,
534 false,
535 releaseFn);
536 }
537
538 void setTriangleIndicesBuffer(const MeshType& mesh) // override
539 {
540 uint nt = Base::numTris();
541
542 auto [buffer, releaseFn] = getAllocatedBufferAndReleaseFn<uint>(nt * 3);
543
544 Base::fillTriangleIndices(mesh, buffer);
545
546 mTriangleIndexBuffer.create(buffer, nt * 3, true, releaseFn);
547 }
548
549 void setTriangleNormalsBuffer(const MeshType& mesh) // override
550 {
551 uint nt = Base::numTris();
552
553 auto [buffer, releaseFn] =
554 getAllocatedBufferAndReleaseFn<float>(nt * 3);
555
556 Base::fillTriangleNormals(mesh, buffer);
557
558 mTriangleNormalBuffer.createForCompute(
559 buffer,
560 nt * 3,
561 PrimitiveType::FLOAT,
562 bgfx::Access::Read,
563 releaseFn);
564 }
565
566 void setTriangleColorsBuffer(const MeshType& mesh) // override
567 {
568 uint nt = Base::numTris();
569
570 auto [buffer, releaseFn] = getAllocatedBufferAndReleaseFn<uint>(nt);
571
572 Base::fillTriangleColors(mesh, buffer, Color::Format::ABGR);
573
574 mTriangleColorBuffer.createForCompute(
575 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
576 }
577
578 void setEdgeIndicesBuffer(const MeshType& mesh) // override
579 {
580 computeEdgeLines(mesh);
581 }
582
583 void setWireframeIndicesBuffer(const MeshType& mesh) // override
584 {
585 computeWireframeLines(mesh);
586 }
587
588 void setTextures(const MeshType& mesh) // override
589 {
590 // lambda that sets a texture
591 auto setTexture = [&](const Image& img,
592 const std::string& path,
593 bool generateMips) {
594 const uint size = img.width() * img.height();
595 assert(size > 0);
596
597 uint sizeWithMips = bimg::imageGetSize(
598 nullptr,
599 img.width(),
600 img.height(),
601 1,
602 false,
603 generateMips,
604 1,
605 bimg::TextureFormat::RGBA8) /
606 4; // in uints
607 uint numMips = 1;
608 if (generateMips)
609 numMips = bimg::imageGetNumMips(
610 bimg::TextureFormat::RGBA8, img.width(), img.height());
611
612 auto [buffer, releaseFn] =
613 getAllocatedBufferAndReleaseFn<uint>(sizeWithMips);
614
615 const uint* tdata = reinterpret_cast<const uint*>(img.data());
616
617 std::copy(tdata, tdata + size, buffer); // mip level 0
618
619 if (numMips > 1) {
620 uint* source = buffer;
621 uint* dest;
622 uint offset = size;
623 for (uint mip = 1; mip < numMips; mip++) {
624 dest = source + offset;
625 uint mipSize = (img.width() >> mip) * (img.height() >> mip);
626 bimg::imageRgba8Downsample2x2(
627 dest, // output location
628 img.width() >> (mip - 1), // input width
629 img.height() >> (mip - 1), // input height
630 1, // depth, always 1 for 2D textures
631 (img.width() >> (mip - 1)) * 4, // input pitch
632 (img.width() >> mip) * 4, // output pitch
633 source // input location
634 );
635 source = dest;
636 offset = mipSize;
637 }
638 }
639
640 uint64_t flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE;
641
642 if (img.colorSpace() == Image::ColorSpace::SRGB)
643 flags |= BGFX_TEXTURE_SRGB;
644
645 Texture tex;
646 tex.set(
647 buffer,
648 vcl::Point2i(img.width(), img.height()),
649 generateMips,
650 flags,
651 releaseFn);
652
653 // at() does not insert if already present, thus safe in parallel
654 mMaterialTextures.at(path) = std::move(tex);
655 };
656
657 auto loadImageAndSetTexture =
658 [&](const std::pair<std::string, uint>& pathPair) {
659 const std::string& path = pathPair.first;
660
661 uint materialId = pathPair.second / N_TEXTURE_TYPES;
662 uint textureType = pathPair.second % N_TEXTURE_TYPES;
663 // copy the image because it could be not loaded,
664 // and at the end it needs to be mirrored.
665 vcl::Image txtImg = mesh.textureImage(path);
666 if (txtImg.isNull()) { // try to load it just for rendering
667 try {
668 txtImg = vcl::loadImage(mesh.meshBasePath() + path);
670 static_cast<Material::TextureType>(textureType));
671 }
672 catch (...) {
673 // do nothing
674 }
675 if (txtImg.isNull()) {
676 // still null, use a dummy texture
677 txtImg = createCheckBoardImage(512);
678 }
679 }
680
681 // if loading succeeded (or dummy texture has been created)
682 if (!txtImg.isNull()) {
683 const TextureDescriptor& tex =
684 mesh.material(materialId)
685 .textureDescriptor(textureType);
687
689 tex.minFilter();
690
691 bool hasMips =
692 minFilter >= NEAREST_MIPMAP_NEAREST ||
693 minFilter == NONE; // default LINEAR_MIPMAP_LINEAR
694
695 txtImg.mirror();
696 setTexture(txtImg, path, hasMips);
697 }
698 };
699
700 mMaterialTextures.clear();
701
702 if constexpr (vcl::HasMaterials<MeshType>) {
703 // textures could be missing from the textureImages of the mesh
704 // setting the texture paths in a map - key is the path and value is
705 // an uint where materialIndex and textureType are encoded
706 // map is used to avoid duplicates, then is moved to a vector for
707 // parallel processing
708 std::map<std::string, uint> texturePaths;
709 for (uint i = 0; i < mesh.materialsNumber(); ++i) {
710 for (uint j = 0; j < N_TEXTURE_TYPES; ++j) {
711 const vcl::TextureDescriptor& td =
712 mesh.material(i).textureDescriptor(j);
713 if (!td.path().empty()) {
714 texturePaths[td.path()] = i * N_TEXTURE_TYPES + j;
715
716 // create a null texture in the map
717 // this is crucial to avoid insertions during the
718 // actual creation, that is done in parallel
719 mMaterialTextures[td.path()] = Texture();
720 }
721 }
722 }
723
724 // move to vector for parallel processing
725 std::vector<std::pair<std::string, uint>> texturePathVec;
726 texturePathVec.reserve(texturePaths.size());
727 for (const auto& tp : texturePaths) {
728 texturePathVec.push_back(tp);
729 }
730
731 parallelFor(texturePathVec, loadImageAndSetTexture);
732
733 createTextureSamplerUniforms();
734 }
735 }
736
737 void setMeshUniforms(const MeshType& mesh) // override
738 {
739 mMeshUniforms.update(mesh);
740 if constexpr (HasColor<MeshType>) {
741 mMeshColor = mesh.color();
742 }
743 }
744
745 void computeEdgeLines(const MeshType& mesh)
746 {
747 // if cpu lines, do this...
748
749 // positions
750 const uint nv = Base::numVerts();
751 std::vector<float> positions(nv * 3);
752 Base::fillVertexPositions(mesh, positions.data());
753
754 // indices
755 const uint ne = Base::numEdges();
756 std::vector<uint> indices(ne * 2);
757 Base::fillEdgeIndices(mesh, indices.data());
758
759 // v normals
760 std::vector<float> normals;
761 if (mVertexNormalsBuffer.isValid()) {
762 normals.resize(nv * 3);
763 Base::fillVertexNormals(mesh, normals.data());
764 }
765
766 // todo - edge normals
767
768 // vcolors
769 std::vector<uint> vcolors;
770 if (mVertexColorsBuffer.isValid()) {
771 vcolors.resize(nv);
772 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
773 }
774
775 std::vector<uint> ecolors;
776 if constexpr (vcl::HasPerEdgeColor<MeshType>) {
778 // if (btu[toUnderlying(EDGE_COLORS)]) {
779 // edge color buffer
780 ecolors.resize(ne);
781 Base::fillEdgeColors(mesh, ecolors.data(), Color::Format::ABGR);
782 //}
783 }
784 }
785
786 mEdgeLines.setPoints(positions, indices, normals, vcolors, ecolors);
787
788 // otherwise, already computed buffers should do the job
789 }
790
791 // to generate wireframe lines
792 void computeWireframeLines(const MeshType& mesh)
793 {
794 // if cpu lines, do this...
795
796 // positions
797 const uint nv = Base::numVerts();
798 std::vector<float> positions(nv * 3);
799 Base::fillVertexPositions(mesh, positions.data());
800
801 // indices
802 const uint nw = Base::numWireframeLines();
803 std::vector<uint> indices(nw * 2);
804 Base::fillWireframeIndices(mesh, indices.data());
805
806 // v normals
807 std::vector<float> normals;
808 if (mVertexNormalsBuffer.isValid()) {
809 normals.resize(nv * 3);
810 Base::fillVertexNormals(mesh, normals.data());
811 }
812
813 // vcolors
814 std::vector<uint> vcolors;
815 if (mVertexColorsBuffer.isValid()) {
816 vcolors.resize(nv);
817 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
818 }
819
820 mWireframeLines.setPoints(positions, indices, normals, vcolors, {});
821
822 // otherwise, already computed buffers should do the job
823 }
824
825 void createTextureSamplerUniforms()
826 {
827 for (uint i = 0; i < mTextureSamplerUniforms.size(); ++i) {
828 mTextureSamplerUniforms[i] = Uniform(
829 Material::TEXTURE_TYPE_NAMES[i].c_str(),
830 bgfx::UniformType::Sampler);
831 }
832 }
833
834 template<typename T>
835 std::pair<T*, bgfx::ReleaseFn> getAllocatedBufferAndReleaseFn(uint size)
836 {
837 T* buffer = new T[size];
838
839 return std::make_pair(buffer, [](void* ptr, void*) {
840 delete[] static_cast<T*>(ptr);
841 });
842 }
843};
844
845} // namespace vcl
846
847#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
A class representing a box in N-dimensional space.
Definition box.h:46
void add(const PointT &p)
Adds the given point to the current box, expanding this box in order to contain also the values of th...
Definition box.h:385
PointT size() const
Computes the size of the box.
Definition box.h:267
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
Definition drawable_mesh_uniforms.h:32
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:427
void setColorToUse(ColorToUse color)
Sets which color to use for rendering the lines.
Definition lines.h:411
float thickness() const
Returns the thickness of the lines (in pixels).
Definition lines.h:335
Color generalColor() const
Returns the general color that is used to render the lines when colorToUse() is set to ColorToUse::GE...
Definition lines.h:362
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:236
void setShading(bool perVertex)
Sets wether to use per vertex shading (using vertex normals) or not.
Definition lines.h:391
Definition material_uniforms.h:34
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
AlphaMode
Defines the alpha rendering mode of the material.
Definition material.h:50
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:427
uint64_t bindMaterials(const MeshRenderSettings &mrs, uint chunkNumber, const MeshType &m) const
Sets and binds the material uniforms for the given triangle chunk, and returns the render state assoc...
Definition mesh_render_buffers.h:263
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
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
bool isEdges(MeshRenderInfo::Edges e) const
Returns whether the given edges option is set.
Definition mesh_render_settings.h:295
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
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:43
static uint samplerFlagsFromTexture(const TextureDescriptor &tex)
Generates BGFX sampler flags based on the texture's filtering and wrapping modes.
Definition texture.h:232
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:48
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