54 inline static const uint N_TEXTURE_TYPES =
67 mutable bool mVertexQuadBufferGenerated =
false;
75 Lines mWireframeLines;
80 std::map<std::string, Texture> mMaterialTextures;
82 static inline std::array<Uniform, N_TEXTURE_TYPES> sTextureSamplerUniforms;
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);
131 void computeQuadVertexBuffers(
133 const bgfx::ViewId viewId)
const
135 if (!mVertexQuadBuffer.isValid() || mVertexQuadBufferGenerated) {
141 VCL_MRB_VERTEX_POSITION_STREAM, bgfx::Access::Read);
143 VCL_MRB_VERTEX_NORMAL_STREAM, bgfx::Access::Read);
145 VCL_MRB_VERTEX_COLOR_STREAM, bgfx::Access::Read);
147 mVertexQuadBuffer.
bindCompute(4, bgfx::Access::Write);
152 pm.getComputeProgram<ComputeProgram::DRAWABLE_MESH_POINTS>(),
157 mVertexQuadBufferGenerated =
true;
174 mVertexPositionsBuffer.bindVertex(
stream++);
176 if (mVertexNormalsBuffer.isValid()) {
179 mVertexNormalsBuffer.bindVertex(
stream++);
182 if (mVertexTangentsBuffer.isValid()) {
188 if (mVertexColorsBuffer.isValid()) {
191 mVertexColorsBuffer.bindVertex(
stream++);
194 if (mVertexUVBuffer.isValid() &&
mrs.isSurface(COLOR_VERTEX_TEX)) {
200 if (mVertexWedgeUVBuffer.isValid() &&
mrs.isSurface(COLOR_WEDGE_TEX)) {
208 void bindVertexQuadBuffer()
const
210 mVertexQuadBuffer.
bind(VCL_MRB_VERTEX_POSITION_STREAM);
211 mVertexQuadIndexBuffer.
bind();
214 void bindIndexBuffers(
218 using enum MRI::Buffers;
221 mTriangleIndexBuffer.
bind();
225 mTriangleIndexBuffer.
bind(
229 mTriangleNormalBuffer.
bind(VCL_MRB_PRIMITIVE_NORMAL_BUFFER);
231 mTriangleColorBuffer.
bind(VCL_MRB_PRIMITIVE_COLOR_BUFFER);
234 void drawEdgeLines(uint viewId)
const { mEdgeLines.
draw(viewId); }
236 void drawWireframeLines(uint viewId)
const { mWireframeLines.
draw(viewId); }
246 for (uint
j = 0;
j < N_TEXTURE_TYPES; ++
j) {
248 const std::string& path =
td.path();
250 const Texture&
tex = mMaterialTextures.at(path);
254 VCL_MRB_TEXTURE0 +
j,
255 sTextureSamplerUniforms[
j].handle(),
263 std::array<bool, N_TEXTURE_TYPES> textureAvailableArray(
275 for (uint
j = 0;
j < N_TEXTURE_TYPES; ++
j) {
277 const std::string& path =
td.path();
279 const Texture&
tex = mMaterialTextures.at(path);
290 using enum Lines::ColorToUse;
295 if (
mrs.isEdges(COLOR_USER)) {
299 else if (
mrs.isEdges(COLOR_MESH)) {
303 else if (
mrs.isEdges(COLOR_VERTEX)) {
306 else if (
mrs.isEdges(COLOR_EDGE)) {
314 using enum Lines::ColorToUse;
319 if (
mrs.isWireframe(COLOR_USER)) {
323 else if (
mrs.isWireframe(COLOR_MESH)) {
327 else if (
mrs.isWireframe(COLOR_VERTEX)) {
333 void setVertexPositionsBuffer(
const MeshType& mesh)
335 uint
nv = Base::numVerts();
338 Context::getAllocatedBufferAndReleaseFn<float>(
nv * 3);
340 Base::fillVertexPositions(mesh, buffer);
345 bgfx::Attrib::Position,
347 PrimitiveType::FLOAT,
356 bgfx::VertexLayout
layout;
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)
372 mVertexQuadBufferGenerated =
false;
387 Context::getAllocatedBufferAndReleaseFn<uint>(
totalIndices);
389 Base::fillVertexQuadIndices(mesh, buffer);
397 void setVertexNormalsBuffer(
const MeshType& mesh)
399 uint
nv = Base::numVerts();
402 Context::getAllocatedBufferAndReleaseFn<float>(
nv * 3);
404 Base::fillVertexNormals(mesh, buffer);
409 bgfx::Attrib::Normal,
411 PrimitiveType::FLOAT,
417 void setVertexColorsBuffer(
const MeshType& mesh)
419 uint nv = Base::numVerts();
421 auto [buffer, releaseFn] =
422 Context::getAllocatedBufferAndReleaseFn<uint>(nv);
424 Base::fillVertexColors(mesh, buffer, Color::Format::ABGR);
429 bgfx::Attrib::Color0,
431 PrimitiveType::UCHAR,
437 void setVertexTexCoordsBuffer(
const MeshType& mesh)
439 uint nv = Base::numVerts();
441 auto [buffer, releaseFn] =
442 Context::getAllocatedBufferAndReleaseFn<float>(nv * 2);
444 Base::fillVertexTexCoords(mesh, buffer);
449 bgfx::Attrib::TexCoord0,
451 PrimitiveType::FLOAT,
456 void setVertexTangentsBuffer(
const MeshType& mesh)
458 uint nv = Base::numVerts();
460 auto [buffer, releaseFn] =
461 Context::getAllocatedBufferAndReleaseFn<float>(nv * 4);
463 Base::fillVertexTangents(mesh, buffer);
465 mVertexTangentsBuffer.
create(
468 bgfx::Attrib::Tangent,
470 PrimitiveType::FLOAT,
475 void setWedgeTexCoordsBuffer(
const MeshType& mesh)
477 uint nv = Base::numVerts();
479 auto [buffer, releaseFn] =
480 Context::getAllocatedBufferAndReleaseFn<float>(nv * 2);
482 Base::fillWedgeTexCoords(mesh, buffer);
484 mVertexWedgeUVBuffer.
create(
487 bgfx::Attrib::TexCoord1,
489 PrimitiveType::FLOAT,
494 void setTriangleIndicesBuffer(
const MeshType& mesh)
496 uint nt = Base::numTris();
498 auto [buffer, releaseFn] =
499 Context::getAllocatedBufferAndReleaseFn<uint>(nt * 3);
501 Base::fillTriangleIndices(mesh, buffer);
503 mTriangleIndexBuffer.
create(buffer, nt * 3,
true, releaseFn);
506 void setTriangleNormalsBuffer(
const MeshType& mesh)
508 uint nt = Base::numTris();
510 auto [buffer, releaseFn] =
511 Context::getAllocatedBufferAndReleaseFn<float>(nt * 3);
513 Base::fillTriangleNormals(mesh, buffer);
518 PrimitiveType::FLOAT,
523 void setTriangleColorsBuffer(
const MeshType& mesh)
525 uint nt = Base::numTris();
527 auto [buffer, releaseFn] =
528 Context::getAllocatedBufferAndReleaseFn<uint>(nt);
530 Base::fillTriangleColors(mesh, buffer, Color::Format::ABGR);
533 buffer, nt, PrimitiveType::UINT, bgfx::Access::Read, releaseFn);
536 void setEdgeIndicesBuffer(
const MeshType& mesh)
538 computeEdgeLines(mesh);
541 void setWireframeIndicesBuffer(
const MeshType& mesh)
543 computeWireframeLines(mesh);
546 void setTextures(
const MeshType& mesh)
549 auto setTexture = [&](
const Image& img,
550 const std::string& path,
552 const uint size = img.width() * img.height();
555 uint sizeWithMips = bimg::imageGetSize(
563 bimg::TextureFormat::RGBA8) /
567 numMips = bimg::imageGetNumMips(
568 bimg::TextureFormat::RGBA8, img.width(), img.height());
570 auto [buffer, releaseFn] =
571 Context::getAllocatedBufferAndReleaseFn<uint>(sizeWithMips);
573 const uint* tdata =
reinterpret_cast<const uint*
>(img.data());
575 std::copy(tdata, tdata + size, buffer);
578 uint* source = buffer;
581 for (uint mip = 1; mip < numMips; mip++) {
582 dest = source + offset;
583 uint mipSize = (img.width() >> mip) * (img.height() >> mip);
584 bimg::imageRgba8Downsample2x2(
586 img.width() >> (mip - 1),
587 img.height() >> (mip - 1),
589 (img.width() >> (mip - 1)) * 4,
590 (img.width() >> mip) * 4,
598 uint64_t flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE;
600 if (img.colorSpace() == Image::ColorSpace::SRGB)
601 flags |= BGFX_TEXTURE_SRGB;
609 bgfx::TextureFormat::RGBA8,
614 mMaterialTextures.at(path) = std::move(tex);
617 auto loadImageAndSetTexture =
618 [&](
const std::pair<std::string, uint>& pathPair) {
619 const std::string& path = pathPair.first;
621 uint materialId = pathPair.second / N_TEXTURE_TYPES;
622 uint textureType = pathPair.second % N_TEXTURE_TYPES;
628 txtImg = vcl::loadImage(mesh.meshBasePath() + path);
643 const TextureDescriptor& tex =
644 mesh.material(materialId)
645 .textureDescriptor(textureType);
652 minFilter >= NEAREST_MIPMAP_NEAREST ||
656 setTexture(txtImg, path, hasMips);
660 mMaterialTextures.clear();
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) {
672 mesh.material(i).textureDescriptor(j);
673 if (!td.
path().empty()) {
674 texturePaths[td.
path()] = i * N_TEXTURE_TYPES + j;
679 mMaterialTextures[td.
path()] = Texture();
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);
691 parallelFor(texturePathVec, loadImageAndSetTexture);
693 createTextureSamplerUniforms();
697 void setMeshAdditionalData(
const MeshType& mesh)
699 if constexpr (HasColor<MeshType>) {
700 mMeshColor = mesh.color();
704 void computeEdgeLines(
const MeshType& mesh)
709 const uint nv = Base::numVerts();
710 std::vector<float> positions(nv * 3);
711 Base::fillVertexPositions(mesh, positions.data());
714 const uint ne = Base::numEdges();
715 std::vector<uint> indices(ne * 2);
716 Base::fillEdgeIndices(mesh, indices.data());
719 std::vector<float> normals;
720 if (mVertexNormalsBuffer.isValid()) {
721 normals.resize(nv * 3);
722 Base::fillVertexNormals(mesh, normals.data());
728 std::vector<uint> vcolors;
729 if (mVertexColorsBuffer.isValid()) {
731 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
734 std::vector<uint> ecolors;
740 Base::fillEdgeColors(mesh, ecolors.data(), Color::Format::ABGR);
745 mEdgeLines.
setPoints(positions, indices, normals, vcolors, ecolors);
751 void computeWireframeLines(
const MeshType& mesh)
756 const uint nv = Base::numVerts();
757 std::vector<float> positions(nv * 3);
758 Base::fillVertexPositions(mesh, positions.data());
761 const uint nw = Base::numWireframeLines();
762 std::vector<uint> indices(nw * 2);
763 Base::fillWireframeIndices(mesh, indices.data());
766 std::vector<float> normals;
767 if (mVertexNormalsBuffer.isValid()) {
768 normals.resize(nv * 3);
769 Base::fillVertexNormals(mesh, normals.data());
773 std::vector<uint> vcolors;
774 if (mVertexColorsBuffer.isValid()) {
776 Base::fillVertexColors(mesh, vcolors.data(), Color::Format::ABGR);
779 mWireframeLines.
setPoints(positions, indices, normals, vcolors, {});
784 static void createTextureSamplerUniforms()
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);