Initial support for gltf scenes
This commit is contained in:
@@ -111,7 +111,7 @@ void main() {
|
|||||||
//fragmentColor += spotLightContribution(u_spotLight, normal, v_fragmentPositionTangent, viewDir);
|
//fragmentColor += spotLightContribution(u_spotLight, normal, v_fragmentPositionTangent, viewDir);
|
||||||
|
|
||||||
f_color = vec4(fragmentColor, 1.0f);
|
f_color = vec4(fragmentColor, 1.0f);
|
||||||
|
f_color = vec4(0.95f, 0.16f, 0.33f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 viewDir) {
|
vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 viewDir) {
|
||||||
|
|||||||
1
lib/CMakeLists.txt
vendored
1
lib/CMakeLists.txt
vendored
@@ -2,6 +2,7 @@ option(SPDLOG_NO_EXCEPTIONS "" ON)
|
|||||||
|
|
||||||
set(TINYGLTF_HEADER_ONLY OFF CACHE INTERNAL "" FORCE)
|
set(TINYGLTF_HEADER_ONLY OFF CACHE INTERNAL "" FORCE)
|
||||||
set(TINYGLTF_INSTALL OFF CACHE INTERNAL "" FORCE)
|
set(TINYGLTF_INSTALL OFF CACHE INTERNAL "" FORCE)
|
||||||
|
set(TINYGLTF_NOEXCEPTION OFF CACHE INTERNAL "" FORCE)
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glad)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glad)
|
||||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/entt)
|
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/entt)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ target_link_libraries(
|
|||||||
fmt
|
fmt
|
||||||
pthread
|
pthread
|
||||||
spdlog
|
spdlog
|
||||||
|
tinygltf
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(Fall-Fever
|
add_executable(Fall-Fever
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Entity.h"
|
|
||||||
#include "FrameBuffer.h"
|
#include "FrameBuffer.h"
|
||||||
#include "Helper.h"
|
#include "Helper.h"
|
||||||
#include "Light.h"
|
#include "Mesh.h"
|
||||||
#include "Scene.h"
|
|
||||||
#include "ShaderProgram.h"
|
#include "ShaderProgram.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
#include "definitions/attribute_locations.h"
|
||||||
|
#include "resources/Model.h"
|
||||||
#include "util/Log.h"
|
#include "util/Log.h"
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
@@ -21,6 +21,73 @@ Controller::Controller()
|
|||||||
m_postProcessFrameBuffer(m_gameWindow->dimensions().first, m_gameWindow->dimensions().second,
|
m_postProcessFrameBuffer(m_gameWindow->dimensions().first, m_gameWindow->dimensions().second,
|
||||||
postProcessingProgram)
|
postProcessingProgram)
|
||||||
{
|
{
|
||||||
|
tinygltf::TinyGLTF loader;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
bool ret = loader.LoadASCIIFromFile(&m_model, &err, &warn, "glTF/ABeautifulGame.gltf");
|
||||||
|
// bool ret = loader.LoadASCIIFromFile(&m_model, &err, &warn, "minimal.gltf");
|
||||||
|
|
||||||
|
if (!warn.empty()) {
|
||||||
|
Log::logger().warn("{}", warn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
Log::logger().error("{}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
Log::logger().error("Failed to parse glTF");
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultProgram.bind();
|
||||||
|
AttributeLocations locations{};
|
||||||
|
|
||||||
|
locations.position = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_position");
|
||||||
|
locations.normal = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_normal");
|
||||||
|
locations.uv = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_texCoord");
|
||||||
|
|
||||||
|
ShaderProgram::unbind();
|
||||||
|
|
||||||
|
std::vector<Model> models;
|
||||||
|
for (auto const &mesh : m_model.meshes) {
|
||||||
|
std::vector<Mesh> meshes;
|
||||||
|
for (auto const &primitive : mesh.primitives) {
|
||||||
|
meshes.emplace_back(Mesh({primitive, m_model, locations}, {}));
|
||||||
|
}
|
||||||
|
models.emplace_back(Model(mesh.name, std::move(meshes)));
|
||||||
|
}
|
||||||
|
m_models = std::move(models);
|
||||||
|
|
||||||
|
std::vector<ModelEntity> entities;
|
||||||
|
for (auto const &node : m_model.nodes) {
|
||||||
|
ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F), m_models[static_cast<unsigned>(node.mesh)],
|
||||||
|
defaultProgram);
|
||||||
|
|
||||||
|
if (!node.translation.empty()) {
|
||||||
|
entity.setPosition(glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node.rotation.empty()) {
|
||||||
|
entity.setRotation(
|
||||||
|
glm::eulerAngles(glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2])));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node.scale.empty()) {
|
||||||
|
entity.setScale(node.scale[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
entities.push_back(std::move(entity));
|
||||||
|
|
||||||
|
for (auto const &child : node.children) {
|
||||||
|
if (!node.translation.empty()) {
|
||||||
|
entities[child].translate(glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::logger().info("Load node {}.", node.name);
|
||||||
|
}
|
||||||
|
m_entities = std::move(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::run()
|
void Controller::run()
|
||||||
@@ -29,7 +96,7 @@ void Controller::run()
|
|||||||
|
|
||||||
m_camera->translate(glm::vec3(0., 1.5, 5.));
|
m_camera->translate(glm::vec3(0., 1.5, 5.));
|
||||||
|
|
||||||
Log::logger().info("Startup complete.");
|
Log::logger().info("Startup complete. Enter game loop.");
|
||||||
|
|
||||||
// This is the game loop
|
// This is the game loop
|
||||||
while (glfwWindowShouldClose(&m_gameWindow->glfw_window()) == GLFW_FALSE) {
|
while (glfwWindowShouldClose(&m_gameWindow->glfw_window()) == GLFW_FALSE) {
|
||||||
@@ -40,7 +107,7 @@ void Controller::run()
|
|||||||
// --- Update game ---
|
// --- Update game ---
|
||||||
lightProgram.bind();
|
lightProgram.bind();
|
||||||
lightProgram.setUniform("v_lightColor", glm::vec3{1., 1., 1.} * 100.0F);
|
lightProgram.setUniform("v_lightColor", glm::vec3{1., 1., 1.} * 100.0F);
|
||||||
lightProgram.unbind();
|
ShaderProgram::unbind();
|
||||||
|
|
||||||
// --- Render and buffer swap ---
|
// --- Render and buffer swap ---
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
@@ -51,6 +118,13 @@ void Controller::run()
|
|||||||
m_camera->lookForward();
|
m_camera->lookForward();
|
||||||
m_camera->updateVPM();
|
m_camera->updateVPM();
|
||||||
|
|
||||||
|
// Draw scene
|
||||||
|
defaultProgram.bind();
|
||||||
|
for (auto const &entity : m_entities) {
|
||||||
|
entity.draw(m_camera->getViewProj(), m_camera->getPosition());
|
||||||
|
}
|
||||||
|
ShaderProgram::unbind();
|
||||||
|
|
||||||
m_postProcessFrameBuffer.unbind();
|
m_postProcessFrameBuffer.unbind();
|
||||||
m_postProcessFrameBuffer.drawOnEntireScreen();
|
m_postProcessFrameBuffer.drawOnEntireScreen();
|
||||||
|
|
||||||
@@ -68,7 +142,6 @@ void Controller::run()
|
|||||||
|
|
||||||
auto const &key_input = m_gameWindow->key_input();
|
auto const &key_input = m_gameWindow->key_input();
|
||||||
auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input();
|
auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input();
|
||||||
// auto const &mouse_button_input = m_gameWindow->mouse_button_input();
|
|
||||||
|
|
||||||
m_camera->updatePositionFromKeyboardInput(key_input, (float)m_deltaTime);
|
m_camera->updatePositionFromKeyboardInput(key_input, (float)m_deltaTime);
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
#include "FrameBuffer.h"
|
#include "FrameBuffer.h"
|
||||||
#include "ShaderProgram.h"
|
#include "ShaderProgram.h"
|
||||||
|
#include "VertexArray.h"
|
||||||
|
#include "resources/Model.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tiny_gltf.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Window;
|
class Window;
|
||||||
@@ -39,6 +43,11 @@ private:
|
|||||||
|
|
||||||
static constexpr unsigned MAX_FPS = 60;
|
static constexpr unsigned MAX_FPS = 60;
|
||||||
|
|
||||||
|
tinygltf::Model m_model;
|
||||||
|
|
||||||
|
std::vector<ModelEntity> m_entities;
|
||||||
|
std::vector<Model> m_models;
|
||||||
|
|
||||||
double m_deltaTime{};
|
double m_deltaTime{};
|
||||||
float m_exposure = 1.0;
|
float m_exposure = 1.0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,10 +12,8 @@
|
|||||||
uint32_t Entity::s_idCounter = 0;
|
uint32_t Entity::s_idCounter = 0;
|
||||||
|
|
||||||
Entity::Entity(const std::string &name) : m_id(s_idCounter++), m_uniqueName(name)
|
Entity::Entity(const std::string &name) : m_id(s_idCounter++), m_uniqueName(name)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
Entity::~Entity()
|
|
||||||
{}
|
|
||||||
|
|
||||||
uint32_t Entity::getId() const
|
uint32_t Entity::getId() const
|
||||||
{
|
{
|
||||||
@@ -93,7 +91,7 @@ glm::mat4 Entity::getModelMatrix() const
|
|||||||
return m_modelMatrix;
|
return m_modelMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelEntity::ModelEntity(Prototype prototype, const Model *model, ShaderProgram *shaderProgram)
|
ModelEntity::ModelEntity(Entity::Prototype prototype, Model const &model, ShaderProgram const &shaderProgram)
|
||||||
: Entity(prototype.name), m_model(model), m_shaderProgram(shaderProgram)
|
: Entity(prototype.name), m_model(model), m_shaderProgram(shaderProgram)
|
||||||
{
|
{
|
||||||
setPosition(prototype.position);
|
setPosition(prototype.position);
|
||||||
@@ -101,27 +99,27 @@ ModelEntity::ModelEntity(Prototype prototype, const Model *model, ShaderProgram
|
|||||||
setScale(prototype.scale);
|
setScale(prototype.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition)
|
void ModelEntity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) const
|
||||||
{
|
{
|
||||||
m_shaderProgram->bind();
|
m_shaderProgram.bind();
|
||||||
|
|
||||||
glm::mat4 modelViewProj = viewProjMatrix * m_modelMatrix;
|
glm::mat4 modelViewProj = viewProjMatrix * m_modelMatrix;
|
||||||
m_shaderProgram->setUniform("u_modelViewProjMatrix", modelViewProj);
|
m_shaderProgram.setUniform("u_modelViewProjMatrix", modelViewProj);
|
||||||
m_shaderProgram->setUniform("u_modelMatrix", m_modelMatrix);
|
m_shaderProgram.setUniform("u_modelMatrix", m_modelMatrix);
|
||||||
|
|
||||||
glm::mat3 normalMatrix = glm::mat3(m_modelMatrix);
|
glm::mat3 normalMatrix = glm::mat3(m_modelMatrix);
|
||||||
normalMatrix = glm::transpose(glm::inverse(normalMatrix));
|
normalMatrix = glm::transpose(glm::inverse(normalMatrix));
|
||||||
m_shaderProgram->setUniform("u_normalMatrix", normalMatrix);
|
m_shaderProgram.setUniform("u_normalMatrix", normalMatrix);
|
||||||
|
|
||||||
m_shaderProgram->setUniform("u_viewPosition", viewPosition);
|
m_shaderProgram.setUniform("u_viewPosition", viewPosition);
|
||||||
|
|
||||||
// Draw the model
|
// Draw the model
|
||||||
m_model->draw(m_shaderProgram);
|
m_model.draw(m_shaderProgram);
|
||||||
|
|
||||||
m_shaderProgram->unbind();
|
m_shaderProgram.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntity::drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *shaderProgram)
|
void ModelEntity::drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *shaderProgram) const
|
||||||
{
|
{
|
||||||
shaderProgram->bind();
|
shaderProgram->bind();
|
||||||
|
|
||||||
@@ -129,19 +127,19 @@ void ModelEntity::drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram
|
|||||||
shaderProgram->setUniform("u_modelViewProjMatrix", modelViewProj);
|
shaderProgram->setUniform("u_modelViewProjMatrix", modelViewProj);
|
||||||
|
|
||||||
// Draw the model
|
// Draw the model
|
||||||
m_model->drawWithoutTextures();
|
m_model.drawWithoutTextures();
|
||||||
|
|
||||||
shaderProgram->unbind();
|
shaderProgram->unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntity::drawPointShadows(ShaderProgram *shaderProgram)
|
void ModelEntity::drawPointShadows(ShaderProgram *shaderProgram) const
|
||||||
{
|
{
|
||||||
shaderProgram->bind();
|
shaderProgram->bind();
|
||||||
|
|
||||||
shaderProgram->setUniform("u_modelMatrix", m_modelMatrix);
|
shaderProgram->setUniform("u_modelMatrix", m_modelMatrix);
|
||||||
|
|
||||||
// Draw the model
|
// Draw the model
|
||||||
m_model->drawWithoutTextures();
|
m_model.drawWithoutTextures();
|
||||||
|
|
||||||
shaderProgram->unbind();
|
shaderProgram->unbind();
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/Entity.h
28
src/Entity.h
@@ -20,7 +20,8 @@ public:
|
|||||||
{
|
{
|
||||||
Prototype(const std::string &_name, glm::vec3 _position, glm::vec3 _rotation, float _scale)
|
Prototype(const std::string &_name, glm::vec3 _position, glm::vec3 _rotation, float _scale)
|
||||||
: name(_name), position(_position), rotation(_rotation), scale(_scale)
|
: name(_name), position(_position), rotation(_rotation), scale(_scale)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
virtual ~Prototype() = default;
|
virtual ~Prototype() = default;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -30,7 +31,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Entity(const std::string &name);
|
Entity(const std::string &name);
|
||||||
virtual ~Entity() = 0;
|
virtual ~Entity() = default;
|
||||||
|
|
||||||
uint32_t getId() const;
|
uint32_t getId() const;
|
||||||
const std::string &getUniqueName() const;
|
const std::string &getUniqueName() const;
|
||||||
@@ -64,26 +65,15 @@ protected:
|
|||||||
class ModelEntity : public Entity
|
class ModelEntity : public Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Prototype : public Entity::Prototype
|
ModelEntity(Entity::Prototype prototype, Model const &model, ShaderProgram const &shaderProgram);
|
||||||
{
|
|
||||||
Prototype(const std::string &_name, glm::vec3 _position, glm::vec3 _rotation, float _scale,
|
|
||||||
std::string _modelName, std::string _shaderProgramName)
|
|
||||||
: Entity::Prototype(_name, _position, _rotation, _scale), modelName(std::move(_modelName)),
|
|
||||||
shaderProgramName(std::move(_shaderProgramName))
|
|
||||||
{}
|
|
||||||
std::string modelName;
|
|
||||||
std::string shaderProgramName;
|
|
||||||
};
|
|
||||||
|
|
||||||
ModelEntity(Prototype prototype, const Model *model, ShaderProgram *shaderProgram);
|
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) const;
|
||||||
|
void drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *p_shaderProgram) const;
|
||||||
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition);
|
void drawPointShadows(ShaderProgram *p_shaderProgram) const;
|
||||||
void drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *p_shaderProgram);
|
|
||||||
void drawPointShadows(ShaderProgram *p_shaderProgram);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Model *m_model;
|
Model const &m_model;
|
||||||
ShaderProgram *m_shaderProgram;
|
ShaderProgram const &m_shaderProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Skybox
|
class Skybox
|
||||||
|
|||||||
60
src/Mesh.cpp
60
src/Mesh.cpp
@@ -1,65 +1,57 @@
|
|||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
|
||||||
#include "ShaderProgram.h"
|
#include "ShaderProgram.h"
|
||||||
#include "VertexArray.h"
|
#include "VertexArray.h"
|
||||||
#include "resources/ResourceHandler.h"
|
#include "resources/ResourceHandler.h"
|
||||||
#include "resources/Texture.h"
|
#include "resources/Texture.h"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
Mesh::Mesh(std::vector<Vertex> vertices, std::vector<uint32_t> indices, std::vector<ResourceId> textures)
|
Mesh::Mesh(VertexArray vertexArray, std::vector<ResourceId> textures)
|
||||||
: m_preInitializationVertexData{vertices, indices}, m_numElements(static_cast<unsigned>(indices.size())),
|
: m_vertexArray(std::move(vertexArray)), m_textures(std::move(textures))
|
||||||
m_textures(textures)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::initializeOnGPU()
|
void Mesh::draw(ShaderProgram const &shaderProgram) const
|
||||||
{
|
{
|
||||||
m_vertexArray = new VertexArray(static_cast<void *>(m_preInitializationVertexData.vertices.data()),
|
std::array<uint8_t, static_cast<std::size_t>(TextureType::TEXTURE_TYPE_NUM_ITEMS)> typeNumberCount{};
|
||||||
static_cast<void *>(m_preInitializationVertexData.indices.data()),
|
|
||||||
static_cast<unsigned>(m_preInitializationVertexData.vertices.size()),
|
|
||||||
static_cast<unsigned>(m_preInitializationVertexData.indices.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh::~Mesh()
|
|
||||||
{
|
|
||||||
delete m_vertexArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::draw(ShaderProgram *shaderProgram)
|
|
||||||
{
|
|
||||||
uint8_t typeNumberCount[static_cast<int>(TextureType::TEXTURE_TYPE_NUM_ITEMS)]{0};
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
// Bind all textures in order to its texture unit
|
// Bind all textures in order to its texture unit
|
||||||
std::size_t i = 0;
|
std::size_t textureNum = 0;
|
||||||
for (auto it : m_textures) {
|
for (auto textureIt : m_textures) {
|
||||||
auto texture = std::static_pointer_cast<Texture>(ResourceHandler::instance().resource(it));
|
auto texture = std::static_pointer_cast<Texture>(ResourceHandler::instance().resource(textureIt));
|
||||||
TextureType currentTextureType = texture->textureType();
|
TextureType currentTextureType = texture->textureType();
|
||||||
|
|
||||||
texture->bind(static_cast<uint8_t>(i), shaderProgram, typeNumberCount[static_cast<int>(currentTextureType)]);
|
texture->bind(static_cast<uint8_t>(textureNum), shaderProgram,
|
||||||
|
typeNumberCount.at(static_cast<std::size_t>(currentTextureType)));
|
||||||
|
|
||||||
typeNumberCount[static_cast<int>(currentTextureType)] += 1;
|
typeNumberCount.at(static_cast<std::size_t>(currentTextureType)) += 1;
|
||||||
|
|
||||||
i++;
|
textureNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw elements
|
// Draw elements
|
||||||
m_vertexArray->bind();
|
m_vertexArray.bind();
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_numElements), GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_vertexArray.indicesCount()),
|
||||||
m_vertexArray->unbind();
|
static_cast<GLenum>(m_vertexArray.indicesType()), nullptr);
|
||||||
|
VertexArray::unbind();
|
||||||
|
|
||||||
// Unbind all textures
|
// Unbind all textures
|
||||||
for (auto it : m_textures) {
|
for (auto textureIt : m_textures) {
|
||||||
auto texture = std::static_pointer_cast<Texture>(ResourceHandler::instance().resource(it));
|
auto texture = std::static_pointer_cast<Texture>(ResourceHandler::instance().resource(textureIt));
|
||||||
texture->unbind();
|
texture->unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::drawWithoutTextures()
|
void Mesh::drawWithoutTextures() const
|
||||||
{
|
{
|
||||||
m_vertexArray->bind();
|
m_vertexArray.bind();
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_numElements), GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_vertexArray.indicesCount()),
|
||||||
m_vertexArray->unbind();
|
static_cast<GLenum>(m_vertexArray.indicesType()), nullptr);
|
||||||
|
VertexArray::unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexArray *Mesh::getVertexArray()
|
auto Mesh::getVertexArray() -> VertexArray *
|
||||||
{
|
{
|
||||||
return m_vertexArray;
|
return &m_vertexArray;
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/Mesh.h
22
src/Mesh.h
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "VertexArray.h"
|
#include "VertexArray.h"
|
||||||
#include "definitions/models.h"
|
|
||||||
#include "resources/Resource.h"
|
#include "resources/Resource.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -11,27 +10,14 @@ class ShaderProgram;
|
|||||||
class Mesh
|
class Mesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<ResourceId> textures);
|
Mesh(VertexArray vertexArray, std::vector<ResourceId> textures);
|
||||||
~Mesh();
|
|
||||||
|
|
||||||
void initializeOnGPU();
|
void draw(ShaderProgram const &shaderProgram) const;
|
||||||
|
void drawWithoutTextures() const;
|
||||||
void draw(ShaderProgram *shaderProgram);
|
|
||||||
void drawWithoutTextures();
|
|
||||||
|
|
||||||
auto getVertexArray() -> VertexArray *;
|
auto getVertexArray() -> VertexArray *;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PreInitializationVertexData
|
VertexArray m_vertexArray;
|
||||||
{
|
|
||||||
std::vector<Vertex> vertices;
|
|
||||||
std::vector<unsigned int> indices;
|
|
||||||
} m_preInitializationVertexData;
|
|
||||||
|
|
||||||
bool m_isInitialized = false;
|
|
||||||
|
|
||||||
uint32_t m_numElements;
|
|
||||||
std::vector<ResourceId> m_textures;
|
std::vector<ResourceId> m_textures;
|
||||||
|
|
||||||
VertexArray *m_vertexArray;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
#include "ShaderProgram.h"
|
#include "ShaderProgram.h"
|
||||||
#include "util/Log.h"
|
#include "util/Log.h"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
ShaderProgram::ShaderProgram(Prototype prototype) : m_uniqueName(prototype.name)
|
ShaderProgram::ShaderProgram(Prototype prototype) : m_shaderProgramId(glCreateProgram())
|
||||||
{
|
{
|
||||||
std::string vertexShaderSource = parse(prototype.vertexPath.c_str());
|
std::string vertexShaderSource = parse(prototype.vertexPath).value();
|
||||||
std::string fragmentShaderSource = parse(prototype.fragmentPath.c_str());
|
std::string fragmentShaderSource = parse(prototype.fragmentPath).value();
|
||||||
|
|
||||||
m_shaderProgramId = glCreateProgram();
|
GLuint vertexShader = compile(vertexShaderSource, GL_VERTEX_SHADER);
|
||||||
GLuint vs = compile(vertexShaderSource, GL_VERTEX_SHADER);
|
GLuint fragmentShader = compile(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||||
GLuint fs = compile(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
glAttachShader(m_shaderProgramId, vs);
|
glAttachShader(m_shaderProgramId, vertexShader);
|
||||||
glAttachShader(m_shaderProgramId, fs);
|
glAttachShader(m_shaderProgramId, fragmentShader);
|
||||||
|
|
||||||
glLinkProgram(m_shaderProgramId);
|
glLinkProgram(m_shaderProgramId);
|
||||||
|
|
||||||
GLint isLinked = 0;
|
GLint isLinked = 0;
|
||||||
glGetProgramiv(m_shaderProgramId, GL_LINK_STATUS, &isLinked);
|
glGetProgramiv(m_shaderProgramId, GL_LINK_STATUS, &isLinked);
|
||||||
if (!isLinked)
|
if (isLinked == 0) {
|
||||||
Log::logger().critical("Failed to link shaderProgram \"{}\", \"{}\"", prototype.vertexPath,
|
Log::logger().warn(R"(Failed to link shaderProgram "{}", "{}")", prototype.vertexPath, prototype.fragmentPath);
|
||||||
prototype.fragmentPath);
|
}
|
||||||
|
|
||||||
#ifdef _RELEASE
|
#ifdef _RELEASE
|
||||||
glDetachShader(program, vs);
|
glDetachShader(program, vs);
|
||||||
@@ -32,7 +32,7 @@ ShaderProgram::ShaderProgram(Prototype prototype) : m_uniqueName(prototype.name)
|
|||||||
glDeleteShader(fs);
|
glDeleteShader(fs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Log::logger().info("Loaded shaderprogram \"{}\"", prototype.name);
|
Log::logger().info(R"(Loaded shaderprogram "{}")", prototype.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderProgram::~ShaderProgram()
|
ShaderProgram::~ShaderProgram()
|
||||||
@@ -40,7 +40,7 @@ ShaderProgram::~ShaderProgram()
|
|||||||
glDeleteProgram(m_shaderProgramId);
|
glDeleteProgram(m_shaderProgramId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderProgram::bind()
|
void ShaderProgram::bind() const
|
||||||
{
|
{
|
||||||
glUseProgram(m_shaderProgramId);
|
glUseProgram(m_shaderProgramId);
|
||||||
}
|
}
|
||||||
@@ -50,14 +50,14 @@ void ShaderProgram::unbind()
|
|||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ShaderProgram::parse(const std::string &filename)
|
auto ShaderProgram::parse(const std::filesystem::path &path) -> std::optional<std::string>
|
||||||
{
|
{
|
||||||
std::fstream shaderfile;
|
std::fstream shaderfile;
|
||||||
shaderfile.open(filename, std::ios::in);
|
shaderfile.open(path, std::ios::in);
|
||||||
|
|
||||||
if (!shaderfile.is_open()) {
|
if (!shaderfile.is_open()) {
|
||||||
Log::logger().critical("Shader \"{}\" not found", filename);
|
Log::logger().warn("Shader \"{}\" not found", path.c_str());
|
||||||
exit(-1);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string contents((std::istreambuf_iterator<char>(shaderfile)), (std::istreambuf_iterator<char>()));
|
std::string contents((std::istreambuf_iterator<char>(shaderfile)), (std::istreambuf_iterator<char>()));
|
||||||
@@ -65,34 +65,40 @@ std::string ShaderProgram::parse(const std::string &filename)
|
|||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint ShaderProgram::compile(const std::string &shaderSource, GLenum type)
|
auto ShaderProgram::compile(const std::string &shaderSource, GLenum type) -> GLuint
|
||||||
{
|
{
|
||||||
GLuint shaderId = glCreateShader(type);
|
GLuint shaderId = glCreateShader(type);
|
||||||
const char *src = shaderSource.c_str();
|
const char *src = shaderSource.c_str();
|
||||||
glShaderSource(shaderId, 1, &src, 0);
|
glShaderSource(shaderId, 1, &src, nullptr);
|
||||||
glCompileShader(shaderId);
|
glCompileShader(shaderId);
|
||||||
|
|
||||||
int result;
|
int result{};
|
||||||
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result);
|
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result);
|
||||||
|
|
||||||
if (result != GL_TRUE) {
|
if (result != GL_TRUE) {
|
||||||
int length;
|
int length{};
|
||||||
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length);
|
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length);
|
||||||
char *message = new char[static_cast<unsigned>(length)];
|
|
||||||
glGetShaderInfoLog(shaderId, length, &length, message);
|
std::string message;
|
||||||
|
message.reserve(static_cast<unsigned>(length));
|
||||||
|
|
||||||
|
glGetShaderInfoLog(shaderId, length, &length, message.data());
|
||||||
Log::logger().error("Shader compilation failed: {}", message);
|
Log::logger().error("Shader compilation failed: {}", message);
|
||||||
delete[] message;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shaderId;
|
return shaderId;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint ShaderProgram::retrieveUniformLocation(const std::string &name) const
|
auto ShaderProgram::retrieveUniformLocation(std::string_view uniform_name) const -> GLint
|
||||||
{
|
{
|
||||||
if (m_uniformLocationCache.find(name) != m_uniformLocationCache.end())
|
if (m_uniformLocationCache.find(uniform_name.data()) != m_uniformLocationCache.end()) {
|
||||||
return m_uniformLocationCache[name];
|
return m_uniformLocationCache[uniform_name.data()];
|
||||||
|
}
|
||||||
|
|
||||||
GLint location = glGetUniformLocation(m_shaderProgramId, name.c_str());
|
GLint location = glGetUniformLocation(m_shaderProgramId, uniform_name.data());
|
||||||
m_uniformLocationCache[name] = location;
|
m_uniformLocationCache[uniform_name.data()] = location;
|
||||||
|
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
@@ -139,12 +145,7 @@ void ShaderProgram::setUniform(const std::string &name, glm::mat4 matrix) const
|
|||||||
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
|
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint ShaderProgram::getShaderProgramId()
|
auto ShaderProgram::getShaderProgramId() const -> GLuint
|
||||||
{
|
{
|
||||||
return m_shaderProgramId;
|
return m_shaderProgramId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &ShaderProgram::getUniqueName()
|
|
||||||
{
|
|
||||||
return m_uniqueName;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -16,13 +18,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ShaderProgram(Prototype prototype);
|
ShaderProgram(Prototype prototype);
|
||||||
|
|
||||||
~ShaderProgram();
|
~ShaderProgram();
|
||||||
|
|
||||||
void bind();
|
void bind() const;
|
||||||
void unbind();
|
static void unbind();
|
||||||
|
|
||||||
|
auto retrieveUniformLocation(std::string_view uniform_name) const -> GLint;
|
||||||
|
|
||||||
GLint retrieveUniformLocation(const std::string &name) const;
|
|
||||||
// May be rewritten...
|
// May be rewritten...
|
||||||
void setUniform(const std::string &name, bool value) const;
|
void setUniform(const std::string &name, bool value) const;
|
||||||
void setUniform(const std::string &name, int value) const;
|
void setUniform(const std::string &name, int value) const;
|
||||||
@@ -32,14 +34,12 @@ public:
|
|||||||
void setUniform(const std::string &name, glm::mat3 matrix) const;
|
void setUniform(const std::string &name, glm::mat3 matrix) const;
|
||||||
void setUniform(const std::string &name, glm::mat4 matrix) const;
|
void setUniform(const std::string &name, glm::mat4 matrix) const;
|
||||||
|
|
||||||
GLuint getShaderProgramId();
|
auto getShaderProgramId() const -> GLuint;
|
||||||
const std::string &getUniqueName();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string parse(const std::string &filename);
|
static auto parse(const std::filesystem::path &path) -> std::optional<std::string>;
|
||||||
GLuint compile(const std::string &shaderSource, GLenum type);
|
static auto compile(const std::string &shaderSource, GLenum type) -> GLuint;
|
||||||
|
|
||||||
GLuint m_shaderProgramId;
|
GLuint m_shaderProgramId;
|
||||||
std::string m_uniqueName;
|
|
||||||
mutable std::unordered_map<std::string, GLint> m_uniformLocationCache;
|
mutable std::unordered_map<std::string, GLint> m_uniformLocationCache;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,51 +4,80 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
VertexArray::VertexArray(void *vertexData, void *indexData, uint32_t numVertices, uint32_t numIndices)
|
VertexArray::VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model const &model, AttributeLocations &locations)
|
||||||
{
|
{
|
||||||
glGenVertexArrays(1, &m_VAO);
|
GLuint vao{};
|
||||||
glBindVertexArray(m_VAO);
|
glGenVertexArrays(1, &vao);
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
glGenBuffers(1, &m_VBO);
|
int position_accessor_id = primitive.attributes.at("POSITION");
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
// int normal_accessor = primitive.attributes.at("NORMAL");
|
||||||
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), vertexData, GL_STATIC_DRAW);
|
// int uv_accessor = primitive.attributes.at("TEXCOORD_0");
|
||||||
|
int indices_accessor_id = primitive.indices;
|
||||||
|
|
||||||
glGenBuffers(1, &m_EBO);
|
auto const &position_accessor = model.accessors.at(position_accessor_id);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
auto const &indices_accessor = model.accessors.at(indices_accessor_id);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(uint32_t), indexData, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// Position
|
int position_buffer_view_id = model.accessors[position_accessor_id].bufferView;
|
||||||
glEnableVertexAttribArray(0);
|
int indices_buffer_view_id = model.accessors[indices_accessor_id].bufferView;
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(struct Vertex, position));
|
|
||||||
|
|
||||||
// UV Texture Mapping
|
auto const &position_buffer_view = model.bufferViews.at(position_buffer_view_id);
|
||||||
glEnableVertexAttribArray(1);
|
auto const &indices_buffer_view = model.bufferViews.at(indices_buffer_view_id);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(struct Vertex, textureCoords));
|
|
||||||
|
|
||||||
// Normal vectors
|
auto const &position_buffer = model.buffers.at(position_buffer_view.buffer);
|
||||||
glEnableVertexAttribArray(2);
|
auto const &indices_buffer = model.buffers.at(indices_buffer_view.buffer);
|
||||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(struct Vertex, normalVec));
|
|
||||||
|
|
||||||
// Tangent vectors
|
GLuint positionVbo{};
|
||||||
glEnableVertexAttribArray(3);
|
glGenBuffers(1, &positionVbo);
|
||||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(struct Vertex, tangentVec));
|
glBindBuffer(GL_ARRAY_BUFFER, positionVbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, position_buffer_view.byteLength,
|
||||||
|
position_buffer.data.data() + position_buffer_view.byteOffset, GL_STATIC_DRAW);
|
||||||
|
|
||||||
// Bitangent vectors
|
int size = 1;
|
||||||
glEnableVertexAttribArray(4);
|
if (position_accessor.type == TINYGLTF_TYPE_SCALAR) {
|
||||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(struct Vertex, bitangentVec));
|
size = 1;
|
||||||
|
} else if (position_accessor.type == TINYGLTF_TYPE_VEC2) {
|
||||||
|
size = 2;
|
||||||
|
} else if (position_accessor.type == TINYGLTF_TYPE_VEC3) {
|
||||||
|
size = 3;
|
||||||
|
} else if (position_accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||||
|
size = 4;
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int position_byte_stride = position_accessor.ByteStride(position_buffer_view);
|
||||||
|
glEnableVertexAttribArray(locations.position);
|
||||||
|
glVertexAttribPointer(locations.position, size, position_accessor.componentType,
|
||||||
|
position_accessor.normalized ? GL_TRUE : GL_FALSE, position_byte_stride,
|
||||||
|
(void *)position_accessor.byteOffset);
|
||||||
|
|
||||||
|
GLuint ebo{};
|
||||||
|
glGenBuffers(1, &ebo);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_buffer_view.byteLength,
|
||||||
|
indices_buffer.data.data() + indices_buffer_view.byteOffset, GL_STATIC_DRAW);
|
||||||
|
|
||||||
// This will also unbind the vertex buffer and index buffer
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
m_vao = vao;
|
||||||
|
m_ebo = ebo;
|
||||||
|
m_positionVbo = positionVbo;
|
||||||
|
m_indicesCount = indices_accessor.count;
|
||||||
|
m_indicesType = indices_accessor.componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexArray::~VertexArray()
|
VertexArray::~VertexArray()
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &m_VBO);
|
glDeleteVertexArrays(1, &m_vao);
|
||||||
|
|
||||||
|
glDeleteBuffers(1, &m_positionVbo);
|
||||||
|
glDeleteBuffers(1, &m_ebo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexArray::bind()
|
void VertexArray::bind() const
|
||||||
{
|
{
|
||||||
glBindVertexArray(m_VAO);
|
glBindVertexArray(m_vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexArray::unbind()
|
void VertexArray::unbind()
|
||||||
|
|||||||
@@ -1,19 +1,59 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "definitions/attribute_locations.h"
|
||||||
|
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
|
#include <tiny_gltf.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class VertexArray
|
class VertexArray final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VertexArray(void *vertexData, void *indexData, uint32_t numVertices, uint32_t numIndices);
|
VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model const &model, AttributeLocations &locations);
|
||||||
|
VertexArray(VertexArray &&other) noexcept
|
||||||
|
: m_indicesCount(other.m_indicesCount),
|
||||||
|
m_indicesType(other.m_indicesType),
|
||||||
|
m_vao(other.m_vao),
|
||||||
|
m_positionVbo(other.m_positionVbo),
|
||||||
|
m_ebo(other.m_ebo)
|
||||||
|
{
|
||||||
|
other.m_ebo = 0;
|
||||||
|
other.m_vao = 0;
|
||||||
|
other.m_positionVbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator=(VertexArray &&other) noexcept -> VertexArray &
|
||||||
|
{
|
||||||
|
m_indicesCount = other.m_indicesCount;
|
||||||
|
m_indicesType = other.m_indicesType;
|
||||||
|
m_vao = other.m_vao;
|
||||||
|
m_positionVbo = other.m_positionVbo;
|
||||||
|
m_ebo = other.m_ebo;
|
||||||
|
|
||||||
|
other.m_ebo = 0;
|
||||||
|
other.m_vao = 0;
|
||||||
|
other.m_positionVbo = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexArray(VertexArray const &) = delete;
|
||||||
|
auto operator=(VertexArray const &) -> VertexArray & = delete;
|
||||||
|
|
||||||
~VertexArray();
|
~VertexArray();
|
||||||
|
|
||||||
void bind();
|
void bind() const;
|
||||||
void unbind();
|
static void unbind();
|
||||||
|
|
||||||
|
[[nodiscard]] auto indicesCount() const -> uint64_t { return m_indicesCount; }
|
||||||
|
[[nodiscard]] auto indicesType() const -> int { return m_indicesType; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_VAO;
|
uint64_t m_indicesCount;
|
||||||
GLuint m_VBO;
|
int m_indicesType;
|
||||||
GLuint m_EBO;
|
|
||||||
|
GLuint m_vao;
|
||||||
|
|
||||||
|
GLuint m_positionVbo;
|
||||||
|
GLuint m_ebo;
|
||||||
};
|
};
|
||||||
|
|||||||
9
src/definitions/attribute_locations.h
Normal file
9
src/definitions/attribute_locations.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct AttributeLocations
|
||||||
|
{
|
||||||
|
int position;
|
||||||
|
int normal;
|
||||||
|
int uv;
|
||||||
|
int tangent;
|
||||||
|
};
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
class AbstractTexture : public Resource, public GlResource
|
class AbstractTexture : public Resource, public GlResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AbstractTexture(const std::string &path) : Resource(path)
|
AbstractTexture(const std::string &path) : Resource(path) {}
|
||||||
{}
|
virtual ~AbstractTexture() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t m_textureWidth;
|
uint32_t m_textureWidth;
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
#include "../util/Log.h"
|
|
||||||
#include "ResourceHandler.h"
|
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
#include <fstream>
|
Model::Model(std::string_view name, std::vector<Mesh> meshes) : m_meshes(std::move(meshes)), m_name(name)
|
||||||
#include <future>
|
|
||||||
|
|
||||||
Model::Model(const ModelDescriptor &descriptor) : Resource(descriptor.path), NamedResource(descriptor.name)
|
|
||||||
{
|
{
|
||||||
m_workingPath = descriptor.path.substr(0, descriptor.path.find_last_of('/'));
|
|
||||||
|
|
||||||
loadModel(descriptor.path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::initialize()
|
void Model::draw(ShaderProgram const &shaderProgram) const
|
||||||
{
|
|
||||||
m_initialized = true;
|
|
||||||
|
|
||||||
for (auto mesh : m_meshes)
|
|
||||||
mesh->initializeOnGPU();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::draw(ShaderProgram *shaderProgram) const
|
|
||||||
{
|
{
|
||||||
// Iterate through every mesh and call the draw function
|
// Iterate through every mesh and call the draw function
|
||||||
for (const auto &mesh : m_meshes) {
|
for (const auto &mesh : m_meshes) {
|
||||||
mesh->draw(shaderProgram);
|
mesh.draw(shaderProgram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,126 +17,11 @@ void Model::drawWithoutTextures() const
|
|||||||
{
|
{
|
||||||
// Iterate through every mesh and call the draw function
|
// Iterate through every mesh and call the draw function
|
||||||
for (const auto &mesh : m_meshes) {
|
for (const auto &mesh : m_meshes) {
|
||||||
mesh->drawWithoutTextures();
|
mesh.drawWithoutTextures();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh *Model::getMesh(unsigned int index) const
|
auto Model::getMesh(unsigned int index) -> Mesh *
|
||||||
{
|
{
|
||||||
return m_meshes[index];
|
return &m_meshes[index];
|
||||||
}
|
|
||||||
|
|
||||||
void Model::loadModel(const std::string &pathToModel)
|
|
||||||
{
|
|
||||||
std::ifstream input(pathToModel, std::ios::in | std::ios::binary);
|
|
||||||
|
|
||||||
if (!input.is_open()) {
|
|
||||||
Log::logger().warn("Could not find model file {}", pathToModel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t numTextures;
|
|
||||||
input.read((char *)&numTextures, sizeof(uint32_t));
|
|
||||||
|
|
||||||
std::vector<TextureType> textureTypes;
|
|
||||||
for (unsigned int i = 0; i < numTextures; i++) {
|
|
||||||
TextureType currentTextureType;
|
|
||||||
input.read((char *)¤tTextureType, sizeof(uint32_t));
|
|
||||||
textureTypes.push_back(currentTextureType);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> textureSources;
|
|
||||||
for (unsigned int i = 0; i < numTextures; i++) {
|
|
||||||
std::string currentTextureSource;
|
|
||||||
for (unsigned int k = 0; k < 128; k++) {
|
|
||||||
uint8_t currentChar;
|
|
||||||
input.read((char *)¤tChar, sizeof(uint8_t));
|
|
||||||
|
|
||||||
if (currentChar) {
|
|
||||||
currentTextureSource.push_back(static_cast<char>(currentChar));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
textureSources.push_back(currentTextureSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maybe write a texture loader class in future, that handles all this.
|
|
||||||
{
|
|
||||||
std::vector<std::future<void>> futures;
|
|
||||||
std::mutex mutex;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < numTextures; i++) {
|
|
||||||
std::string texturePath = m_workingPath + '/' + textureSources[i].c_str();
|
|
||||||
|
|
||||||
auto loadModel = [=, this, &mutex]() {
|
|
||||||
ResourceId texture = ResourceHandler::instance().registerResource<Texture>(
|
|
||||||
TextureDescriptor{texturePath, textureTypes[i]});
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
m_textures.push_back(texture);
|
|
||||||
};
|
|
||||||
|
|
||||||
futures.push_back(std::async(std::launch::async, loadModel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When there is no normal map bound, please use fallback texture
|
|
||||||
bool hasNormalMap = false;
|
|
||||||
for (auto it = textureTypes.begin(); it != textureTypes.end(); it++) {
|
|
||||||
if (*it == TextureType::Normal)
|
|
||||||
hasNormalMap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasNormalMap) {
|
|
||||||
ResourceId texture = ResourceHandler::instance().registerResource<Texture>(
|
|
||||||
TextureDescriptor{"data/res/models/tex/fallback_normal.png", TextureType::Normal});
|
|
||||||
|
|
||||||
m_textures.push_back(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here starts the first mesh
|
|
||||||
uint32_t numMeshes;
|
|
||||||
input.read((char *)&numMeshes, sizeof(uint32_t));
|
|
||||||
|
|
||||||
for (unsigned int j = 0; j < numMeshes; j++) {
|
|
||||||
uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds;
|
|
||||||
|
|
||||||
input.read((char *)&numMeshVertices, sizeof(uint32_t));
|
|
||||||
input.read((char *)&numMeshIndices, sizeof(uint32_t));
|
|
||||||
input.read((char *)&numMeshTextureIds, sizeof(uint32_t));
|
|
||||||
|
|
||||||
uint32_t vertexBlockSize = numMeshVertices * sizeof(Vertex);
|
|
||||||
uint32_t indexBlockSize = numMeshIndices * sizeof(uint32_t);
|
|
||||||
|
|
||||||
// Here starts the first Vertex data
|
|
||||||
|
|
||||||
std::vector<Vertex> meshVertices;
|
|
||||||
meshVertices.resize(numMeshVertices);
|
|
||||||
input.read((char *)meshVertices.data(), vertexBlockSize);
|
|
||||||
|
|
||||||
std::vector<uint32_t> meshIndices;
|
|
||||||
meshIndices.resize(numMeshIndices);
|
|
||||||
input.read((char *)meshIndices.data(), indexBlockSize);
|
|
||||||
|
|
||||||
std::vector<uint32_t> meshTextureIds;
|
|
||||||
std::vector<ResourceId> meshTextures;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < numMeshTextureIds; i++) {
|
|
||||||
uint32_t currentTextureId;
|
|
||||||
input.read((char *)¤tTextureId, sizeof(uint32_t));
|
|
||||||
meshTextureIds.push_back(currentTextureId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasNormalMap) {
|
|
||||||
// This will be the last texture
|
|
||||||
meshTextureIds.push_back(numTextures);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto textureId : meshTextureIds) {
|
|
||||||
meshTextures.push_back(m_textures[textureId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_meshes.push_back(new Mesh(std::move(meshVertices), std::move(meshIndices), std::move(meshTextures)));
|
|
||||||
}
|
|
||||||
|
|
||||||
input.close();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,19 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct ModelDescriptor
|
class Model
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
std::string path;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Model : public Resource, public NamedResource
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Model(const ModelDescriptor &descriptor);
|
Model(std::string_view name, std::vector<Mesh> meshes);
|
||||||
|
|
||||||
void draw(ShaderProgram *shaderProgram) const;
|
void draw(ShaderProgram const &shaderProgram) const;
|
||||||
void drawWithoutTextures() const;
|
void drawWithoutTextures() const;
|
||||||
|
|
||||||
Mesh *getMesh(unsigned int index) const; // TODO...
|
auto getMesh(unsigned int index) -> Mesh *; // TODO...
|
||||||
|
|
||||||
protected:
|
|
||||||
void initialize() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadModel(const std::string &pathToModel);
|
std::vector<Mesh> m_meshes;
|
||||||
|
|
||||||
std::vector<Mesh *> m_meshes;
|
|
||||||
std::vector<ResourceId> m_textures;
|
std::vector<ResourceId> m_textures;
|
||||||
|
|
||||||
std::string m_workingPath;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "ResourceHandler.h"
|
#include "ResourceHandler.h"
|
||||||
#include "../util/Log.h"
|
#include "../util/Log.h"
|
||||||
#include "CubeMap.h"
|
#include "CubeMap.h"
|
||||||
#include "Model.h"
|
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -24,7 +23,6 @@ auto ResourceHandler::registerResource(Param const &...param) -> ResourceId
|
|||||||
template ResourceId ResourceHandler::registerResource<Texture>(TextureDescriptor const &);
|
template ResourceId ResourceHandler::registerResource<Texture>(TextureDescriptor const &);
|
||||||
template ResourceId ResourceHandler::registerResource<TextureCubeMap>(TextureCubeMapDescriptor const &);
|
template ResourceId ResourceHandler::registerResource<TextureCubeMap>(TextureCubeMapDescriptor const &);
|
||||||
template ResourceId ResourceHandler::registerResource<InternalCubeMap>(int const &);
|
template ResourceId ResourceHandler::registerResource<InternalCubeMap>(int const &);
|
||||||
template ResourceId ResourceHandler::registerResource<Model>(ModelDescriptor const &);
|
|
||||||
|
|
||||||
auto ResourceHandler::resource(const ResourceId resourceId) const -> std::shared_ptr<Resource>
|
auto ResourceHandler::resource(const ResourceId resourceId) const -> std::shared_ptr<Resource>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "../ShaderProgram.h"
|
#include "../ShaderProgram.h"
|
||||||
#include "../util/Log.h"
|
#include "../util/Log.h"
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
|
|
||||||
Texture::Texture(const TextureDescriptor &descriptor)
|
Texture::Texture(const TextureDescriptor &descriptor)
|
||||||
@@ -20,16 +19,17 @@ Texture::Texture(const TextureDescriptor &descriptor)
|
|||||||
m_textureHeight = static_cast<unsigned>(textureHeight);
|
m_textureHeight = static_cast<unsigned>(textureHeight);
|
||||||
m_numComponents = static_cast<unsigned>(numComponents);
|
m_numComponents = static_cast<unsigned>(numComponents);
|
||||||
|
|
||||||
if (!m_textureBuffer)
|
if (m_textureBuffer == nullptr) {
|
||||||
Log::logger().warn("Texture {} could not be loaded", resourcePath().string());
|
Log::logger().warn("Texture {} could not be loaded", resourcePath().string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::initialize()
|
void Texture::initialize()
|
||||||
{
|
{
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
|
||||||
GLenum internalFormat;
|
GLenum internalFormat{};
|
||||||
GLenum dataFormat;
|
GLenum dataFormat{};
|
||||||
|
|
||||||
switch (m_numComponents) {
|
switch (m_numComponents) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -52,7 +52,7 @@ void Texture::initialize()
|
|||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.0f);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.0F);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
@@ -66,12 +66,12 @@ void Texture::initialize()
|
|||||||
stbi_image_free(m_textureBuffer);
|
stbi_image_free(m_textureBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureType Texture::textureType() const
|
auto Texture::textureType() const -> TextureType
|
||||||
{
|
{
|
||||||
return m_textureType;
|
return m_textureType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) const
|
void Texture::bind(uint8_t textureUnit, ShaderProgram const &shaderProgram, uint8_t textureTypeNum) const
|
||||||
{
|
{
|
||||||
std::string uniformName = "texture_";
|
std::string uniformName = "texture_";
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t te
|
|||||||
// Add u_material as we store textures in a struct
|
// Add u_material as we store textures in a struct
|
||||||
uniformName = "u_material." + uniformName;
|
uniformName = "u_material." + uniformName;
|
||||||
|
|
||||||
shaderProgram->setUniform(uniformName.c_str(), textureUnit);
|
shaderProgram.setUniform(uniformName, textureUnit);
|
||||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_glId);
|
glBindTexture(GL_TEXTURE_2D, m_glId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include "AbstractTexture.h"
|
#include "AbstractTexture.h"
|
||||||
#include "TextureType.h"
|
#include "TextureType.h"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class ShaderProgram;
|
class ShaderProgram;
|
||||||
|
|
||||||
@@ -19,9 +19,9 @@ class Texture : public AbstractTexture
|
|||||||
public:
|
public:
|
||||||
Texture(const TextureDescriptor &descriptor);
|
Texture(const TextureDescriptor &descriptor);
|
||||||
|
|
||||||
TextureType textureType() const;
|
[[nodiscard]] auto textureType() const -> TextureType;
|
||||||
|
|
||||||
void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) const;
|
void bind(uint8_t textureUnit, ShaderProgram const &shaderProgram, uint8_t textureTypeNum) const;
|
||||||
void unbind() const override;
|
void unbind() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
Reference in New Issue
Block a user