Models now draw in a single draw call

This commit is contained in:
grayson committed 2021-10-01 01:21:27 -05:00
1 parent 037ad47468
commit ba19742bfe
19 files changed
+257 -168

No files matched your search

+8 -1
View File
@@ -2,6 +2,7 @@
#include "Application.h"
#include "Model.h"
#include "Texture.h"
#include "Utility.h"
namespace nf {
@@ -53,9 +54,15 @@ namespace nf {
m_nfObjects.clear();
for (Model* curr : m_modelsToDelete)
delete curr;
if (!curr->isBaseAsset())
delete curr;
m_modelsToDelete.clear();
for (Texture* curr : m_texturesToDelete)
if (!curr->isBaseAsset())
delete curr;
m_texturesToDelete.clear();
delete camera;
app = nullptr;
}
+2 -2
View File
@@ -53,10 +53,10 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())
+1 -1
View File
@@ -113,7 +113,7 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(vb, sizeof(vb));
m_vao->push<float>(3);
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())
+1 -1
View File
@@ -90,7 +90,7 @@ namespace nf {
}
void Entity::destroy() {
if (m_constructed && m_model && !m_model->isBaseAsset()) {
if (m_constructed && m_model) {
Application::getApp()->getCurrentState()->m_modelsToDelete.insert(m_model);
m_model = nullptr;
}
+2 -2
View File
@@ -60,10 +60,10 @@ namespace nf {
}
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (m_string == "NFLoadingText") {
+2 -2
View File
@@ -43,10 +43,10 @@ namespace nf {
};
m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, sizeof(tc));
m_vao->push<float>(2);
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
if (!Application::getApp()->getCurrentState()->isRunning())
+109 -92
View File
@@ -1,96 +1,22 @@
#include "Model.h"
#include <map>
#include <algorithm>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "GL/glew.h"
#include "Application.h"
#include "Texture.h"
#include "Shader.h"
#include "Utility.h"
namespace nf {
Material::Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* tan, const size_t tanSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex) {
m_vao = new VertexArray();
m_vao->addBuffer(vb, vbSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(tc, tcSize);
m_vao->push<float>(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(vn, vnSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(tan, tanSize);
m_vao->push<float>(3);
m_vao->finishBufferLayout();
m_ib = new IndexBuffer(ib, ibCount);
if (diffTex) {
m_hasDiffuse = true;
if (diffTex->alreadyLoaded)
m_diffuseTexture = diffTex->loadedTexture;
else
m_diffuseTexture = new Texture(diffTex);
}
m_diffColor = diffColor;
if (specTex) {
m_hasSpecular = true;
if (specTex->alreadyLoaded)
m_specularTexture = specTex->loadedTexture;
else
m_specularTexture = new Texture(specTex, true);
}
m_shininess = shininess;
if (normalTex) {
m_hasNormal = true;
if (normalTex->alreadyLoaded)
m_normalTexture = normalTex->loadedTexture;
else
m_normalTexture = new Texture(normalTex, true);
}
}
void Material::render(Shader* shader, bool onlyDepth) {
m_vao->bind();
m_ib->bind();
if (!onlyDepth) {
if (m_hasDiffuse) {
shader->setUniform("material.hasDiffuseTex", true);
m_diffuseTexture->bind();
}
else {
shader->setUniform("material.hasDiffuseTex", false);
glm::vec3 color(m_diffColor.x, m_diffColor.y, m_diffColor.z);
shader->setUniform("material.diffuseColor", color);
}
if (m_hasSpecular) {
shader->setUniform("material.hasSpecTex", true);
m_specularTexture->bind(1);
shader->setUniform("material.specularTexture", 1);
}
else
shader->setUniform("material.hasSpecTex", false);
if (m_hasNormal) {
shader->setUniform("material.hasNormTex", true);
m_normalTexture->bind(2);
shader->setUniform("material.normalTexture", 2);
}
else
shader->setUniform("material.hasNormTex", false);
shader->setUniform("material.specPower", m_shininess);
}
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
}
Material::~Material() {
delete m_diffuseTexture;
delete m_specularTexture;
delete m_normalTexture;
}
Model::Model(AModel* model) :
m_base(model->isBaseAsset)
{
if (model->neededTextures.size() > 32)
Error("Model exceedes 32 texture limit!");
std::string obj = model->data;
unsigned int startMtlPos = obj.find("newmtl");
if (startMtlPos == std::string::npos)
@@ -293,6 +219,13 @@ namespace nf {
return std::memcmp((void*)this, (void*)&other, sizeof(Vertex)) > 0;
}
};
std::vector<float> vboPositions;
std::vector<float> vboTexCoords;
std::vector<float> vboNormals;
std::vector<float> vboTangents;
std::vector<int> vboMaterialIndices;
std::vector<unsigned int> vboIndices;
int matCount = 0;
for (auto& m : mats) {
std::string curr = m.first;
std::map<Vertex, unsigned int> vertexMap;
@@ -325,23 +258,101 @@ namespace nf {
}
TempMaterial& curr2 = *m.second;
ATexture* diff = nullptr;
if (curr2.diffuseTextureName.size())
diff = model->neededTextures[curr2.diffuseTextureName];
ATexture* spec = nullptr;
if (curr2.specularTextureName.size())
spec = model->neededTextures[curr2.specularTextureName];
ATexture* norm = nullptr;
if (curr2.normalTextureName.size())
norm = model->neededTextures[curr2.normalTextureName];
m_materials.push_back(new Material(&curr2.outVB[0], curr2.outVB.size() * sizeof(float), &curr2.outTC[0], curr2.outTC.size() * sizeof(float), &curr2.outVN[0], curr2.outVN.size() * sizeof(float), &curr2.outTan[0], curr2.outTan.size() * sizeof(float), &curr2.outIB[0], curr2.ibCount, diff, curr2.diffuseColor, spec, curr2.shininess, norm));
ATexture* diffA = nullptr;
Texture* diff = nullptr;
if (curr2.diffuseTextureName.size()) {
diffA = model->neededTextures[curr2.diffuseTextureName];
diff = new Texture(diffA);
}
ATexture* specA = nullptr;
Texture* spec = nullptr;
if (curr2.specularTextureName.size()) {
specA = model->neededTextures[curr2.specularTextureName];
spec = new Texture(specA, true);
}
ATexture* normA = nullptr;
Texture* norm = nullptr;
if (curr2.normalTextureName.size()) {
normA = model->neededTextures[curr2.normalTextureName];
norm = new Texture(normA, true);
}
m_materials.push_back(std::make_tuple(diff, spec, norm, (float)curr2.diffuseColor.x, (float)curr2.diffuseColor.y, (float)curr2.diffuseColor.z, curr2.shininess));
unsigned int offset = vboPositions.size() / 3;
vboPositions.insert(vboPositions.end(), curr2.outVB.begin(), curr2.outVB.end());
vboTexCoords.insert(vboTexCoords.end(), curr2.outTC.begin(), curr2.outTC.end());
vboNormals.insert(vboNormals.end(), curr2.outVN.begin(), curr2.outVN.end());
vboTangents.insert(vboTangents.end(), curr2.outTan.begin(), curr2.outTan.end());
vboMaterialIndices.insert(vboMaterialIndices.end(), curr2.outVB.size() / 3, matCount);
if (offset)
std::for_each(curr2.outIB.begin(), curr2.outIB.end(), [offset](unsigned int& out) { out += offset; });
vboIndices.insert(vboIndices.end(), curr2.outIB.begin(), curr2.outIB.end());
delete m.second;
matCount++;
}
if (m_materials.size() > 32)
Error("Model exceedes 32 material limit!");
m_vao = new VertexArray;
m_vao->addBuffer(&vboPositions[0], vboPositions.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTexCoords[0], vboTexCoords.size() * sizeof(float));
m_vao->pushFloat(2);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboNormals[0], vboNormals.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboTangents[0], vboTangents.size() * sizeof(float));
m_vao->pushFloat(3);
m_vao->finishBufferLayout();
m_vao->addBuffer(&vboMaterialIndices[0], vboMaterialIndices.size() * sizeof(int));
m_vao->pushInt(1);
m_vao->finishBufferLayout();
m_ib = new IndexBuffer(&vboIndices[0], vboIndices.size());
}
void Model::render(Shader* shader, bool onlyDepth) {
for (Material* curr : m_materials) {
curr->render(shader, onlyDepth);
m_vao->bind();
m_ib->bind();
if (!onlyDepth)
bindMaterials(shader);
glDrawElements(GL_TRIANGLES, m_ib->getCount(), GL_UNSIGNED_INT, nullptr);
}
void Model::bindMaterials(Shader* shader) {
int texSlot = 0;
for (unsigned int i = 0; i < m_materials.size(); i++) {
std::string currMatSuffix = std::to_string(i) + (std::string)"]";
Texture* diff;
if ((diff = std::get<0>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasDiffString + currMatSuffix, true);
diff->bind(texSlot);
shader->setUniform(m_diffString + currMatSuffix, texSlot);
texSlot++;
}
else {
shader->setUniform(m_hasDiffString + currMatSuffix, false);
glm::vec3 color(std::get<3>(m_materials[i]), std::get<4>(m_materials[i]), std::get<5>(m_materials[i]));
shader->setUniform(m_diffColorString + currMatSuffix, color);
}
Texture* spec;
if ((spec = std::get<1>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasSpecString + currMatSuffix, true);
spec->bind(texSlot);
shader->setUniform(m_specString + currMatSuffix, texSlot);
texSlot++;
}
else
shader->setUniform(m_hasSpecString + currMatSuffix, false);
Texture* norm;
if ((norm = std::get<2>(m_materials[i])) != nullptr) {
shader->setUniform(m_hasNormString + currMatSuffix, true);
norm->bind(texSlot);
shader->setUniform(m_normString + currMatSuffix, texSlot);
texSlot++;
}
else
shader->setUniform(m_hasNormString + currMatSuffix, false);
shader->setUniform(m_specPowerString + currMatSuffix, std::get<6>(m_materials[i]));
}
}
@@ -350,8 +361,14 @@ namespace nf {
}
Model::~Model() {
for (Material* curr : m_materials) {
delete curr;
for (unsigned int i = 0; i < m_materials.size(); i++) {
Texture* curr;
if ((curr = std::get<0>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<0>(m_materials[i]));
if ((curr = std::get<1>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<1>(m_materials[i]));
if ((curr = std::get<2>(m_materials[i])) != nullptr)
Application::getApp()->getCurrentState()->m_texturesToDelete.insert(std::get<2>(m_materials[i]));
}
}
}
+2 -2
View File
@@ -111,8 +111,8 @@ namespace nf {
};
m_quadVAO = new VertexArray;
m_quadVAO->addBuffer(quadVB, sizeof(quadVB));
m_quadVAO->push<float>(2);
m_quadVAO->push<float>(2);
m_quadVAO->pushFloat(2);
m_quadVAO->pushFloat(2);
m_quadVAO->finishBufferLayout();
m_quadIB = new IndexBuffer(quadIB, 6);
m_loadingText.create("NFLoadingText", Vec2(0.025, 0.044), Vec3(0.7, 0.7, 0.7));
+9 -1
View File
@@ -44,8 +44,16 @@ namespace nf {
glAttachShader(m_id, fs);
if (gs) glAttachShader(m_id, gs);
glLinkProgram(m_id);
glValidateProgram(m_id);
int result;
glGetProgramiv(m_id, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetProgramiv(m_id, GL_INFO_LOG_LENGTH, &length);
char* message = new char[length];
glGetProgramInfoLog(m_id, length, &length, message);
Error("OpenGL Error: " + (std::string)message);
}
glValidateProgram(m_id);
glGetProgramiv(m_id, GL_VALIDATE_STATUS, &result);
if (result != GL_TRUE) {
int length;
+12 -3
View File
@@ -22,20 +22,29 @@ namespace nf {
m_lastStride = 0;
}
template<>
void VertexArray::push<float>(unsigned int count) {
void VertexArray::pushFloat(unsigned int count) {
if (m_lastBufferHasLayout)
Error("Tried to modify a vertex array's buffer after the layout was final!");
m_lastBufferLayout.push_back({ GL_FLOAT, count, GL_FALSE });
m_lastStride += count * sizeof(GL_FLOAT);
}
void VertexArray::pushInt(unsigned int count) {
if (m_lastBufferHasLayout)
Error("Tried to modify a vertex array's buffer after the layout was final!");
m_lastBufferLayout.push_back({ GL_INT, count, GL_FALSE });
m_lastStride += count * sizeof(GL_INT);
}
void VertexArray::finishBufferLayout() {
unsigned int offset = 0;
for (; m_attribute < m_lastBufferLayout.size(); m_attribute++) {
const VertexBufferElement& curr = m_lastBufferLayout[m_attribute];
glEnableVertexAttribArray(m_attribute);
glVertexAttribPointer(m_attribute, curr.count, curr.type, curr.normalized, m_lastStride, (const void*)offset);
if (curr.type != GL_INT)
glVertexAttribPointer(m_attribute, curr.count, curr.type, curr.normalized, m_lastStride, (const void*)offset);
else
glVertexAttribIPointer(m_attribute, curr.count, curr.type, m_lastStride, (const void*)offset);
offset += sizeof(curr.type) * curr.count;
}
m_lastBufferHasLayout = true;
+1 -1
View File
@@ -17,7 +17,7 @@ namespace nf {
private:
void resize();
unsigned int m_FBO;
std::array<unsigned int, 4> m_textures; //TODO: Check this number
std::array<unsigned int, 4> m_textures;
unsigned int m_depth;
unsigned int m_width, m_height;
+2
View File
@@ -10,6 +10,7 @@ namespace nf {
class Renderer;
class Camera;
class Model;
class Texture;
class Gamestate {
public:
@@ -32,6 +33,7 @@ namespace nf {
std::vector<NFObject*> m_nfObjects;
std::unordered_set<Model*> m_modelsToDelete;
std::unordered_set<Texture*> m_texturesToDelete;
protected:
Application* app;
Camera* camera;
+11 -21
View File
@@ -4,39 +4,29 @@
#include "Utility.h"
namespace nf {
class Drawable;
class Texture;
class Shader;
class Material : public Drawable {
public:
Material(const void* vb, const size_t vbSize, const void* tc, const size_t tcSize, const void* vn, const size_t vnSize, const void* tan, const size_t tanSize, const void* ib, const unsigned int ibCount, ATexture* diffTex, Vec3& diffColor, ATexture* specTex, float shininess, ATexture* normalTex);
void render(Shader* shader, bool onlyDepth);
~Material();
private:
bool m_hasDiffuse = false;
Texture* m_diffuseTexture = nullptr;
Vec3 m_diffColor;
bool m_hasSpecular = false;
Texture* m_specularTexture = nullptr;
float m_shininess;
bool m_hasNormal = false;
Texture* m_normalTexture = nullptr;
};
class Model {
class Model : public Drawable {
public:
Model(AModel* model);
void render(Shader* shader, bool onlyDepth);
void bindMaterials(Shader* shader);
bool isBaseAsset();
~Model();
private:
bool m_base;
std::vector<Material*> m_materials;
std::vector<std::tuple<Texture*, Texture*, Texture*, float, float, float, float>> m_materials;
const std::string m_hasDiffString = "hasDiffuseTex[";
const std::string m_diffString = "diffuseTexture[";
const std::string m_diffColorString = "diffuseColor[";
const std::string m_hasSpecString = "hasSpecTex[";
const std::string m_specString = "specularTexture[";
const std::string m_hasNormString = "hasNormTex[";
const std::string m_normString = "normalTexture[";
const std::string m_specPowerString = "specPower[";
};
}
+2 -2
View File
@@ -15,8 +15,8 @@ namespace nf {
VertexArray();
void addBuffer(const void* data, const size_t size);
template<typename T>
void push(unsigned int count);
void pushFloat(unsigned int count);
void pushInt(unsigned int count);
void finishBufferLayout();
void bind();
void setBufferData(unsigned int buffer, const void* data, const size_t dataSize);