Bind texture units using GpuMaterial
This commit is contained in:
@@ -69,7 +69,6 @@ void main()
|
||||
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
|
||||
}
|
||||
|
||||
fragmentColor = vec3(1.,1.,1.);
|
||||
f_color = vec4(fragmentColor, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,20 +3,16 @@ add_library(fever_engine
|
||||
Controller.cpp
|
||||
Window.cpp
|
||||
ShaderProgram.cpp
|
||||
VertexArray.cpp
|
||||
Camera.cpp
|
||||
Mesh.cpp
|
||||
Entity.cpp
|
||||
Light.cpp
|
||||
Scene.cpp
|
||||
FrameBuffer.cpp
|
||||
Helper.cpp
|
||||
resources/Texture.cpp
|
||||
resources/Model.cpp
|
||||
util/Log.cpp
|
||||
image.cpp
|
||||
mesh.cpp
|
||||
gltf_loader.cpp
|
||||
material.cpp
|
||||
)
|
||||
|
||||
target_compile_features(fever_engine PUBLIC cxx_std_20)
|
||||
|
||||
@@ -3,12 +3,9 @@
|
||||
#include "FrameBuffer.h"
|
||||
#include "Helper.h"
|
||||
#include "Light.h"
|
||||
#include "Mesh.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Window.h"
|
||||
#include "definitions/attribute_locations.h"
|
||||
#include "gltf_loader.h"
|
||||
#include "resources/Model.h"
|
||||
#include "util/Log.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
@@ -31,30 +28,6 @@ Controller::Controller()
|
||||
m_gameWindow->dimensions().second,
|
||||
postProcessingProgram)
|
||||
{
|
||||
// fx::gltf::ReadQuotas read_quotas{.MaxFileSize = 512 * 1024 * 1024,
|
||||
// .MaxBufferByteLength = 512 * 1024 * 1024};
|
||||
|
||||
// // auto gltf_path = std::filesystem::path("Lantern/glTF/Lantern.gltf");
|
||||
// // auto gltf_path = std::filesystem::path("WaterBottle/glTF/WaterBottle.gltf");
|
||||
// auto gltf_path = std::filesystem::path("ABeautifulGame.glb");
|
||||
// auto gltf = [&]() {
|
||||
// if (gltf_path.extension() == ".gltf") {
|
||||
// return fx::gltf::LoadFromText(gltf_path, read_quotas);
|
||||
// }
|
||||
|
||||
// return fx::gltf::LoadFromBinary(gltf_path, read_quotas);
|
||||
// }();
|
||||
|
||||
// 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");
|
||||
// locations.tangent = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_tangent");
|
||||
|
||||
// ShaderProgram::unbind();
|
||||
|
||||
// if (!gltf.cameras.empty()) {
|
||||
// auto const &gltf_camera = gltf.cameras.at(0);
|
||||
|
||||
@@ -65,90 +38,6 @@ Controller::Controller()
|
||||
// } else {
|
||||
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
|
||||
// }
|
||||
|
||||
// std::vector<Model> models;
|
||||
// for (auto const &mesh : gltf.meshes) {
|
||||
// std::vector<Mesh_> meshes;
|
||||
// for (auto const &primitive : mesh.primitives) {
|
||||
// auto const &material = gltf.materials.at(primitive.material);
|
||||
// auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index;
|
||||
// auto normalTexture = material.normalTexture.index;
|
||||
|
||||
// std::vector<std::reference_wrapper<const Texture>> primitive_textures;
|
||||
|
||||
// // Check if texture already exists, if not load it.
|
||||
// if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) {
|
||||
// auto const &gltf_texture = gltf.textures.at(baseColorTexture);
|
||||
// m_textures.emplace(baseColorTexture,
|
||||
// Texture(gltf_texture,
|
||||
// gltf_path.parent_path(),
|
||||
// gltf.images,
|
||||
// gltf.bufferViews,
|
||||
// gltf.buffers,
|
||||
// gltf.samplers,
|
||||
// TextureType::Diffuse));
|
||||
|
||||
// primitive_textures.emplace_back(m_textures.at(baseColorTexture));
|
||||
// }
|
||||
|
||||
// if (normalTexture != -1 && !m_textures.contains(normalTexture)) {
|
||||
// auto const &gltf_texture = gltf.textures.at(normalTexture);
|
||||
// m_textures.emplace(normalTexture,
|
||||
// Texture(gltf_texture,
|
||||
// gltf_path.parent_path(),
|
||||
// gltf.images,
|
||||
// gltf.bufferViews,
|
||||
// gltf.buffers,
|
||||
// gltf.samplers,
|
||||
// TextureType::Normal));
|
||||
|
||||
// primitive_textures.emplace_back(m_textures.at(normalTexture));
|
||||
// }
|
||||
|
||||
// meshes.emplace_back(Mesh_({primitive, gltf, locations}, primitive_textures));
|
||||
// }
|
||||
// models.emplace_back(Model(mesh.name, std::move(meshes)));
|
||||
// }
|
||||
// m_models = std::move(models);
|
||||
|
||||
// std::vector<ModelEntity> entities;
|
||||
// for (auto const &node : gltf.nodes) {
|
||||
// if (node.mesh == -1) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// 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 &node : gltf.nodes) {
|
||||
// for (auto const &child : node.children) {
|
||||
// if (!node.translation.empty()) {
|
||||
// entities[child].translate(
|
||||
// glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// m_entities = std::move(entities);
|
||||
}
|
||||
|
||||
void Controller::run()
|
||||
@@ -191,13 +80,6 @@ void Controller::run()
|
||||
m_camera->getViewProj(),
|
||||
m_camera->getPosition());
|
||||
|
||||
// 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.drawOnEntireScreen();
|
||||
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "VertexArray.h"
|
||||
#include "resources/Model.h"
|
||||
#include "Entity.h"
|
||||
#include "resources/Texture.h"
|
||||
#include "Scene.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@@ -45,10 +41,6 @@ private:
|
||||
|
||||
Scene m_scene;
|
||||
|
||||
std::vector<ModelEntity> m_entities;
|
||||
std::vector<Model> m_models;
|
||||
std::unordered_map<unsigned, Texture> m_textures;
|
||||
|
||||
double m_deltaTime{};
|
||||
float m_exposure = 1.0;
|
||||
};
|
||||
|
||||
161
src/Entity.cpp
161
src/Entity.cpp
@@ -1,161 +0,0 @@
|
||||
#include "Entity.h"
|
||||
#include "Mesh.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "VertexArray.h"
|
||||
#include "resources/Model.h"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
uint32_t Entity::s_idCounter = 0;
|
||||
|
||||
Entity::Entity(const std::string &name) : m_id(s_idCounter++), m_uniqueName(name)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t Entity::getId() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
const std::string &Entity::getUniqueName() const
|
||||
{
|
||||
return m_uniqueName;
|
||||
}
|
||||
|
||||
void Entity::translate(glm::vec3 vector)
|
||||
{
|
||||
m_position += vector;
|
||||
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::rotate(glm::vec3 axis, float radians)
|
||||
{
|
||||
glm::quat rotation = glm::angleAxis(radians, axis);
|
||||
m_quaternion = rotation * m_quaternion;
|
||||
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::setPosition(glm::vec3 position)
|
||||
{
|
||||
m_position = position;
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::setRotation(glm::vec3 eulerAngles)
|
||||
{
|
||||
m_quaternion = glm::quat(eulerAngles);
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::setRotation(glm::vec3 axis, float radians)
|
||||
{
|
||||
m_quaternion = glm::angleAxis(radians, axis);
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::setScale(float scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
updateModelMatrix();
|
||||
}
|
||||
|
||||
void Entity::updateModelMatrix()
|
||||
{
|
||||
// Translate * Rotate * Scale * vertex_vec;
|
||||
// First scaling, then rotation, then translation
|
||||
|
||||
// Translate
|
||||
glm::mat4 translationMatrix = glm::translate(glm::mat4(1.0f), m_position);
|
||||
|
||||
// Rotate
|
||||
glm::mat4 rotationMatrix = glm::toMat4(m_quaternion);
|
||||
|
||||
// Scale
|
||||
glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(m_scale, m_scale, m_scale));
|
||||
|
||||
m_modelMatrix = translationMatrix * rotationMatrix * scaleMatrix;
|
||||
}
|
||||
|
||||
glm::vec3 Entity::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
glm::mat4 Entity::getModelMatrix() const
|
||||
{
|
||||
return m_modelMatrix;
|
||||
}
|
||||
|
||||
ModelEntity::ModelEntity(Entity::Prototype prototype, Model const &model, ShaderProgram const &shaderProgram)
|
||||
: Entity(prototype.name), m_model(model), m_shaderProgram(shaderProgram)
|
||||
{
|
||||
setPosition(prototype.position);
|
||||
setRotation(prototype.rotation);
|
||||
setScale(prototype.scale);
|
||||
}
|
||||
|
||||
void ModelEntity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) const
|
||||
{
|
||||
m_shaderProgram.bind();
|
||||
|
||||
glm::mat4 modelViewProj = viewProjMatrix * m_modelMatrix;
|
||||
m_shaderProgram.setUniform("u_modelViewProjMatrix", modelViewProj);
|
||||
m_shaderProgram.setUniform("u_modelMatrix", m_modelMatrix);
|
||||
m_shaderProgram.setUniform("u_viewPosition", viewPosition);
|
||||
|
||||
// Draw the model
|
||||
m_model.draw(m_shaderProgram);
|
||||
|
||||
m_shaderProgram.unbind();
|
||||
}
|
||||
|
||||
Skybox::Skybox(Prototype prototype, Model *cubeModel, ShaderProgram *shaderProgram)
|
||||
: m_cubeModel(cubeModel), m_shaderProgram(shaderProgram), m_vertexArray(cubeModel->getMesh(0)->getVertexArray())
|
||||
{
|
||||
// m_cubeMap =
|
||||
// ResourceHandler::instance().registerResource<TextureCubeMap>(TextureCubeMapDescriptor{prototype.texturePath});
|
||||
}
|
||||
|
||||
Skybox::~Skybox()
|
||||
{
|
||||
// delete m_cubeMap;
|
||||
}
|
||||
|
||||
void Skybox::initializeOnGPU()
|
||||
{
|
||||
// m_cubeMap->initializeOnGPU();
|
||||
}
|
||||
|
||||
void Skybox::draw(glm::mat4 viewMatrix, glm::mat4 projectionMatrix)
|
||||
{
|
||||
// To disable face culling first get current state
|
||||
GLboolean active;
|
||||
glGetBooleanv(GL_CULL_FACE_MODE, &active);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
m_shaderProgram->bind();
|
||||
|
||||
// Delete any translation from the skybox cube
|
||||
glm::mat4 viewProjectionMatrix = projectionMatrix * glm::mat4(glm::mat3(viewMatrix));
|
||||
|
||||
m_shaderProgram->setUniform("u_viewProjectionMatrix", viewProjectionMatrix);
|
||||
|
||||
// auto cubeMap = std::static_pointer_cast<TextureCubeMap>(ResourceHandler::instance().resource(m_cubeMap));
|
||||
// cubeMap->bind(m_shaderProgram);
|
||||
// m_cubeModel->getMesh(0)->drawWithoutTextures();
|
||||
// cubeMap->unbind();
|
||||
|
||||
m_shaderProgram->unbind();
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Restore face culling
|
||||
if (active) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
} else {
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
100
src/Entity.h
100
src/Entity.h
@@ -1,100 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "resources/Resource.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class VertexArray;
|
||||
class ShaderProgram;
|
||||
class Model;
|
||||
class TextureCubeMap;
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
struct Prototype
|
||||
{
|
||||
Prototype(const std::string &_name, glm::vec3 _position, glm::vec3 _rotation, float _scale)
|
||||
: name(_name), position(_position), rotation(_rotation), scale(_scale)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name;
|
||||
glm::vec3 position;
|
||||
glm::vec3 rotation;
|
||||
float scale;
|
||||
};
|
||||
|
||||
Entity(const std::string &name);
|
||||
virtual ~Entity() = default;
|
||||
|
||||
uint32_t getId() const;
|
||||
const std::string &getUniqueName() const;
|
||||
|
||||
void translate(glm::vec3 vector);
|
||||
void rotate(glm::vec3 axis, float radians);
|
||||
|
||||
void setPosition(glm::vec3 position);
|
||||
void setRotation(glm::vec3 eulerAngles);
|
||||
void setRotation(glm::vec3 axis, float radians);
|
||||
void setScale(float scale);
|
||||
|
||||
glm::vec3 getPosition() const;
|
||||
glm::mat4 getModelMatrix() const;
|
||||
|
||||
protected:
|
||||
void updateModelMatrix();
|
||||
|
||||
const uint32_t m_id;
|
||||
static uint32_t s_idCounter;
|
||||
|
||||
std::string m_uniqueName;
|
||||
|
||||
glm::mat4 m_modelMatrix = glm::mat4(1.0f);
|
||||
glm::vec3 m_position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::vec3 m_velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::quat m_quaternion;
|
||||
float m_scale = 1.0f;
|
||||
};
|
||||
|
||||
class ModelEntity : public Entity
|
||||
{
|
||||
public:
|
||||
ModelEntity(Entity::Prototype prototype, Model const &model, ShaderProgram const &shaderProgram);
|
||||
|
||||
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) const;
|
||||
|
||||
private:
|
||||
Model const &m_model;
|
||||
ShaderProgram const &m_shaderProgram;
|
||||
};
|
||||
|
||||
class Skybox
|
||||
{
|
||||
public:
|
||||
struct Prototype
|
||||
{
|
||||
std::string texturePath;
|
||||
};
|
||||
|
||||
Skybox(Prototype prototype, Model *cubeModel, ShaderProgram *shaderProgram);
|
||||
~Skybox();
|
||||
|
||||
void initializeOnGPU();
|
||||
|
||||
void draw(glm::mat4 viewMatrix, glm::mat4 projectionMatrix);
|
||||
|
||||
private:
|
||||
bool m_isInitialized = false;
|
||||
|
||||
Model *m_cubeModel;
|
||||
ShaderProgram *m_shaderProgram;
|
||||
|
||||
ResourceId m_cubeMap;
|
||||
|
||||
VertexArray *m_vertexArray;
|
||||
};
|
||||
@@ -4,19 +4,17 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
AbstractFrameBuffer::~AbstractFrameBuffer() = default;
|
||||
|
||||
void AbstractFrameBuffer::bind() const
|
||||
void Framebuffer::bind() const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
|
||||
}
|
||||
|
||||
void AbstractFrameBuffer::unbind() const
|
||||
void Framebuffer::unbind()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
GLuint AbstractFrameBuffer::getFBO() const
|
||||
GLuint Framebuffer::getFBO() const
|
||||
{
|
||||
return m_FBO;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "resources/Resource.h"
|
||||
|
||||
#include <glad/gl.h>
|
||||
|
||||
class ShaderProgram;
|
||||
class CubeMap;
|
||||
|
||||
class AbstractFrameBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~AbstractFrameBuffer() = 0;
|
||||
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
GLuint getFBO() const;
|
||||
|
||||
protected:
|
||||
GLuint m_FBO;
|
||||
};
|
||||
|
||||
class Framebuffer : public AbstractFrameBuffer
|
||||
class Framebuffer
|
||||
{
|
||||
public:
|
||||
Framebuffer(uint32_t width, uint32_t height, ShaderProgram &shaderProgram);
|
||||
~Framebuffer();
|
||||
|
||||
void bind() const;
|
||||
static void unbind();
|
||||
GLuint getFBO() const;
|
||||
|
||||
void drawOnEntireScreen() const;
|
||||
|
||||
void changeDimensions(uint32_t width, uint32_t height);
|
||||
@@ -39,6 +27,7 @@ private:
|
||||
|
||||
GLuint m_colorBuffer;
|
||||
GLuint m_depthStencilBuffer;
|
||||
GLuint m_FBO;
|
||||
|
||||
ShaderProgram &m_shaderProgram;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
uint32_t Light::s_idCounter = 0;
|
||||
|
||||
Light::Light(const std::string &name, glm::vec3 color, float intensity, ShaderProgram *shaderProgram)
|
||||
: Entity(name), m_shaderProgram(shaderProgram), m_intensity(intensity), m_lightColor(color * intensity)
|
||||
: m_shaderProgram(shaderProgram), m_intensity(intensity), m_lightColor(color * intensity)
|
||||
{
|
||||
m_id = s_idCounter++;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
|
||||
#define NUM_POINT_LIGHTS 1
|
||||
|
||||
class ShaderProgram;
|
||||
|
||||
class Light : public Entity
|
||||
class Light
|
||||
{
|
||||
public:
|
||||
struct Prototype
|
||||
|
||||
47
src/Mesh.cpp
47
src/Mesh.cpp
@@ -1,47 +0,0 @@
|
||||
#include "Mesh.h"
|
||||
|
||||
#include "ShaderProgram.h"
|
||||
#include "VertexArray.h"
|
||||
#include "resources/Texture.h"
|
||||
#include <utility>
|
||||
|
||||
Mesh_::Mesh_(VertexArray vertexArray, std::vector<std::reference_wrapper<const Texture>> textures)
|
||||
: m_vertexArray(std::move(vertexArray)), m_textures(std::move(textures))
|
||||
{
|
||||
}
|
||||
|
||||
void Mesh_::draw(ShaderProgram const &shaderProgram) const
|
||||
{
|
||||
// Bind all textures in order to its texture unit
|
||||
std::size_t textureNum = 0;
|
||||
for (auto textureIt : m_textures) {
|
||||
textureIt.get().bind(static_cast<uint8_t>(textureNum), shaderProgram);
|
||||
textureNum++;
|
||||
}
|
||||
|
||||
// Draw elements
|
||||
m_vertexArray.bind();
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_vertexArray.indicesCount()),
|
||||
static_cast<GLenum>(m_vertexArray.indicesType()), nullptr);
|
||||
VertexArray::unbind();
|
||||
|
||||
// Unbind all textures
|
||||
for (auto textureIt : m_textures) {
|
||||
textureIt.get().unbind();
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh_::drawWithoutTextures() const
|
||||
{
|
||||
m_vertexArray.bind();
|
||||
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_vertexArray.indicesCount()),
|
||||
static_cast<GLenum>(m_vertexArray.indicesType()), nullptr);
|
||||
|
||||
VertexArray::unbind();
|
||||
}
|
||||
|
||||
auto Mesh_::getVertexArray() -> VertexArray *
|
||||
{
|
||||
return &m_vertexArray;
|
||||
}
|
||||
23
src/Mesh.h
23
src/Mesh.h
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "VertexArray.h"
|
||||
#include "resources/Texture.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ShaderProgram;
|
||||
|
||||
class Mesh_
|
||||
{
|
||||
public:
|
||||
Mesh_(VertexArray vertexArray, std::vector<std::reference_wrapper<const Texture>> textures);
|
||||
|
||||
void draw(ShaderProgram const &shaderProgram) const;
|
||||
void drawWithoutTextures() const;
|
||||
|
||||
auto getVertexArray() -> VertexArray *;
|
||||
|
||||
private:
|
||||
VertexArray m_vertexArray;
|
||||
std::vector<std::reference_wrapper<const Texture>> m_textures;
|
||||
};
|
||||
@@ -72,18 +72,21 @@ Scene::Scene()
|
||||
spawn_node(node, {});
|
||||
}
|
||||
|
||||
auto name_view = m_registry.view<Name>();
|
||||
for (auto [entity, name] : name_view.each()) {
|
||||
Log::logger().info("Hello entity {}!", name);
|
||||
}
|
||||
|
||||
auto mesh_view = m_registry.view<entt::resource<Mesh>>();
|
||||
for (auto [entity, mesh] : mesh_view.each()) {
|
||||
m_registry.emplace<GpuMesh>(entity, GpuMesh{mesh});
|
||||
m_registry.emplace<GpuMesh>(entity, GpuMesh(mesh));
|
||||
|
||||
// Remove Mesh resource as it is no longer needed.
|
||||
m_registry.erase<entt::resource<Mesh>>(entity);
|
||||
}
|
||||
|
||||
auto material_view = m_registry.view<entt::resource<Material>>();
|
||||
for (auto [entity, material] : material_view.each()) {
|
||||
m_registry.emplace<GpuMaterial>(entity, GpuMaterial(material));
|
||||
|
||||
// Remove Material resource as it is no longer needed.
|
||||
m_registry.erase<entt::resource<Material>>(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::update(std::chrono::duration<float> delta,
|
||||
@@ -123,16 +126,19 @@ void Scene::update(std::chrono::duration<float> delta,
|
||||
}
|
||||
}
|
||||
|
||||
auto mesh_view = m_registry.view<GpuMesh, GlobalTransform>();
|
||||
for (auto [entity, mesh, transform] : mesh_view.each()) {
|
||||
auto mesh_view = m_registry.view<GpuMesh const, GpuMaterial const, GlobalTransform const>();
|
||||
for (auto [entity, mesh, material, transform] : mesh_view.each()) {
|
||||
shaderprogram->bind();
|
||||
|
||||
// Bind textures
|
||||
material.bind(*shaderprogram);
|
||||
|
||||
// Bind modelview matrix uniform
|
||||
{
|
||||
glm::mat4 modelViewProj = viewProjMatrix * transform.transform;
|
||||
shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj);
|
||||
// shaderprogram->setUniform("u_modelMatrix", modelMatrix);
|
||||
// shaderprogram->setUniform("u_viewPosition", viewPosition);
|
||||
shaderprogram->setUniform("u_modelMatrix", transform.transform);
|
||||
shaderprogram->setUniform("u_viewPosition", viewPosition);
|
||||
}
|
||||
|
||||
glBindVertexArray(mesh.vao);
|
||||
|
||||
@@ -120,6 +120,12 @@ void ShaderProgram::setUniform(const std::string &name, int value) const
|
||||
glUniform1i(location, value);
|
||||
}
|
||||
|
||||
void ShaderProgram::setUniform(const std::string &name, unsigned int value) const
|
||||
{
|
||||
GLint location = retrieveUniformLocation(name);
|
||||
glUniform1ui(location, value);
|
||||
}
|
||||
|
||||
void ShaderProgram::setUniform(const std::string &name, float value) const
|
||||
{
|
||||
GLint location = retrieveUniformLocation(name);
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
// May be rewritten...
|
||||
void setUniform(const std::string &name, bool value) const;
|
||||
void setUniform(const std::string &name, int value) const;
|
||||
void setUniform(const std::string &name, unsigned int value) const;
|
||||
void setUniform(const std::string &name, float value) const;
|
||||
void setUniform(const std::string &name, glm::vec2 vector) const;
|
||||
void setUniform(const std::string &name, glm::vec3 vector) const;
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
#include "VertexArray.h"
|
||||
#include "definitions/models.h"
|
||||
#include "util/Log.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
static auto accessor_byte_size(fx::gltf::Accessor::Type accessor_type) -> std::size_t
|
||||
{
|
||||
switch (accessor_type) {
|
||||
case fx::gltf::Accessor::Type::Scalar:
|
||||
return 1;
|
||||
case fx::gltf::Accessor::Type::Vec2:
|
||||
return 2;
|
||||
case fx::gltf::Accessor::Type::Vec3:
|
||||
return 3;
|
||||
case fx::gltf::Accessor::Type::Vec4:
|
||||
return 4;
|
||||
default:
|
||||
Log::logger().warn("Unexpected accessor type: {}", static_cast<int>(accessor_type));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
VertexArray::VertexArray(fx::gltf::Primitive const &primitive,
|
||||
fx::gltf::Document const &model,
|
||||
AttributeLocations &locations)
|
||||
{
|
||||
GLuint vao{};
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
if (!primitive.attributes.contains("TANGENT") || !primitive.attributes.contains("NORMAL")) {
|
||||
Log::logger().critical("glTF scene has to include tangent and normal components!");
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
int position_accessor_id = primitive.attributes.at("POSITION");
|
||||
int normal_accessor_id = primitive.attributes.at("NORMAL");
|
||||
int uv_accessor_id = primitive.attributes.at("TEXCOORD_0");
|
||||
int tangent_accessor_id = primitive.attributes.at("TANGENT");
|
||||
int indices_accessor_id = primitive.indices;
|
||||
|
||||
auto const &position_accessor = model.accessors.at(position_accessor_id);
|
||||
auto const &normal_accessor = model.accessors.at(normal_accessor_id);
|
||||
auto const &uv_accessor = model.accessors.at(uv_accessor_id);
|
||||
auto const &tangent_accessor = model.accessors.at(tangent_accessor_id);
|
||||
auto const &indices_accessor = model.accessors.at(indices_accessor_id);
|
||||
|
||||
int position_buffer_view_id = model.accessors[position_accessor_id].bufferView;
|
||||
int normal_buffer_view_id = model.accessors[normal_accessor_id].bufferView;
|
||||
int uv_buffer_view_id = model.accessors[uv_accessor_id].bufferView;
|
||||
int tangent_buffer_view_id = model.accessors[tangent_accessor_id].bufferView;
|
||||
int indices_buffer_view_id = model.accessors[indices_accessor_id].bufferView;
|
||||
|
||||
auto const &position_buffer_view = model.bufferViews.at(position_buffer_view_id);
|
||||
auto const &normal_buffer_view = model.bufferViews.at(normal_buffer_view_id);
|
||||
auto const &uv_buffer_view = model.bufferViews.at(uv_buffer_view_id);
|
||||
auto const &tangent_buffer_view = model.bufferViews.at(tangent_buffer_view_id);
|
||||
auto const &indices_buffer_view = model.bufferViews.at(indices_buffer_view_id);
|
||||
|
||||
auto const &position_buffer = model.buffers.at(position_buffer_view.buffer);
|
||||
auto const &normal_buffer = model.buffers.at(normal_buffer_view.buffer);
|
||||
auto const &uv_buffer = model.buffers.at(uv_buffer_view.buffer);
|
||||
auto const &tangent_buffer = model.buffers.at(tangent_buffer_view.buffer);
|
||||
auto const &indices_buffer = model.buffers.at(indices_buffer_view.buffer);
|
||||
|
||||
GLuint positionVbo{};
|
||||
{
|
||||
glGenBuffers(1, &positionVbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, positionVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
position_buffer_view.byteLength,
|
||||
position_buffer.data.data() + position_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(locations.position);
|
||||
glVertexAttribPointer(locations.position,
|
||||
accessor_byte_size(position_accessor.type),
|
||||
static_cast<GLenum>(position_accessor.componentType),
|
||||
position_accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||
position_buffer_view.byteStride,
|
||||
reinterpret_cast<void *>(position_accessor.byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
// performance-no-int-to-ptr)
|
||||
}
|
||||
|
||||
GLuint normalVbo{};
|
||||
{
|
||||
glGenBuffers(1, &normalVbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, normalVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
normal_buffer_view.byteLength,
|
||||
normal_buffer.data.data() + normal_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(locations.normal);
|
||||
glVertexAttribPointer(locations.normal,
|
||||
accessor_byte_size(normal_accessor.type),
|
||||
static_cast<GLenum>(normal_accessor.componentType),
|
||||
normal_accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||
normal_buffer_view.byteStride,
|
||||
reinterpret_cast<void *>(normal_accessor.byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
// performance-no-int-to-ptr)
|
||||
}
|
||||
|
||||
GLuint uvVbo{};
|
||||
{
|
||||
glGenBuffers(1, &uvVbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
uv_buffer_view.byteLength,
|
||||
uv_buffer.data.data() + uv_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(locations.uv);
|
||||
glVertexAttribPointer(locations.uv,
|
||||
accessor_byte_size(uv_accessor.type),
|
||||
static_cast<GLenum>(uv_accessor.componentType),
|
||||
uv_accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||
uv_buffer_view.byteStride,
|
||||
reinterpret_cast<void *>(uv_accessor.byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
// performance-no-int-to-ptr)
|
||||
}
|
||||
|
||||
GLuint tangentVbo{};
|
||||
{
|
||||
glGenBuffers(1, &tangentVbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tangentVbo);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
tangent_buffer_view.byteLength,
|
||||
tangent_buffer.data.data() + tangent_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(locations.tangent);
|
||||
glVertexAttribPointer(locations.tangent,
|
||||
accessor_byte_size(tangent_accessor.type),
|
||||
static_cast<GLenum>(tangent_accessor.componentType),
|
||||
tangent_accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||
tangent_buffer_view.byteStride,
|
||||
reinterpret_cast<void *>(tangent_accessor.byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
// performance-no-int-to-ptr)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_vao = vao;
|
||||
m_ebo = ebo;
|
||||
m_positionVbo = positionVbo;
|
||||
m_normalVbo = normalVbo;
|
||||
m_uvVbo = uvVbo;
|
||||
m_tangentVbo = tangentVbo;
|
||||
m_indicesCount = indices_accessor.count;
|
||||
m_indicesType = indices_accessor.componentType;
|
||||
}
|
||||
|
||||
VertexArray::~VertexArray()
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_vao);
|
||||
|
||||
glDeleteBuffers(1, &m_positionVbo);
|
||||
glDeleteBuffers(1, &m_normalVbo);
|
||||
glDeleteBuffers(1, &m_uvVbo);
|
||||
glDeleteBuffers(1, &m_tangentVbo);
|
||||
glDeleteBuffers(1, &m_ebo);
|
||||
}
|
||||
|
||||
void VertexArray::bind() const
|
||||
{
|
||||
glBindVertexArray(m_vao);
|
||||
}
|
||||
|
||||
void VertexArray::unbind()
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "definitions/attribute_locations.h"
|
||||
|
||||
#include <glad/gl.h>
|
||||
#include <fx/gltf.h>
|
||||
#include <vector>
|
||||
|
||||
class VertexArray final
|
||||
{
|
||||
public:
|
||||
VertexArray(fx::gltf::Primitive const &primitive, fx::gltf::Document 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_normalVbo(other.m_normalVbo),
|
||||
m_uvVbo(other.m_uvVbo),
|
||||
m_tangentVbo(other.m_tangentVbo),
|
||||
m_ebo(other.m_ebo)
|
||||
{
|
||||
other.m_ebo = 0;
|
||||
other.m_vao = 0;
|
||||
other.m_positionVbo = 0;
|
||||
other.m_normalVbo = 0;
|
||||
other.m_uvVbo = 0;
|
||||
other.m_tangentVbo = 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_normalVbo = other.m_normalVbo;
|
||||
m_uvVbo = other.m_uvVbo;
|
||||
m_tangentVbo = other.m_tangentVbo;
|
||||
m_ebo = other.m_ebo;
|
||||
|
||||
other.m_ebo = 0;
|
||||
other.m_vao = 0;
|
||||
other.m_positionVbo = 0;
|
||||
other.m_normalVbo = 0;
|
||||
other.m_uvVbo = 0;
|
||||
other.m_tangentVbo = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
VertexArray(VertexArray const &) = delete;
|
||||
auto operator=(VertexArray const &) -> VertexArray & = delete;
|
||||
|
||||
~VertexArray();
|
||||
|
||||
void bind() const;
|
||||
static void unbind();
|
||||
|
||||
[[nodiscard]] auto indicesCount() const -> uint64_t { return m_indicesCount; }
|
||||
[[nodiscard]] auto indicesType() const -> fx::gltf::Accessor::ComponentType { return m_indicesType; }
|
||||
|
||||
private:
|
||||
uint64_t m_indicesCount;
|
||||
fx::gltf::Accessor::ComponentType m_indicesType;
|
||||
|
||||
GLuint m_vao;
|
||||
|
||||
GLuint m_positionVbo;
|
||||
GLuint m_normalVbo;
|
||||
GLuint m_uvVbo;
|
||||
GLuint m_tangentVbo;
|
||||
GLuint m_ebo;
|
||||
};
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
struct AttributeLocations
|
||||
{
|
||||
int position;
|
||||
int normal;
|
||||
int uv;
|
||||
int tangent;
|
||||
int position = 0;
|
||||
int uv = 1;
|
||||
int normal = 2;
|
||||
int tangent = 3;
|
||||
};
|
||||
|
||||
static constexpr AttributeLocations ATTRIBUTE_LOCATION;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
// Postition
|
||||
glm::vec3 position;
|
||||
|
||||
// UV Texture Mapping
|
||||
glm::vec2 textureCoords;
|
||||
|
||||
// Normal vector
|
||||
glm::vec3 normalVec;
|
||||
|
||||
// Tangent vector
|
||||
glm::vec3 tangentVec;
|
||||
|
||||
// Bittangent vector
|
||||
glm::vec3 bitangentVec;
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "gltf_loader.h"
|
||||
#include "util/Log.h"
|
||||
#include "definitions/attribute_locations.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
@@ -117,16 +118,16 @@ static auto load_attribute(std::string_view attribute_name,
|
||||
|
||||
auto vertex_attribute_id = [attribute_name]() -> std::optional<std::size_t> {
|
||||
if (attribute_name == "POSITION") {
|
||||
return 0;
|
||||
return ATTRIBUTE_LOCATION.position;
|
||||
}
|
||||
if (attribute_name == "TEXCOORD_0") {
|
||||
return 1;
|
||||
return ATTRIBUTE_LOCATION.uv;
|
||||
}
|
||||
if (attribute_name == "NORMAL") {
|
||||
return 2;
|
||||
return ATTRIBUTE_LOCATION.normal;
|
||||
}
|
||||
if (attribute_name == "TANGENT") {
|
||||
return 3;
|
||||
return ATTRIBUTE_LOCATION.tangent;
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
32
src/material.cpp
Normal file
32
src/material.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "material.h"
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
GpuMaterial::GpuMaterial(Material const &material)
|
||||
{
|
||||
int texture_unit_counter = 0;
|
||||
|
||||
if (material.base_color_texture.has_value()) {
|
||||
Binding binding{.uniform_name = "u_material.texture_diffuse",
|
||||
.texture_unit = texture_unit_counter++};
|
||||
base_color_texture = std::make_pair(GpuImage(material.base_color_texture.value()), binding);
|
||||
}
|
||||
|
||||
if (material.normal_map_texture.has_value()) {
|
||||
Binding binding{.uniform_name = "u_material.texture_normal",
|
||||
.texture_unit = texture_unit_counter++};
|
||||
normal_map_texture = std::make_pair(GpuImage(material.normal_map_texture.value()), binding);
|
||||
}
|
||||
}
|
||||
void GpuMaterial::bind(ShaderProgram const &shader_program) const
|
||||
{
|
||||
auto bind_texture = [&shader_program](auto const &texture) {
|
||||
if (texture.has_value()) {
|
||||
shader_program.setUniform(texture->second.uniform_name, texture->second.texture_unit);
|
||||
glActiveTexture(GL_TEXTURE0 + texture->second.texture_unit);
|
||||
glBindTexture(GL_TEXTURE_2D, texture->first.texture);
|
||||
}
|
||||
};
|
||||
|
||||
bind_texture(base_color_texture);
|
||||
bind_texture(normal_map_texture);
|
||||
}
|
||||
@@ -5,8 +5,26 @@
|
||||
#include <entt/entt.hpp>
|
||||
#include <optional>
|
||||
|
||||
class ShaderProgram;
|
||||
|
||||
struct Material
|
||||
{
|
||||
std::optional<entt::resource<Image>> base_color_texture;
|
||||
std::optional<entt::resource<Image>> normal_map_texture;
|
||||
};
|
||||
|
||||
struct GpuMaterial
|
||||
{
|
||||
GpuMaterial(Material const &material);
|
||||
|
||||
void bind(ShaderProgram const &shader_program) const;
|
||||
|
||||
struct Binding
|
||||
{
|
||||
std::string uniform_name;
|
||||
int texture_unit;
|
||||
};
|
||||
|
||||
std::optional<std::pair<GpuImage, Binding>> base_color_texture;
|
||||
std::optional<std::pair<GpuImage, Binding>> normal_map_texture;
|
||||
};
|
||||
|
||||
@@ -50,6 +50,7 @@ struct GpuMesh
|
||||
{
|
||||
other.vao = 0;
|
||||
}
|
||||
|
||||
auto operator=(GpuMesh &&other) noexcept -> GpuMesh &
|
||||
{
|
||||
vao = other.vao;
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
using Name = std::string;
|
||||
struct Name
|
||||
{
|
||||
std::string name;
|
||||
};
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "Model.h"
|
||||
#include "Texture.h"
|
||||
#include "../util/Log.h"
|
||||
|
||||
Model::Model(std::string_view name, std::vector<Mesh_> meshes) : m_meshes(std::move(meshes)), m_name(name)
|
||||
{
|
||||
Log::logger().trace(R"(Loaded model "{}".)", name);
|
||||
}
|
||||
|
||||
void Model::draw(ShaderProgram const &shaderProgram) const
|
||||
{
|
||||
// Iterate through every mesh and call the draw function
|
||||
for (const auto &mesh : m_meshes) {
|
||||
mesh.draw(shaderProgram);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::drawWithoutTextures() const
|
||||
{
|
||||
// Iterate through every mesh and call the draw function
|
||||
for (const auto &mesh : m_meshes) {
|
||||
mesh.drawWithoutTextures();
|
||||
}
|
||||
}
|
||||
|
||||
auto Model::getMesh(unsigned int index) -> Mesh_ *
|
||||
{
|
||||
return &m_meshes[index];
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Mesh.h"
|
||||
#include "Resource.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
Model(std::string_view name, std::vector<Mesh_> meshes);
|
||||
|
||||
void draw(ShaderProgram const &shaderProgram) const;
|
||||
void drawWithoutTextures() const;
|
||||
|
||||
auto getMesh(unsigned int index) -> Mesh_ *; // TODO...
|
||||
|
||||
private:
|
||||
std::vector<Mesh_> m_meshes;
|
||||
std::vector<ResourceId> m_textures;
|
||||
|
||||
std::string m_name;
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
#include "Resource.h"
|
||||
#include "../util/Log.h"
|
||||
|
||||
ResourceId Resource::s_idCounter = 0;
|
||||
|
||||
Resource::Resource(std::filesystem::path path) : m_id(s_idCounter++), m_path(std::move(path))
|
||||
{
|
||||
Log::logger().info("Resource \"{}\" with id {} created", m_path.string(), m_id);
|
||||
}
|
||||
|
||||
auto Resource::id() const -> ResourceId
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
auto Resource::resourcePath() const -> const std::filesystem::path &
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
auto GlResource::glId() const -> GLuint
|
||||
{
|
||||
return m_glId;
|
||||
}
|
||||
|
||||
NamedResource::NamedResource(std::string name) : m_name(std::move(name))
|
||||
{
|
||||
}
|
||||
|
||||
auto NamedResource::name() const -> const std::string &
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
NamedResource::~NamedResource() = default;
|
||||
@@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <glad/gl.h>
|
||||
#include <string>
|
||||
|
||||
using ResourceId = uint64_t;
|
||||
|
||||
class Resource
|
||||
{
|
||||
public:
|
||||
Resource(std::filesystem::path path);
|
||||
Resource(const Resource &other) = delete;
|
||||
Resource(Resource &&other) = delete;
|
||||
auto operator=(const Resource &other) -> Resource & = delete;
|
||||
auto operator=(Resource &&other) -> Resource & = delete;
|
||||
|
||||
[[nodiscard]] auto id() const -> ResourceId;
|
||||
[[nodiscard]] auto resourcePath() const -> const std::filesystem::path &;
|
||||
|
||||
private:
|
||||
ResourceId m_id;
|
||||
static ResourceId s_idCounter;
|
||||
|
||||
std::filesystem::path m_path;
|
||||
|
||||
friend class ResourceHandler;
|
||||
};
|
||||
|
||||
class GlResource
|
||||
{
|
||||
public:
|
||||
// virtual ~GlResource() = 0; TODO!!
|
||||
virtual void unbind() const = 0;
|
||||
|
||||
auto glId() const -> GLuint;
|
||||
|
||||
protected:
|
||||
GLuint m_glId;
|
||||
};
|
||||
|
||||
class NamedResource
|
||||
{
|
||||
public:
|
||||
NamedResource(std::string name);
|
||||
virtual ~NamedResource() = 0;
|
||||
|
||||
[[nodiscard]] auto name() const -> const std::string &;
|
||||
|
||||
private:
|
||||
const std::string m_name;
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "ResourceHandler.h"
|
||||
#include "../util/Log.h"
|
||||
#include "CubeMap.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
ResourceHandler ResourceHandler::s_instance;
|
||||
|
||||
auto ResourceHandler::instance() -> ResourceHandler &
|
||||
{
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
template <typename T, typename... Param>
|
||||
auto ResourceHandler::registerResource(Param const &...param) -> ResourceId
|
||||
{
|
||||
auto resource = std::make_shared<T>(param...);
|
||||
m_resources.emplace(resource->id(), resource);
|
||||
return resource->id();
|
||||
}
|
||||
|
||||
template ResourceId ResourceHandler::registerResource<TextureCubeMap>(TextureCubeMapDescriptor const &);
|
||||
template ResourceId ResourceHandler::registerResource<InternalCubeMap>(int const &);
|
||||
|
||||
auto ResourceHandler::resource(const ResourceId resourceId) const -> std::shared_ptr<Resource>
|
||||
{
|
||||
auto resourceIt = m_resources.find(resourceId);
|
||||
|
||||
if (resourceIt != m_resources.end()) {
|
||||
auto resource = resourceIt->second;
|
||||
return resource;
|
||||
}
|
||||
|
||||
Log::logger().warn("Could not find resource with id {}", resourceId);
|
||||
return {};
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class ResourceHandler
|
||||
{
|
||||
public:
|
||||
static auto instance() -> ResourceHandler &;
|
||||
|
||||
template <typename T, typename... Param>
|
||||
auto registerResource(Param const &...param) -> ResourceId;
|
||||
|
||||
[[nodiscard]] auto resource(ResourceId resourceId) const -> std::shared_ptr<Resource>;
|
||||
|
||||
private:
|
||||
ResourceHandler() = default;
|
||||
|
||||
static ResourceHandler s_instance;
|
||||
|
||||
std::map<ResourceId, std::shared_ptr<Resource>> m_resources;
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
class ShaderProgram : public GlResource, public NamedResource
|
||||
{
|
||||
public:
|
||||
ShaderProgram();
|
||||
|
||||
void bind() const;
|
||||
void unbind() const override;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "Texture.h"
|
||||
#include "../ShaderProgram.h"
|
||||
#include "../util/Log.h"
|
||||
|
||||
// #define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
Texture::Texture(fx::gltf::Texture const &texture,
|
||||
std::filesystem::path const &working_directory,
|
||||
std::span<fx::gltf::Image> images,
|
||||
std::span<fx::gltf::BufferView> bufferViews,
|
||||
std::span<fx::gltf::Buffer> buffers,
|
||||
std::span<fx::gltf::Sampler> samplers,
|
||||
TextureType textureType)
|
||||
: m_textureType(textureType)
|
||||
{
|
||||
auto sampler_id = texture.sampler;
|
||||
|
||||
auto sampler = [samplers, sampler_id]() {
|
||||
if (sampler_id != -1) {
|
||||
return samplers[static_cast<unsigned>(sampler_id)];
|
||||
}
|
||||
|
||||
return fx::gltf::Sampler{.magFilter = fx::gltf::Sampler::MagFilter::Linear,
|
||||
.minFilter = fx::gltf::Sampler::MinFilter::LinearMipMapLinear,
|
||||
.wrapS = fx::gltf::Sampler::WrappingMode::Repeat,
|
||||
.wrapT = fx::gltf::Sampler::WrappingMode::Repeat};
|
||||
}();
|
||||
|
||||
auto const &image = images[static_cast<unsigned>(texture.source)];
|
||||
auto const &imageBufferView = bufferViews[static_cast<unsigned>(image.bufferView)];
|
||||
auto const &imageBuffer = buffers[static_cast<unsigned>(imageBufferView.buffer)];
|
||||
|
||||
int width{};
|
||||
int height{};
|
||||
int components{};
|
||||
|
||||
auto *stbi_image = [&]() {
|
||||
if (!image.uri.empty()) {
|
||||
auto image_path = working_directory / image.uri;
|
||||
return stbi_load(image_path.c_str(), &width, &height, &components, 0);
|
||||
}
|
||||
|
||||
return stbi_load_from_memory(&imageBuffer.data[imageBufferView.byteOffset],
|
||||
static_cast<int>(imageBufferView.byteOffset),
|
||||
&width,
|
||||
&height,
|
||||
&components,
|
||||
0);
|
||||
}();
|
||||
|
||||
GLenum internalFormat{};
|
||||
GLenum dataFormat{};
|
||||
|
||||
switch (components) {
|
||||
case 1:
|
||||
internalFormat = GL_RED;
|
||||
dataFormat = GL_RED;
|
||||
break;
|
||||
case 3:
|
||||
internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8;
|
||||
dataFormat = GL_RGB;
|
||||
break;
|
||||
case 4:
|
||||
internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
dataFormat = GL_RGBA;
|
||||
break;
|
||||
}
|
||||
|
||||
glGenTextures(1, &m_glId);
|
||||
glBindTexture(GL_TEXTURE_2D, m_glId);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, static_cast<GLint>(sampler.magFilter));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(sampler.minFilter));
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -2.0F);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, static_cast<GLint>(sampler.wrapS));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, static_cast<GLint>(sampler.wrapT));
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
static_cast<GLint>(internalFormat),
|
||||
static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height),
|
||||
0,
|
||||
dataFormat,
|
||||
GL_UNSIGNED_BYTE,
|
||||
stbi_image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
stbi_image_free(stbi_image);
|
||||
|
||||
Log::logger().trace(R"(Loaded texture "{}")", image.name);
|
||||
}
|
||||
|
||||
auto Texture::textureType() const -> TextureType
|
||||
{
|
||||
return m_textureType;
|
||||
}
|
||||
|
||||
void Texture::bind(uint8_t textureUnit, ShaderProgram const &shaderProgram) const
|
||||
{
|
||||
std::string uniformName = "texture_";
|
||||
|
||||
switch (m_textureType) {
|
||||
case TextureType::Diffuse:
|
||||
uniformName += "diffuse";
|
||||
break;
|
||||
case TextureType::Normal:
|
||||
uniformName += "normal";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Add u_material as we store textures in a struct
|
||||
uniformName = "u_material." + uniformName;
|
||||
|
||||
shaderProgram.setUniform(uniformName, textureUnit);
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, m_glId);
|
||||
}
|
||||
|
||||
void Texture::unbind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "TextureType.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fx/gltf.h>
|
||||
#include <glad/gl.h>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
class ShaderProgram;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(fx::gltf::Texture const &texture,
|
||||
std::filesystem::path const &working_directory,
|
||||
std::span<fx::gltf::Image> images,
|
||||
std::span<fx::gltf::BufferView> bufferViews,
|
||||
std::span<fx::gltf::Buffer> buffers,
|
||||
std::span<fx::gltf::Sampler> samplers,
|
||||
TextureType textureType);
|
||||
|
||||
[[nodiscard]] auto textureType() const -> TextureType;
|
||||
|
||||
void bind(uint8_t textureUnit, ShaderProgram const &shaderProgram) const;
|
||||
static void unbind();
|
||||
|
||||
private:
|
||||
TextureType m_textureType;
|
||||
GLuint m_glId = 0;
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
enum class TextureType
|
||||
{
|
||||
Diffuse,
|
||||
Normal,
|
||||
TEXTURE_TYPE_NUM_ITEMS
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
#pragma once
|
||||
Reference in New Issue
Block a user