Port from tinygltf to fx-gltf
This commit is contained in:
@@ -6,6 +6,8 @@ AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: 'false'
|
||||
AlwaysBreakTemplateDeclarations: 'true'
|
||||
BreakBeforeBraces: Mozilla
|
||||
BinPackParameters: 'false'
|
||||
BinPackArguments: 'false'
|
||||
ColumnLimit: '120'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
IndentWidth: '4'
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -13,3 +13,6 @@
|
||||
[submodule "lib/glfw"]
|
||||
path = lib/glfw
|
||||
url = https://github.com/glfw/glfw.git
|
||||
[submodule "lib/fx-gltf"]
|
||||
path = lib/fx-gltf
|
||||
url = https://github.com/jessey-git/fx-gltf.git
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
|
||||
project(
|
||||
Fall-Fever
|
||||
@@ -9,6 +10,11 @@ project(
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz)
|
||||
FetchContent_MakeAvailable(json)
|
||||
|
||||
find_package(glm REQUIRED)
|
||||
find_package(spdlog REQUIRED)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"name": "flags-unix",
|
||||
"hidden": true,
|
||||
"cacheVariables": {
|
||||
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wshadow -Wformat=2 -Wundef -Werror=float-equal"
|
||||
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wshadow -Wformat=2 -Wundef"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,12 +4,12 @@ layout(location = 0) out vec4 f_color;
|
||||
|
||||
in vec3 v_normal;
|
||||
in vec2 v_texCoord;
|
||||
in vec3 v_fragmentPositionTangent;
|
||||
in vec3 v_fragmentPosition;
|
||||
|
||||
in vec3 v_lightDirectionTangent;
|
||||
in vec3 v_lightPositionTangent0;
|
||||
in vec3 v_lightDirection;
|
||||
in vec3 v_lightPosition0;
|
||||
|
||||
in vec3 v_viewPositionTangent;
|
||||
in vec3 v_viewPosition;
|
||||
|
||||
struct Material
|
||||
{
|
||||
@@ -61,12 +61,12 @@ void main()
|
||||
vec3 normal = texture(u_material.texture_normal, v_texCoord).rgb;
|
||||
normal = normalize(normal * 2.0 - 1.0);
|
||||
|
||||
vec3 viewDir = normalize(v_viewPositionTangent - v_fragmentPositionTangent);
|
||||
vec3 viewDir = normalize(v_viewPosition - v_fragmentPosition);
|
||||
|
||||
fragmentColor += directionalLightContribution(u_directionalLight, normal, viewDir);
|
||||
|
||||
for (int i = 0; i < NUM_POINT_LIGHTS; i++) {
|
||||
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPositionTangent, viewDir);
|
||||
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
|
||||
}
|
||||
|
||||
f_color = vec4(fragmentColor, 1.0f);
|
||||
@@ -78,7 +78,7 @@ vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 view
|
||||
if (!light.isActive)
|
||||
return vec3(0.0f);
|
||||
|
||||
vec3 lightDir = normalize(-v_lightDirectionTangent);
|
||||
vec3 lightDir = normalize(-v_lightDirection);
|
||||
|
||||
vec3 diffuseColor = light.color;
|
||||
vec3 specularColor = light.color * 0.5f;
|
||||
@@ -96,7 +96,7 @@ vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 vi
|
||||
if (!light.isActive)
|
||||
return vec3(0.0f);
|
||||
|
||||
vec3 lightDir = normalize(v_lightPositionTangent0 - fragPos);
|
||||
vec3 lightDir = normalize(v_lightPosition0 - fragPos);
|
||||
|
||||
vec3 diffuseColor = light.color;
|
||||
vec3 specularColor = light.color * 0.5f;
|
||||
@@ -105,10 +105,10 @@ vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 vi
|
||||
vec3 ambient, diffuse, specular;
|
||||
computeShading(ambientColor, diffuseColor, specularColor, lightDir, viewDir, normal, ambient, diffuse, specular);
|
||||
|
||||
float attenuation = computeAttenuation(v_lightPositionTangent0, fragPos, 0.032f);
|
||||
// ambient *= attenuation;
|
||||
// diffuse *= attenuation;
|
||||
// specular *= attenuation;
|
||||
float attenuation = computeAttenuation(v_lightPosition0, fragPos, 0.032f);
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ layout(location = 3) in vec4 a_tangent;
|
||||
out vec3 v_normal;
|
||||
out vec2 v_texCoord;
|
||||
|
||||
out vec3 v_fragmentPositionTangent;
|
||||
out vec3 v_fragmentPosition;
|
||||
out vec4 v_fragmentPositionDirectionalLightSpace;
|
||||
|
||||
out vec3 v_viewPositionTangent;
|
||||
out vec3 v_viewPosition;
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
@@ -20,7 +20,7 @@ struct DirectionalLight
|
||||
vec3 color;
|
||||
};
|
||||
uniform DirectionalLight u_directionalLight;
|
||||
out vec3 v_lightDirectionTangent;
|
||||
out vec3 v_lightDirection;
|
||||
|
||||
struct PointLight
|
||||
{
|
||||
@@ -30,7 +30,7 @@ struct PointLight
|
||||
};
|
||||
#define NUM_POINT_LIGHTS 1
|
||||
uniform PointLight u_pointLight[NUM_POINT_LIGHTS];
|
||||
out vec3 v_lightPositionTangent0;
|
||||
out vec3 v_lightPosition0;
|
||||
|
||||
uniform vec3 u_viewPosition;
|
||||
|
||||
@@ -45,14 +45,14 @@ void main()
|
||||
vec3 N = normalize(vec3(u_modelMatrix * vec4(a_normal, 0.0f)));
|
||||
T = normalize(T - dot(T, N) * N);
|
||||
vec3 B = cross(N, T) * a_tangent.w;
|
||||
mat3 TBN_transposed = transpose(mat3(T, B, N));
|
||||
mat3 TBN = transpose(mat3(T, B, N));
|
||||
|
||||
v_lightDirectionTangent = TBN_transposed * u_directionalLight.direction;
|
||||
v_lightPositionTangent0 = TBN_transposed * u_pointLight[0].position;
|
||||
v_lightDirection = TBN * u_directionalLight.direction;
|
||||
v_lightPosition0 = TBN * u_pointLight[0].position;
|
||||
|
||||
v_fragmentPositionTangent = TBN_transposed * vec3(u_modelMatrix * vec4(a_position, 1.0f));
|
||||
v_viewPositionTangent = TBN_transposed * u_viewPosition; // seems like this is always 0 ?
|
||||
v_fragmentPosition = TBN * vec3(u_modelMatrix * vec4(a_position, 1.0f));
|
||||
v_viewPosition = TBN * u_viewPosition;
|
||||
|
||||
v_normal = a_normal;
|
||||
v_normal = N;
|
||||
v_texCoord = a_texCoord;
|
||||
}
|
||||
|
||||
13
lib/CMakeLists.txt
vendored
13
lib/CMakeLists.txt
vendored
@@ -1,13 +1,12 @@
|
||||
option(SPDLOG_NO_EXCEPTIONS "" ON)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glad)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/entt)
|
||||
|
||||
option(TINYGLTF_HEADER_ONLY "" OFF)
|
||||
option(TINYGLTF_INSTALL "" OFF)
|
||||
option(TINYGLTF_NOEXCEPTION "" ON)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tinygltf)
|
||||
|
||||
option(GLFW_BUILD_DOCS "" OFF)
|
||||
option(GLFW_INSTALL "" OFF)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glfw)
|
||||
|
||||
option(FX_GLTF_BUILD_TESTS "" OFF)
|
||||
option(FX_GLTF_INSTALL "" OFF)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/fx-gltf)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/stb)
|
||||
|
||||
1
lib/fx-gltf
vendored
Submodule
1
lib/fx-gltf
vendored
Submodule
Submodule lib/fx-gltf added at 7766c237ea
3
lib/stb/CMakeLists.txt
Normal file
3
lib/stb/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add_library(stb INTERFACE)
|
||||
|
||||
target_include_directories(stb SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
7897
lib/stb/stb_image.h
Normal file
7897
lib/stb/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,15 +8,13 @@ add_library(fever_engine
|
||||
Mesh.cpp
|
||||
Entity.cpp
|
||||
Light.cpp
|
||||
# Scene.cpp
|
||||
Scene.cpp
|
||||
FrameBuffer.cpp
|
||||
Helper.cpp
|
||||
resources/Resource.cpp
|
||||
resources/ResourceHandler.cpp
|
||||
resources/Texture.cpp
|
||||
resources/Model.cpp
|
||||
resources/CubeMap.cpp
|
||||
util/Log.cpp
|
||||
image.cpp
|
||||
)
|
||||
|
||||
target_compile_features(fever_engine PUBLIC cxx_std_20)
|
||||
@@ -27,11 +25,12 @@ target_link_libraries(
|
||||
glad
|
||||
glm
|
||||
glfw
|
||||
glm
|
||||
EnTT::EnTT
|
||||
fmt
|
||||
pthread
|
||||
spdlog
|
||||
tinygltf
|
||||
fx-gltf::fx-gltf
|
||||
stb
|
||||
)
|
||||
|
||||
add_executable(Fall-Fever
|
||||
|
||||
@@ -12,37 +12,23 @@
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <fx/gltf.h>
|
||||
#include <glad/gl.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
Controller::Controller()
|
||||
: m_gameWindow(std::make_shared<Window>()),
|
||||
m_camera(std::make_shared<Camera>(90., m_gameWindow->aspectRatio())),
|
||||
m_postProcessFrameBuffer(m_gameWindow->dimensions().first, m_gameWindow->dimensions().second,
|
||||
postProcessingProgram)
|
||||
m_postProcessFrameBuffer(
|
||||
m_gameWindow->dimensions().first, m_gameWindow->dimensions().second, postProcessingProgram)
|
||||
{
|
||||
tinygltf::TinyGLTF loader;
|
||||
// auto gltf = fx::gltf::LoadFromBinary("ABeautifulGame/ABeautifulGame.glb",
|
||||
// {.MaxFileSize = 512 * 1024 * 1024, .MaxBufferByteLength = 512 * 1024 *
|
||||
// 1024});
|
||||
|
||||
std::string err;
|
||||
std::string warn;
|
||||
// bool ret = loader.LoadASCIIFromFile(&m_model, &err, &warn, "WaterBottle/glTF/WaterBottle.gltf");
|
||||
// bool ret = loader.LoadASCIIFromFile(&m_model, &err, &warn, "Duck/glTF/Duck.gltf");
|
||||
// bool ret = loader.LoadASCIIFromFile(&m_model, &err, &warn, "Lantern/glTF/Lantern.gltf");
|
||||
// bool ret = loader.LoadBinaryFromFile(&m_model, &err, &warn, "Camera.glb");
|
||||
bool ret = loader.LoadBinaryFromFile(&m_model, &err, &warn, "ABeautifulGame/ABeautifulGame.glb");
|
||||
|
||||
if (!warn.empty()) {
|
||||
Log::logger().warn("{}", warn);
|
||||
}
|
||||
|
||||
if (!err.empty()) {
|
||||
Log::logger().error("{}", err);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
Log::logger().error("Failed to parse glTF");
|
||||
}
|
||||
auto gltf_path = std::filesystem::path("Lantern/glTF/Lantern.gltf");
|
||||
auto gltf = fx::gltf::LoadFromText(gltf_path);
|
||||
|
||||
defaultProgram.bind();
|
||||
AttributeLocations locations{};
|
||||
@@ -54,11 +40,22 @@ Controller::Controller()
|
||||
|
||||
ShaderProgram::unbind();
|
||||
|
||||
if (!gltf.cameras.empty()) {
|
||||
auto const &gltf_camera = gltf.cameras.at(0);
|
||||
|
||||
assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective);
|
||||
auto const &perspective = gltf_camera.perspective;
|
||||
|
||||
m_camera = std::make_shared<Camera>(perspective.yfov, perspective.aspectRatio);
|
||||
} else {
|
||||
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
|
||||
}
|
||||
|
||||
std::vector<Model> models;
|
||||
for (auto const &mesh : m_model.meshes) {
|
||||
for (auto const &mesh : gltf.meshes) {
|
||||
std::vector<Mesh> meshes;
|
||||
for (auto const &primitive : mesh.primitives) {
|
||||
auto const &material = m_model.materials.at(primitive.material);
|
||||
auto const &material = gltf.materials.at(primitive.material);
|
||||
auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index;
|
||||
auto normalTexture = material.normalTexture.index;
|
||||
|
||||
@@ -66,31 +63,47 @@ Controller::Controller()
|
||||
|
||||
// Check if texture already exists, if not load it.
|
||||
if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) {
|
||||
auto const &gltf_texture = m_model.textures.at(baseColorTexture);
|
||||
m_textures.emplace(baseColorTexture, Texture(gltf_texture, m_model.images, TextureType::Diffuse));
|
||||
primitive_textures.push_back(m_textures.at(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 = m_model.textures.at(normalTexture);
|
||||
m_textures.emplace(normalTexture, Texture(gltf_texture, m_model.images, TextureType::Normal));
|
||||
primitive_textures.push_back(m_textures.at(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, m_model, locations}, primitive_textures));
|
||||
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 : m_model.nodes) {
|
||||
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);
|
||||
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]));
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
#include "resources/Model.h"
|
||||
#include "Entity.h"
|
||||
#include "resources/Texture.h"
|
||||
#include "Scene.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <tiny_gltf.h>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class Window;
|
||||
class Scene;
|
||||
class Camera;
|
||||
class FrameBuffer;
|
||||
class Framebuffer;
|
||||
|
||||
class Controller
|
||||
{
|
||||
@@ -32,7 +32,6 @@ private:
|
||||
void update_window_dimensions();
|
||||
|
||||
std::shared_ptr<Window> m_gameWindow;
|
||||
|
||||
std::shared_ptr<Camera> m_camera;
|
||||
|
||||
ShaderProgram defaultProgram{{"defaultProgram", "data/shaders/basic.vert", "data/shaders/basic.frag"}};
|
||||
@@ -40,11 +39,11 @@ private:
|
||||
ShaderProgram postProcessingProgram{
|
||||
{"postProcessingProgram", "data/shaders/postprocessing.vert", "data/shaders/postprocessing.frag"}};
|
||||
|
||||
FrameBuffer m_postProcessFrameBuffer;
|
||||
Framebuffer m_postProcessFrameBuffer;
|
||||
|
||||
static constexpr unsigned MAX_FPS = 60;
|
||||
|
||||
tinygltf::Model m_model;
|
||||
Scene m_scene;
|
||||
|
||||
std::vector<ModelEntity> m_entities;
|
||||
std::vector<Model> m_models;
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
#include "Mesh.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "VertexArray.h"
|
||||
#include "resources/CubeMap.h"
|
||||
#include "resources/Model.h"
|
||||
#include "resources/ResourceHandler.h"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
@@ -117,8 +115,8 @@ void ModelEntity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) const
|
||||
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});
|
||||
// m_cubeMap =
|
||||
// ResourceHandler::instance().registerResource<TextureCubeMap>(TextureCubeMapDescriptor{prototype.texturePath});
|
||||
}
|
||||
|
||||
Skybox::~Skybox()
|
||||
@@ -146,10 +144,10 @@ void Skybox::draw(glm::mat4 viewMatrix, glm::mat4 projectionMatrix)
|
||||
|
||||
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();
|
||||
// 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);
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "resources/CubeMap.h"
|
||||
#include "resources/ResourceHandler.h"
|
||||
#include "resources/Texture.h"
|
||||
#include "util/Log.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
AbstractFrameBuffer::~AbstractFrameBuffer()
|
||||
{
|
||||
}
|
||||
AbstractFrameBuffer::~AbstractFrameBuffer() = default;
|
||||
|
||||
void AbstractFrameBuffer::bind() const
|
||||
{
|
||||
@@ -26,7 +21,7 @@ GLuint AbstractFrameBuffer::getFBO() const
|
||||
return m_FBO;
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer(uint32_t width, uint32_t height, ShaderProgram &shaderProgram) : m_shaderProgram(shaderProgram)
|
||||
Framebuffer::Framebuffer(uint32_t width, uint32_t height, ShaderProgram &shaderProgram) : m_shaderProgram(shaderProgram)
|
||||
{
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
|
||||
@@ -34,19 +29,19 @@ FrameBuffer::FrameBuffer(uint32_t width, uint32_t height, ShaderProgram &shaderP
|
||||
setExposureCorrection(true);
|
||||
}
|
||||
|
||||
FrameBuffer::~FrameBuffer()
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
glDeleteFramebuffers(1, &m_FBO);
|
||||
glDeleteTextures(1, &m_colorBuffer);
|
||||
glDeleteRenderbuffers(1, &m_depthStencilBuffer);
|
||||
}
|
||||
|
||||
GLuint FrameBuffer::getTextureId() const
|
||||
GLuint Framebuffer::getTextureId() const
|
||||
{
|
||||
return m_colorBuffer;
|
||||
}
|
||||
|
||||
void FrameBuffer::drawOnEntireScreen() const
|
||||
void Framebuffer::drawOnEntireScreen() const
|
||||
{
|
||||
// Disable wireframe mode
|
||||
GLint wireframe;
|
||||
@@ -71,7 +66,7 @@ void FrameBuffer::drawOnEntireScreen() const
|
||||
m_shaderProgram.unbind();
|
||||
}
|
||||
|
||||
void FrameBuffer::changeDimensions(uint32_t width, uint32_t height)
|
||||
void Framebuffer::changeDimensions(uint32_t width, uint32_t height)
|
||||
{
|
||||
// Delete old textures
|
||||
glDeleteTextures(1, &m_colorBuffer);
|
||||
@@ -80,7 +75,7 @@ void FrameBuffer::changeDimensions(uint32_t width, uint32_t height)
|
||||
generateTextures(width, height);
|
||||
}
|
||||
|
||||
void FrameBuffer::generateTextures(uint32_t width, uint32_t height)
|
||||
void Framebuffer::generateTextures(uint32_t width, uint32_t height)
|
||||
{
|
||||
bind();
|
||||
|
||||
@@ -88,20 +83,24 @@ void FrameBuffer::generateTextures(uint32_t width, uint32_t height)
|
||||
glGenTextures(1, &m_colorBuffer);
|
||||
glGenRenderbuffers(1, &m_depthStencilBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, GL_RGBA,
|
||||
GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_colorBuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0,
|
||||
GL_RGBA, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
std::array<unsigned, 3> attachments = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
|
||||
glDrawBuffers(3, attachments.data());
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height));
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
Log::logger().error("Framebuffer not complete");
|
||||
|
||||
@@ -109,76 +108,9 @@ void FrameBuffer::generateTextures(uint32_t width, uint32_t height)
|
||||
unbind();
|
||||
}
|
||||
|
||||
void FrameBuffer::setExposureCorrection(bool exposureCorrection) const
|
||||
void Framebuffer::setExposureCorrection(bool exposureCorrection) const
|
||||
{
|
||||
m_shaderProgram.bind();
|
||||
m_shaderProgram.setUniform("u_exposureCorrection", exposureCorrection);
|
||||
m_shaderProgram.unbind();
|
||||
}
|
||||
|
||||
AbstractDepthMap::~AbstractDepthMap()
|
||||
{
|
||||
}
|
||||
|
||||
DepthMap::DepthMap(int RESOLUTION)
|
||||
{
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
bind();
|
||||
|
||||
glGenTextures(1, &m_depthMap);
|
||||
glBindTexture(GL_TEXTURE_2D, m_depthMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, RESOLUTION, RESOLUTION, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthMap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
Log::logger().error("Framebuffer not complete");
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
DepthMap::~DepthMap()
|
||||
{
|
||||
// if (m_cubeMap)
|
||||
// delete m_cubeMap;
|
||||
}
|
||||
|
||||
GLuint DepthMap::getDepthMap() const
|
||||
{
|
||||
return m_depthMap;
|
||||
}
|
||||
|
||||
DepthMapCube::DepthMapCube(int resolution)
|
||||
{
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
bind();
|
||||
|
||||
m_cubeMap = ResourceHandler::instance().registerResource<InternalCubeMap>(resolution);
|
||||
GLuint glId = std::static_pointer_cast<InternalCubeMap>(ResourceHandler::instance().resource(m_cubeMap))->glId();
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, glId, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
Log::logger().error("Framebuffer not complete");
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
DepthMapCube::~DepthMapCube()
|
||||
{
|
||||
}
|
||||
|
||||
GLuint DepthMapCube::getCubeMapTextureId()
|
||||
{
|
||||
return std::static_pointer_cast<InternalCubeMap>(ResourceHandler::instance().resource(m_cubeMap))->glId();
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ protected:
|
||||
GLuint m_FBO;
|
||||
};
|
||||
|
||||
class FrameBuffer : public AbstractFrameBuffer
|
||||
class Framebuffer : public AbstractFrameBuffer
|
||||
{
|
||||
public:
|
||||
FrameBuffer(uint32_t width, uint32_t height, ShaderProgram &shaderProgram);
|
||||
~FrameBuffer();
|
||||
Framebuffer(uint32_t width, uint32_t height, ShaderProgram &shaderProgram);
|
||||
~Framebuffer();
|
||||
|
||||
void drawOnEntireScreen() const;
|
||||
|
||||
@@ -42,34 +42,3 @@ private:
|
||||
|
||||
ShaderProgram &m_shaderProgram;
|
||||
};
|
||||
|
||||
class AbstractDepthMap : public AbstractFrameBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~AbstractDepthMap() = 0;
|
||||
};
|
||||
|
||||
// FrameBuffer without color buffer. (Shadows)
|
||||
class DepthMap : public AbstractDepthMap
|
||||
{
|
||||
public:
|
||||
DepthMap(int resolution);
|
||||
~DepthMap();
|
||||
|
||||
GLuint getDepthMap() const;
|
||||
|
||||
private:
|
||||
GLuint m_depthMap;
|
||||
};
|
||||
|
||||
class DepthMapCube : public AbstractDepthMap
|
||||
{
|
||||
public:
|
||||
DepthMapCube(int resolution);
|
||||
~DepthMapCube();
|
||||
|
||||
GLuint getCubeMapTextureId();
|
||||
|
||||
private:
|
||||
ResourceId m_cubeMap;
|
||||
};
|
||||
|
||||
203
src/Scene.cpp
203
src/Scene.cpp
@@ -1,197 +1,20 @@
|
||||
#include "Scene.h"
|
||||
#include "Controller.h"
|
||||
#include "Entity.h"
|
||||
#include "Light.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "resources/Model.h"
|
||||
#include "resources/ResourceHandler.h"
|
||||
#include "util/Log.h"
|
||||
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
Scene::Scene(std::vector<std::shared_ptr<ShaderProgram>> shaderPrograms)
|
||||
: m_shaderProgram(*Controller::getShaderProgramByName("defaultProgram", shaderPrograms))
|
||||
#include <iostream>
|
||||
static void hallo()
|
||||
{
|
||||
std::array modelDescriptors{
|
||||
ModelDescriptor{"fallback", "data/res/models/fallback.ffo"},
|
||||
ModelDescriptor{"backpack", "data/res/models/backpack.ffo"},
|
||||
ModelDescriptor{"ground", "data/res/models/wood_floor.ffo"},
|
||||
ModelDescriptor{"cube", "data/res/models/cube.ffo"},
|
||||
ModelDescriptor{"container", "data/res/models/container.ffo"},
|
||||
std::cout << "Testobj created!\n";
|
||||
}
|
||||
|
||||
Scene::Scene()
|
||||
{
|
||||
struct TestComponent
|
||||
{
|
||||
int x;
|
||||
};
|
||||
|
||||
{
|
||||
std::vector<std::future<void>> futures;
|
||||
std::mutex mutex;
|
||||
auto entity = m_registry.create();
|
||||
|
||||
for (const auto &descriptor : modelDescriptors) {
|
||||
auto sink = m_registry.on_construct<TestComponent>().before();
|
||||
|
||||
auto loadModel = [=, this, &mutex]() {
|
||||
ResourceId model = ResourceHandler::instance().registerResource<Model>(descriptor);
|
||||
|
||||
Log::logger().info("Loaded model \"{}\": {}", descriptor.name, descriptor.path);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
m_models.push_back(model);
|
||||
};
|
||||
|
||||
futures.push_back(std::async(std::launch::async, loadModel));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use geometry shader instead of model and load skybox before models.
|
||||
Skybox::Prototype skyboxPrototype{"data/res/textures/skybox/"};
|
||||
m_skybox = std::make_shared<Skybox>(
|
||||
skyboxPrototype, std::static_pointer_cast<Model>(ResourceHandler::instance().resource("cube")).get(),
|
||||
Controller::getShaderProgramByName("skyboxProgram", shaderPrograms).get());
|
||||
|
||||
Log::logger().info("Loaded skybox: {}", skyboxPrototype.texturePath);
|
||||
m_skybox->initializeOnGPU();
|
||||
|
||||
std::array entityPrototypes{
|
||||
ModelEntity::Prototype{"backpack", {0., 1., 0.}, {}, 0.6F, "backpack", "defaultProgram"},
|
||||
ModelEntity::Prototype{"container", {10., 1., 0.}, {45., 45., 45.}, 1., "container", "defaultProgram"},
|
||||
ModelEntity::Prototype{"ground", {}, {}, 1., "ground", "defaultProgram"},
|
||||
ModelEntity::Prototype{"light", {}, {}, 1., "cube", "lightProgram"},
|
||||
};
|
||||
|
||||
{
|
||||
for (auto &prototype : entityPrototypes) {
|
||||
// Get model
|
||||
const Model *currentModel =
|
||||
std::static_pointer_cast<Model>(ResourceHandler::instance().resource(prototype.modelName)).get();
|
||||
|
||||
if (!currentModel) {
|
||||
// Apply fallback model (first model in vector)
|
||||
currentModel = std::static_pointer_cast<Model>(ResourceHandler::instance().resource("fallback"))
|
||||
.get(); // TODO rename fallbackModel
|
||||
|
||||
Log::logger().warn("Model could not be found by name \"{}\"", prototype.modelName);
|
||||
}
|
||||
|
||||
// Get shaderprogram
|
||||
auto currentProgram = Controller::getShaderProgramByName(prototype.shaderProgramName, shaderPrograms);
|
||||
|
||||
if (!currentProgram) {
|
||||
currentProgram = Controller::getShaderProgramByName("basic", shaderPrograms);
|
||||
}
|
||||
|
||||
m_entities.push_back(std::make_shared<ModelEntity>(prototype, currentModel, currentProgram.get()));
|
||||
|
||||
Log::logger().info("Loaded entity \"{}\" with model \"{}\"", prototype.name, prototype.modelName);
|
||||
}
|
||||
}
|
||||
|
||||
// Order important
|
||||
std::array<std::unique_ptr<Light::Prototype>, 2> lightPrototypes{
|
||||
std::unique_ptr<DirectionalLight::Prototype>(
|
||||
new DirectionalLight::Prototype{"directionalLight", {-0.2, -1.0, -0.3}, {1., 1., 1.}, 0.25}),
|
||||
std::unique_ptr<PointLight::Prototype>(
|
||||
new PointLight::Prototype{"pointLight0", "light", {0., 1., 0.}, {1., 1., 1.}, 7.5}),
|
||||
};
|
||||
|
||||
std::vector<std::shared_ptr<Light>> lights;
|
||||
{
|
||||
for (auto &prototype : lightPrototypes) {
|
||||
std::shared_ptr<Light> currentLight;
|
||||
auto directionalPrototype = dynamic_cast<DirectionalLight::Prototype *>(prototype.get());
|
||||
if (directionalPrototype) {
|
||||
currentLight = std::make_shared<DirectionalLight>(*directionalPrototype, &m_shaderProgram);
|
||||
}
|
||||
auto pointPrototype = dynamic_cast<PointLight::Prototype *>(prototype.get());
|
||||
if (pointPrototype) {
|
||||
currentLight = std::make_shared<PointLight>(*pointPrototype, &m_shaderProgram);
|
||||
}
|
||||
|
||||
lights.push_back(currentLight);
|
||||
Log::logger().info("Loaded light \"{}\"", prototype->name);
|
||||
}
|
||||
}
|
||||
m_lights = lights;
|
||||
}
|
||||
|
||||
void Scene::updatePointLight(unsigned int lightId, bool active, glm::vec3 position, glm::vec3 color, float intensity)
|
||||
{
|
||||
auto pointLights = getPointLights();
|
||||
pointLights[lightId]->setActive(active);
|
||||
pointLights[lightId]->setPosition(position);
|
||||
pointLights[lightId]->setIntensity(intensity);
|
||||
pointLights[lightId]->setColor(color);
|
||||
}
|
||||
|
||||
void Scene::updateDirectionalLight(bool active, glm::vec3 direction, glm::vec3 color)
|
||||
{
|
||||
auto directionalLight = getDirectionalLight();
|
||||
directionalLight->setActive(active);
|
||||
directionalLight->setDirection(direction);
|
||||
directionalLight->setColor(color);
|
||||
}
|
||||
|
||||
void Scene::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition)
|
||||
{
|
||||
// Draw all entities
|
||||
for (auto it = m_entities.begin(); it != m_entities.end(); it++) {
|
||||
(*it)->draw(viewProjMatrix, viewPosition);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ModelEntity> Scene::getEntityByName(const std::string &name)
|
||||
{
|
||||
for (auto it = m_entities.begin(); it != m_entities.end(); it++) {
|
||||
if ((*it)->getUniqueName() == name) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
Log::logger().warn("Entity could not be found by unique name \"{}\"", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ModelEntity> Scene::getEntityById(uint32_t id)
|
||||
{
|
||||
for (auto it = m_entities.begin(); it != m_entities.end(); it++) {
|
||||
if ((*it)->getId() == id) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
Log::logger().warn("Entity could not be found by ID \"{}\"", id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<PointLight>> Scene::getPointLights()
|
||||
{
|
||||
std::vector<std::shared_ptr<PointLight>> temp_pointLights;
|
||||
|
||||
for (auto it = m_lights.begin(); it != m_lights.end(); it++) {
|
||||
auto temp_pointLight = std::dynamic_pointer_cast<PointLight>(*it);
|
||||
if (temp_pointLight) {
|
||||
temp_pointLights.push_back(temp_pointLight);
|
||||
}
|
||||
}
|
||||
|
||||
return temp_pointLights;
|
||||
}
|
||||
|
||||
std::shared_ptr<DirectionalLight> Scene::getDirectionalLight()
|
||||
{
|
||||
std::shared_ptr<DirectionalLight> temp_directionalLight;
|
||||
|
||||
for (auto it = m_lights.begin(); it != m_lights.end(); it++) {
|
||||
temp_directionalLight = std::dynamic_pointer_cast<DirectionalLight>(*it);
|
||||
if (temp_directionalLight)
|
||||
break;
|
||||
}
|
||||
|
||||
return temp_directionalLight;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ModelEntity>> Scene::getEntities()
|
||||
{
|
||||
return m_entities;
|
||||
}
|
||||
|
||||
std::shared_ptr<Skybox> Scene::getSkybox()
|
||||
{
|
||||
return m_skybox;
|
||||
m_registry.emplace<TestComponent>(entity, TestComponent{.x = 2});
|
||||
}
|
||||
38
src/Scene.h
38
src/Scene.h
@@ -1,44 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "resources/Resource.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ModelEntity;
|
||||
class Light;
|
||||
class PointLight;
|
||||
class DirectionalLight;
|
||||
class ShaderProgram;
|
||||
class Skybox;
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
Scene(std::vector<std::shared_ptr<ShaderProgram>> shaderPrograms);
|
||||
|
||||
void updatePointLight(unsigned int lightId, bool active, glm::vec3 position, glm::vec3 color, float intensity);
|
||||
void updateDirectionalLight(bool active, glm::vec3 direction, glm::vec3 color);
|
||||
|
||||
std::vector<std::shared_ptr<ModelEntity>> getEntities();
|
||||
std::vector<std::shared_ptr<PointLight>> getPointLights();
|
||||
std::shared_ptr<DirectionalLight> getDirectionalLight();
|
||||
std::shared_ptr<Skybox> getSkybox();
|
||||
std::shared_ptr<ModelEntity> getEntityByName(const std::string &name);
|
||||
std::shared_ptr<ModelEntity> getEntityById(uint32_t id);
|
||||
|
||||
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition);
|
||||
Scene();
|
||||
|
||||
private:
|
||||
ShaderProgram &m_shaderProgram;
|
||||
|
||||
std::vector<ResourceId> m_models;
|
||||
std::vector<std::shared_ptr<ModelEntity>> m_entities;
|
||||
std::shared_ptr<Skybox> m_skybox;
|
||||
|
||||
// Lights
|
||||
std::vector<std::shared_ptr<Light>> m_lights;
|
||||
entt::registry m_registry;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,25 @@
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
VertexArray::VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model const &model,
|
||||
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{};
|
||||
@@ -14,7 +32,7 @@ VertexArray::VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model c
|
||||
|
||||
if (!primitive.attributes.contains("TANGENT") || !primitive.attributes.contains("NORMAL")) {
|
||||
Log::logger().critical("glTF scene has to include tangent and normal components!");
|
||||
exit(-1);
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
int position_accessor_id = primitive.attributes.at("POSITION");
|
||||
@@ -23,7 +41,6 @@ VertexArray::VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model c
|
||||
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);
|
||||
@@ -52,115 +69,85 @@ VertexArray::VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model c
|
||||
{
|
||||
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);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
position_buffer_view.byteLength,
|
||||
position_buffer.data.data() + position_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
int size = 1;
|
||||
if (position_accessor.type == TINYGLTF_TYPE_SCALAR) {
|
||||
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);
|
||||
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);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
normal_buffer_view.byteLength,
|
||||
normal_buffer.data.data() + normal_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
int size = 1;
|
||||
if (normal_accessor.type == TINYGLTF_TYPE_SCALAR) {
|
||||
size = 1;
|
||||
} else if (normal_accessor.type == TINYGLTF_TYPE_VEC2) {
|
||||
size = 2;
|
||||
} else if (normal_accessor.type == TINYGLTF_TYPE_VEC3) {
|
||||
size = 3;
|
||||
} else if (normal_accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||
size = 4;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int normal_byte_stride = normal_accessor.ByteStride(normal_buffer_view);
|
||||
glEnableVertexAttribArray(locations.normal);
|
||||
glVertexAttribPointer(locations.normal, size, normal_accessor.componentType,
|
||||
normal_accessor.normalized ? GL_TRUE : GL_FALSE, normal_byte_stride,
|
||||
(void *)normal_accessor.byteOffset);
|
||||
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,
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
uv_buffer_view.byteLength,
|
||||
uv_buffer.data.data() + uv_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
int size = 1;
|
||||
if (uv_accessor.type == TINYGLTF_TYPE_SCALAR) {
|
||||
size = 1;
|
||||
} else if (uv_accessor.type == TINYGLTF_TYPE_VEC2) {
|
||||
size = 2;
|
||||
} else if (uv_accessor.type == TINYGLTF_TYPE_VEC3) {
|
||||
size = 3;
|
||||
} else if (uv_accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||
size = 4;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int uv_byte_stride = uv_accessor.ByteStride(uv_buffer_view);
|
||||
glEnableVertexAttribArray(locations.uv);
|
||||
glVertexAttribPointer(locations.uv, size, uv_accessor.componentType,
|
||||
uv_accessor.normalized ? GL_TRUE : GL_FALSE, uv_byte_stride,
|
||||
(void *)uv_accessor.byteOffset);
|
||||
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);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
tangent_buffer_view.byteLength,
|
||||
tangent_buffer.data.data() + tangent_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
int size = 1;
|
||||
if (tangent_accessor.type == TINYGLTF_TYPE_SCALAR) {
|
||||
size = 1;
|
||||
} else if (tangent_accessor.type == TINYGLTF_TYPE_VEC2) {
|
||||
size = 2;
|
||||
} else if (tangent_accessor.type == TINYGLTF_TYPE_VEC3) {
|
||||
size = 3;
|
||||
} else if (tangent_accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||
size = 4;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int tangent_byte_stride = tangent_accessor.ByteStride(tangent_buffer_view);
|
||||
glEnableVertexAttribArray(locations.tangent);
|
||||
glVertexAttribPointer(locations.tangent, size, tangent_accessor.componentType,
|
||||
tangent_accessor.normalized ? GL_TRUE : GL_FALSE, tangent_byte_stride,
|
||||
(void *)tangent_accessor.byteOffset);
|
||||
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);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
indices_buffer_view.byteLength,
|
||||
indices_buffer.data.data() + indices_buffer_view.byteOffset,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#include "definitions/attribute_locations.h"
|
||||
|
||||
#include <glad/gl.h>
|
||||
#include <tiny_gltf.h>
|
||||
#include <fx/gltf.h>
|
||||
#include <vector>
|
||||
|
||||
class VertexArray final
|
||||
{
|
||||
public:
|
||||
VertexArray(tinygltf::Primitive const &primitive, tinygltf::Model const &model, AttributeLocations &locations);
|
||||
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),
|
||||
@@ -58,11 +58,11 @@ public:
|
||||
static void unbind();
|
||||
|
||||
[[nodiscard]] auto indicesCount() const -> uint64_t { return m_indicesCount; }
|
||||
[[nodiscard]] auto indicesType() const -> int { return m_indicesType; }
|
||||
[[nodiscard]] auto indicesType() const -> fx::gltf::Accessor::ComponentType { return m_indicesType; }
|
||||
|
||||
private:
|
||||
uint64_t m_indicesCount;
|
||||
int m_indicesType;
|
||||
fx::gltf::Accessor::ComponentType m_indicesType;
|
||||
|
||||
GLuint m_vao;
|
||||
|
||||
|
||||
0
src/image.cpp
Normal file
0
src/image.cpp
Normal file
5
src/image.h
Normal file
5
src/image.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
struct Image {
|
||||
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
class AbstractTexture : public Resource, public GlResource
|
||||
{
|
||||
public:
|
||||
AbstractTexture(const std::string &path) : Resource(path) {}
|
||||
virtual ~AbstractTexture() = default;
|
||||
|
||||
protected:
|
||||
uint32_t m_textureWidth;
|
||||
uint32_t m_textureHeight;
|
||||
};
|
||||
@@ -2,15 +2,52 @@
|
||||
#include "../ShaderProgram.h"
|
||||
#include "../util/Log.h"
|
||||
|
||||
Texture::Texture(tinygltf::Texture const &texture, std::span<tinygltf::Image> images, TextureType textureType)
|
||||
#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 = texture.sampler;
|
||||
auto const &image = images[texture.source];
|
||||
auto sampler_id = texture.sampler;
|
||||
|
||||
uint32_t width = image.width;
|
||||
uint32_t height = image.height;
|
||||
unsigned int components = image.component;
|
||||
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{};
|
||||
@@ -33,20 +70,29 @@ Texture::Texture(tinygltf::Texture const &texture, std::span<tinygltf::Image> im
|
||||
glGenTextures(1, &m_glId);
|
||||
glBindTexture(GL_TEXTURE_2D, m_glId);
|
||||
|
||||
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_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, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
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, image.image.data());
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
static_cast<GLint>(internalFormat),
|
||||
static_cast<GLsizei>(width),
|
||||
static_cast<GLsizei>(height),
|
||||
0,
|
||||
dataFormat,
|
||||
GL_UNSIGNED_BYTE, // read from bufferview?
|
||||
stbi_image);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Log::logger().trace(R"(Loaded texture "{}".)", image.name);
|
||||
stbi_image_free(stbi_image);
|
||||
|
||||
Log::logger().trace(R"(Loaded texture "{}")", image.name);
|
||||
}
|
||||
|
||||
auto Texture::textureType() const -> TextureType
|
||||
|
||||
@@ -2,17 +2,24 @@
|
||||
|
||||
#include "TextureType.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fx/gltf.h>
|
||||
#include <glad/gl.h>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <tiny_gltf.h>
|
||||
|
||||
class ShaderProgram;
|
||||
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(tinygltf::Texture const &texture, std::span<tinygltf::Image> images, TextureType textureType);
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user