From 08907567b034c0b8d535f670406f264e95d7783a Mon Sep 17 00:00:00 2001 From: devZoGok Date: Sun, 15 Jun 2025 18:41:52 +0300 Subject: [PATCH] only loading one's model data to the GPU once --- box.cpp | 1 - mesh.cpp | 66 ++++++-------------------------- mesh.h | 2 - meshData.cpp | 75 ++++++++++++++++++++++++++++++++++++ meshData.h | 95 +++++++++++++++++++--------------------------- model.cpp | 16 +++----- quad.cpp | 1 - xmlModelReader.cpp | 19 +++++++++- 8 files changed, 150 insertions(+), 125 deletions(-) diff --git a/box.cpp b/box.cpp index 671656b..8901662 100755 --- a/box.cpp +++ b/box.cpp @@ -3,7 +3,6 @@ namespace vb01{ Box::Box(Vector3 size){ setSize(size); - construct(); } void Box::setSize(Vector3 size){ diff --git a/mesh.cpp b/mesh.cpp index 64de30e..91cf395 100755 --- a/mesh.cpp +++ b/mesh.cpp @@ -30,51 +30,7 @@ namespace vb01{ for(Mesh *m : meshes) delete m; - if(material) - delete material; - - glDeleteVertexArrays(1, &VAO); - glDeleteBuffers(1, &EBO); - glDeleteBuffers(1, &VBO); - } - - //TODO allow to init meshes to be drawn statically or dynamically - void Mesh::construct(){ - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - - u32 size = sizeof(MeshData::GpuVertex); - - glBindVertexArray(VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - - MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); - glBufferData(GL_ARRAY_BUFFER, 3 * meshBase.numTris * size, glVertData, GL_DYNAMIC_DRAW); - delete glVertData; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * meshBase.numTris * sizeof(u32), meshBase.indices, GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, size, (void*)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, norm))); - glEnableVertexAttribArray(1); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, uv))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, tan))); - glEnableVertexAttribArray(3); - glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, biTan))); - glEnableVertexAttribArray(4); - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, weights))); - glEnableVertexAttribArray(5); - glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, boneIndices))); - glEnableVertexAttribArray(6); - - for(int i = 0; i < meshBase.numShapeKeys; i++){ - glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float))); - glEnableVertexAttribArray(7 + i); - } + if(material) delete material; } void Mesh::initFramebuffer(u32 &framebuffer, u32 &renderbuffer, int width){ @@ -94,7 +50,7 @@ namespace vb01{ } void Mesh::updateVerts(MeshData meshData){ - glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBindBuffer(GL_ARRAY_BUFFER, meshData.VBO); MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(MeshData::GpuVertex) * meshBase.numTris, glVertData); @@ -130,8 +86,15 @@ namespace vb01{ float fov = cam->getFov(), width = root->getWidth(), height = root->getHeight(), nearPlane = cam->getNearPlane(), farPlane = cam->getFarPlane(); mat4 proj = perspective(radians(fov), width / height, nearPlane, farPlane); - material->update(); Shader *shader = material->getShader(); + material->update(); + + shader->setBool(castShadow, "castShadow"); + shader->setBool(skeleton, "animated"); + shader->setMat4(view, "view"); + shader->setMat4(proj, "proj"); + shader->setVec3(camPos, "camPos"); + shader->setMat4(model, "model"); if(skeleton) updateSkeleton(shader); @@ -142,13 +105,6 @@ namespace vb01{ if(reflect) updateReflection(pos); - shader->setBool(castShadow, "castShadow"); - shader->setBool(skeleton, "animated"); - shader->setMat4(view, "view"); - shader->setMat4(proj, "proj"); - shader->setVec3(camPos, "camPos"); - shader->setMat4(model, "model"); - if(shader->getName() == "gui"){ shader->setVec2(Vector2((float)width, (float)height), "screen"); @@ -401,7 +357,7 @@ namespace vb01{ } void Mesh::render(){ - glBindVertexArray(VAO); + glBindVertexArray(meshBase.VAO); glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); glDrawElements(GL_TRIANGLES, 3 * meshBase.numTris, GL_UNSIGNED_INT, 0); } diff --git a/mesh.h b/mesh.h index 6d69172..099f259 100755 --- a/mesh.h +++ b/mesh.h @@ -20,7 +20,6 @@ namespace vb01{ public: Mesh(MeshData); ~Mesh(); - void construct(); void updateVerts(MeshData); virtual void update(); void render(); @@ -67,7 +66,6 @@ namespace vb01{ int numShapeKeys = 0; MeshData::ShapeKey *shapeKeys = nullptr; bool castShadow = false, reflect = false, reflective = false, wireframe = false; - u32 VAO, VBO, EBO; }; } diff --git a/meshData.cpp b/meshData.cpp index ba7572b..4e384ce 100644 --- a/meshData.cpp +++ b/meshData.cpp @@ -1,8 +1,83 @@ #include "meshData.h" +#include "glad.h" +#include +#include +#include + using namespace std; namespace vb01{ + //TODO allow to init meshes to be drawn statically or dynamically + MeshData::MeshData( + Vector3 *pos, + float **w, + int **bi, + Vector3 **sko, + int np, + Vector3 *norm, + Vertex *vert, + u32 *ind, + int nt, + std::string an, + std::string *vg, + int nvg, + std::string fsn, + ShapeKey *sk, + int nsk + ) : + positions(pos), + weights(w), + boneIndices(bi), + shapeKeyOffsets(sko), + numPos(np), + normals(norm), + vertices(vert), + indices(ind), + numTris(nt), + vertexGroups(vg), + numVertexGroups(nvg), + fullSkeletonName(fsn), + shapeKeys(sk), + numShapeKeys(nsk) + { + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); + + u32 size = sizeof(MeshData::GpuVertex); + + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + MeshData::GpuVertex *glVertData = toGpuVerts(); + glBufferData(GL_ARRAY_BUFFER, 3 * numTris * size, glVertData, GL_DYNAMIC_DRAW); + delete glVertData; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * numTris * sizeof(u32), indices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, size, (void*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, norm))); + glEnableVertexAttribArray(1); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, uv))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, tan))); + glEnableVertexAttribArray(3); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, biTan))); + glEnableVertexAttribArray(4); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, weights))); + glEnableVertexAttribArray(5); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, boneIndices))); + glEnableVertexAttribArray(6); + + for(int i = 0; i < numShapeKeys; i++){ + glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float))); + glEnableVertexAttribArray(7 + i); + } + } + void MeshData::ShapeKey::animate(float value, KeyframeChannel keyframeChannel){ switch(keyframeChannel.type){ case KeyframeChannel::SHAPE_KEY_MIN: diff --git a/meshData.h b/meshData.h index 6ca0ced..add53c6 100644 --- a/meshData.h +++ b/meshData.h @@ -9,62 +9,47 @@ #include "animatable.h" namespace vb01{ - struct MeshData{ - struct ShapeKey : public Animatable{ - std::string name; - float minValue, value, maxValue; - - ShapeKey(std::string n, float v, float mnv, float mxv) : name(n), value(v), minValue(mnv), maxValue(mxv), Animatable(Animatable::SHAPE_KEY, n){} - ShapeKey() : Animatable(Animatable::SHAPE_KEY){} - void animate(float, KeyframeChannel); - }; - - struct GpuVertex{ - Vector3 pos, norm, tan, biTan; - Vector2 uv; - float weights[4]{0, 0, 0, 0}; - int boneIndices[4]{-1, -1, -1, -1}; - Vector3 shapeKeyOffsets[100]; - }; - - struct Vertex{ - Vector3 *pos = nullptr, *norm = nullptr, tan, biTan; - Vector2 uv; - float *weights = nullptr; - int *boneIndices = nullptr; - Vector3 *shapeKeyOffsets = nullptr; - }; - - GpuVertex* toGpuVerts(); - - Vector3 *positions = nullptr, *normals = nullptr, **shapeKeyOffsets = nullptr; - float **weights = nullptr; - int **boneIndices = nullptr; - Vertex *vertices; - std::string *vertexGroups = nullptr; - ShapeKey *shapeKeys = nullptr; - u32 *indices, VAO, VBO, EBO; - int numPos, numTris, numVertexGroups = 0, numShapeKeys = 0; - std::string attachableName = "", fullSkeletonName = ""; - - MeshData(){} - MeshData(Vector3 *pos, float **w, int **bi, Vector3 **sko, int np, Vector3 *norm, Vertex *vert, u32 *ind, int nt, std::string an = "", std::string *vg = nullptr, int nvg = 0, std::string fsn = "", ShapeKey *sk = nullptr, int nsk = 0) : - positions(pos), - weights(w), - boneIndices(bi), - shapeKeyOffsets(sko), - numPos(np), - normals(norm), - vertices(vert), - indices(ind), - numTris(nt), - vertexGroups(vg), - numVertexGroups(nvg), - fullSkeletonName(fsn), - shapeKeys(sk), - numShapeKeys(nsk) - {} + struct MeshData{ + struct ShapeKey : public Animatable{ + std::string name; + float minValue, value, maxValue; + + ShapeKey(std::string n, float v, float mnv, float mxv) : name(n), value(v), minValue(mnv), maxValue(mxv), Animatable(Animatable::SHAPE_KEY, n){} + ShapeKey() : Animatable(Animatable::SHAPE_KEY){} + void animate(float, KeyframeChannel); }; + + struct GpuVertex{ + Vector3 pos, norm, tan, biTan; + Vector2 uv; + float weights[4]{0, 0, 0, 0}; + int boneIndices[4]{-1, -1, -1, -1}; + Vector3 shapeKeyOffsets[100]; + }; + + struct Vertex{ + Vector3 *pos = nullptr, *norm = nullptr, tan, biTan; + Vector2 uv; + float *weights = nullptr; + int *boneIndices = nullptr; + Vector3 *shapeKeyOffsets = nullptr; + }; + + GpuVertex* toGpuVerts(); + + Vector3 *positions = nullptr, *normals = nullptr, **shapeKeyOffsets = nullptr; + float **weights = nullptr; + int **boneIndices = nullptr; + Vertex *vertices; + std::string *vertexGroups = nullptr; + ShapeKey *shapeKeys = nullptr; + u32 *indices, VAO, VBO, EBO; + int numPos, numTris, numVertexGroups = 0, numShapeKeys = 0; + std::string attachableName = "", fullSkeletonName = ""; + + MeshData(){} + MeshData(Vector3*, float**, int**, Vector3**, int, Vector3*, Vertex*, u32*, int, std::string = "", std::string *vg = nullptr, int = 0, std::string = "", ShapeKey *sk = nullptr, int = 0); + }; } #endif diff --git a/model.cpp b/model.cpp index 0684ba1..f8e3257 100755 --- a/model.cpp +++ b/model.cpp @@ -14,17 +14,13 @@ using namespace std; namespace vb01{ Model::Model(string path) : Node(){ - ModelAsset *asset = ((ModelAsset*)AssetManager::getSingleton()->getAsset(path)); - Node *clonedRoot = asset->rootNode->clone(); - vector descendants = vector{clonedRoot}; - clonedRoot->getDescendants(descendants); + ModelAsset *asset = ((ModelAsset*)AssetManager::getSingleton()->getAsset(path)); + Node *clonedRoot = asset->rootNode->clone(); + vector descendants = vector{clonedRoot}; + clonedRoot->getDescendants(descendants); - for(Node *desc : descendants) - for(Mesh *mesh : desc->getMeshes()) - mesh->construct(); - - for(Node *child : clonedRoot->getChildren()) - attachChild(child); + for(Node *child : clonedRoot->getChildren()) + attachChild(child); } Model::~Model(){ diff --git a/quad.cpp b/quad.cpp index 076b313..f7a6314 100755 --- a/quad.cpp +++ b/quad.cpp @@ -11,7 +11,6 @@ namespace vb01{ this->numHorDiv = numHorDiv; setSize(size); - Mesh::construct(); } void Quad::setSize(Vector3 size){ diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index f268ab7..1e77a36 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -190,7 +190,24 @@ namespace vb01{ const char *fullSkeletonName = meshEl->Attribute("skeleton"); string name = string(meshEl->Parent()->ToElement()->Attribute("name")) + string(meshEl->Attribute("name")); - Mesh *mesh = new Mesh(MeshData(vertPos, weights, boneIndices, shapeKeyOffsets, numVertPos, normals, vertices, indices, numVertices / 3, name, vertexGroups, numVertexGroups, (fullSkeletonName ? fullSkeletonName : ""), shapeKeys, numShapeKeys)); + MeshData meshData = MeshData( + vertPos, + weights, + boneIndices, + shapeKeyOffsets, + numVertPos, + normals, + vertices, + indices, + numVertices / 3, + name, + vertexGroups, + numVertexGroups, + (fullSkeletonName ? fullSkeletonName : ""), + shapeKeys, + numShapeKeys + ); + Mesh *mesh = new Mesh(meshData); return mesh; }