Some refactoring in multithreading.

This commit is contained in:
2021-07-08 17:42:26 +02:00
parent 979ae4686f
commit be4e63046a
42 changed files with 598 additions and 285 deletions

View File

@@ -9,6 +9,5 @@ ColumnLimit: '120'
IndentWidth: '4'
Language: Cpp
PointerAlignment: Right
SortIncludes: false
...

45
.clang-tidy Normal file
View File

@@ -0,0 +1,45 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
CheckOptions:
- key: llvm-else-after-return.WarnOnConditionVariables
value: '0'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons
value: '0'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1'
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
- key: llvm-qualified-auto.AddConstToQualified
value: '0'
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: llvm-else-after-return.WarnOnUnfixable
value: '0'
- key: google-readability-function-size.StatementThreshold
value: '800'
...

View File

@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.10)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(Fall-Fever)
if(WIN32)

View File

@@ -1,14 +1,30 @@
{
"directionalLight": {
"intensity": 0.5,
"direction": [-0.2, -1.0, -0.3],
"color": [1.0, 1.0, 1.0]
"intensity": 0.25,
"direction": [
-0.2,
-1.0,
-0.3
],
"color": [
1.0,
1.0,
1.0
]
},
"pointLights": [
{
"intensity": 7.5,
"position": [0.0, 1.0, 0.0],
"color": [1.0, 1.0, 1.0]
"position": [
0.0,
1.0,
0.0
],
"color": [
1.0,
1.0,
1.0
]
}
]
}
}

View File

@@ -26,16 +26,32 @@
"unique_name": "backpack",
"model": "backpack",
"shaderProgram": "defaultProgram",
"position": [0.0, 1.0, 0.0],
"rotation": [0.0, 0.0, 0.0],
"position": [
0.0,
1.0,
0.0
],
"rotation": [
0.0,
0.0,
0.0
],
"scale": 0.6
},
{
"unique_name": "container",
"model": "container",
"shaderProgram": "defaultProgram",
"position": [10.0, 1.0, 0.0],
"rotation": [45.0, 45.0, 45.0]
"position": [
10.0,
1.0,
0.0
],
"rotation": [
45.0,
45.0,
45.0
]
},
{
"unique_name": "ground",
@@ -48,7 +64,7 @@
"shaderProgram": "lightProgram"
}
],
"textures" : [
"textures": [
{
"unique_name": "fallback_normal",
"path": "data/res/models/tex/fallback_normal.png"
@@ -57,4 +73,4 @@
"skybox": {
"texturePath": "data/res/textures/skybox/"
}
}
}

View File

@@ -2,32 +2,56 @@
"loadingScreen": [
{
"unique_name": "background",
"position": [0.0, 0.0],
"dimensions": [1.0, 1.0],
"position": [
0.0,
0.0
],
"dimensions": [
1.0,
1.0
],
"texture": "data/res/textures/loading.png"
}
],
"mainMenuScreen": [
{
"unique_name": "play",
"position": [0.4, 0.5],
"dimensions": [0.25, 0.1],
"position": [
0.4,
0.5
],
"dimensions": [
0.25,
0.1
],
"texture": "data/res/textures/play.png",
"callbackId": 1
},
{
"unique_name": "exit",
"position": [0.4, 0.2],
"dimensions": [0.25, 0.10],
"position": [
0.4,
0.2
],
"dimensions": [
0.25,
0.10
],
"texture": "data/res/textures/exit.png",
"callbackId": 2
},
{
"unique_name": "background",
"position": [0.0, 0.0],
"dimensions": [1.0, 1.0],
"position": [
0.0,
0.0
],
"dimensions": [
1.0,
1.0
],
"texture": "data/res/textures/mainMenu.png",
"callbackId": 0
}
]
}
}

View File

@@ -37,4 +37,4 @@
"geometryPath": "data/shaders/pointShadowDepth.geom"
}
]
}
}

View File

@@ -4,7 +4,8 @@ layout(location = 0) out vec4 f_color;
in vec2 v_texCoord;
struct Material {
struct Material
{
sampler2D texture_diffuse0;
};
uniform Material u_material;

View File

@@ -18,6 +18,11 @@ add_executable(Fall-Fever
Menu.cpp
JsonParser.cpp
Helper.cpp
GLBucket.cpp
imgui/EntityWindow.cpp
imgui/GeneralInfoWindow.cpp
imgui/Handler.cpp
imgui/Window.cpp
)
target_link_libraries(

View File

@@ -9,32 +9,29 @@
#include <GLFW/glfw3.h>
#ifdef _DEBUG
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include "imgui/GeneralInfoWindow.h"
#include "imgui/Handler.h"
#endif
#include "Camera.h"
#include "Controller.h"
#include "Entity.h"
#include "EventHandler.h"
#include "Helper.h"
#include "JsonParser.h"
#include "Light.h"
#include "Menu.h"
#include "Model.h"
#include "Screen.h"
#include "ShaderProgram.h"
#include "Texture.h"
#include "VertexArray.h"
#include "Widget.h"
#include "World.h"
#include "Menu.h"
#include "Camera.h"
#include "Light.h"
#include "Window.h"
#include "Texture.h"
#include "ShaderProgram.h"
#include "EventHandler.h"
#include "World.h"
Controller::Controller()
Controller::Controller() : m_gameWindow(std::unique_ptr<Window>(new Window))
{
m_gameWindow = new Window();
m_gameEventHandler = new EventHandler(m_gameWindow->getGLFWwindow());
m_camera = new Camera(90.0f, m_gameWindow->getWindowAspectRatio());
@@ -58,27 +55,12 @@ Controller::Controller()
m_world = new World(m_shaderPrograms);
#ifdef _DEBUG
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
(void)io;
// Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(m_gameWindow->getGLFWwindow(), true);
ImGui_ImplOpenGL3_Init("#version 150");
// Setup Dear ImGui style
ImGui::StyleColorsDark();
m_imguiHandler = std::unique_ptr<Imgui::Handler>(new Imgui::Handler(m_gameWindow->getGLFWwindow()));
#endif
}
Controller::~Controller()
{
#ifdef _DEBUG
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
#endif
for (auto it = m_shaderPrograms.begin(); it != m_shaderPrograms.end(); it++) {
delete *it;
}
@@ -88,7 +70,6 @@ Controller::~Controller()
delete m_menu;
delete m_postProcessFrameBuffer;
delete m_gameEventHandler;
delete m_gameWindow;
}
void Controller::run()
@@ -103,6 +84,17 @@ void Controller::run()
m_camera->translate(glm::vec3(0.0f, 1.5f, 5.0f));
// imgui stuff
bool rotateLightSource = false, rotateEntity = false, drawShadows = false;
glm::vec3 lightColor = glm::vec3(1.f);
float intensity = 7.5f;
#ifdef _DEBUG
std::shared_ptr<Imgui::Window> imguiWindow = std::make_shared<Imgui::GeneralInfoWindow>(
this, m_world, getShaderProgramByName("postProcessingProgram"), &rotateEntity, &drawShadows, &rotateLightSource,
&lightColor, &m_exposure, &intensity);
m_imguiHandler->addImguiWindow(imguiWindow);
#endif
// This is the game loop
while (!glfwWindowShouldClose(m_gameWindow->getGLFWwindow())) {
@@ -111,7 +103,6 @@ void Controller::run()
// --- Update game ---
static bool rotateLightSource = false, rotateEntity = false;
if (rotateLightSource) {
float radius = 4.0;
glm::vec3 newPos = glm::vec3(-cos(glfwGetTime() * 0.5), 0.5f, sin(glfwGetTime() * 0.5)) * radius;
@@ -120,8 +111,7 @@ void Controller::run()
if (rotateEntity) {
m_world->getEntityById(0)->rotate(glm::vec3(0.0f, 1.0f, 0.0f), -0.2f * m_deltaTime);
}
static glm::vec3 lightColor = glm::vec3(1.f);
static float intensity = 7.5f;
m_world->updatePointLight(0, true, m_world->getEntityByName("light")->getPosition(), lightColor, intensity);
m_world->updateDirectionalLight(true, m_world->getDirectionalLight()->getDirection(), lightColor);
getShaderProgramByName("lightProgram")->bind();
@@ -131,7 +121,6 @@ void Controller::run()
// --- Render and buffer swap ---
// Calc shadows
static bool drawShadows = false;
static bool firstRun = true;
getShaderProgramByName("defaultProgram")->bind();
getShaderProgramByName("defaultProgram")->setUniform("b_drawShadows", (int)drawShadows);
@@ -161,8 +150,7 @@ void Controller::run()
m_postProcessFrameBuffer->render();
#ifdef _DEBUG
renderImGui(m_world, &lightColor, &rotateEntity, &rotateLightSource,
getShaderProgramByName("postProcessingProgram"), &intensity, &drawShadows);
m_imguiHandler->renderWindows();
#endif
}
glfwSwapBuffers(m_gameWindow->getGLFWwindow());
@@ -186,7 +174,7 @@ void Controller::run()
// Handle widget pressed event only when a screen is currently active
if (m_menu->getActiveScreen())
m_menu->handleMouseButtonActionMap(m_gameEventHandler->getMouseButtonActionMap(), m_gameWindow);
m_menu->handleMouseButtonActionMap(m_gameEventHandler->getMouseButtonActionMap(), m_gameWindow.get());
}
}
@@ -248,59 +236,3 @@ void Controller::setMaxFps(uint16_t fps)
{
m_MAX_FPS = fps;
}
#ifdef _DEBUG
void Controller::renderImGui(World *world, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource,
ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows)
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// render your GUI
ImGui::Begin("Debug Utils");
ImGui::Text("Object");
static float rotation = 0.0;
ImGui::SliderFloat("Rotation", &rotation, 0, 2 * M_PI);
static float translation[] = {0.0f, 1.0f, 0.0f};
ImGui::SliderFloat3("Position", translation, -4.0, 4.0);
static float scale = 0.6f;
ImGui::SliderFloat("Scale", &scale, 0.02, 2.0);
ImGui::Checkbox("Rotate Object", rotateEntity);
Entity *mainObject = world->getEntityById(0);
mainObject->setPosition(glm::vec3(translation[0], translation[1], translation[2]));
if (!*rotateEntity) {
mainObject->setRotation(glm::vec3(0.f, 1.0f, 0.f), rotation);
}
mainObject->setScale(scale);
// color picker
ImGui::Text("\nLight Source");
updateExposure(postProcessingProgram);
static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
ImGui::SliderFloat("Intensity", intensity, 0, 250.f);
ImGui::ColorEdit3("Color", color);
lightColor->x = color[0];
lightColor->y = color[1];
lightColor->z = color[2];
ImGui::Text("\nMiscellaneous");
ImGui::SliderFloat("Exposure", &m_exposure, 0, 5.0f);
ImGui::Checkbox("Draw Shadows", drawShadows);
ImGui::Checkbox("Rotate Lightsource", rotateLightSource);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / ImGui::GetIO().Framerate,
ImGui::GetIO().Framerate);
ImGui::End();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
#endif

View File

@@ -1,8 +1,8 @@
#pragma once
#include <glm/glm.hpp>
#include <memory>
#include <vector>
#include <glm/glm.hpp>
class ShaderProgram;
class Window;
@@ -12,6 +12,10 @@ class Camera;
class Menu;
class FrameBuffer;
namespace Imgui {
class Handler;
}
class Controller
{
public:
@@ -24,18 +28,19 @@ public:
static ShaderProgram *getShaderProgramByName(std::vector<ShaderProgram *> shaderPrograms, const std::string &name);
void updateExposure(ShaderProgram *shaderProgram);
private:
void limit_framerate();
void updateWindowDimensions();
void updateExposure(ShaderProgram *shaderProgram);
ShaderProgram *getShaderProgramByName(const std::string &name);
void renderImGui(World *world, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource,
ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows);
Window *m_gameWindow;
std::unique_ptr<Window> m_gameWindow;
EventHandler *m_gameEventHandler;
World *m_world;
@@ -45,6 +50,10 @@ private:
std::vector<ShaderProgram *> m_shaderPrograms;
#ifdef _DEBUG
std::unique_ptr<Imgui::Handler> m_imguiHandler;
#endif
FrameBuffer *m_postProcessFrameBuffer;
uint16_t m_MAX_FPS = 60;

View File

@@ -1,8 +1,8 @@
#include "Entity.h"
#include "VertexArray.h"
#include "Mesh.h"
#include "ShaderProgram.h"
#include "Model.h"
#include "ShaderProgram.h"
#include "VertexArray.h"
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
@@ -11,8 +11,7 @@ uint32_t Entity::s_idCounter = 0;
Entity::Entity(const std::string &name, Model *model, ShaderProgram *shaderProgram)
: m_uniqueName(name), m_model(model), m_shaderProgram(shaderProgram), m_id(s_idCounter++)
{
}
{}
void Entity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition)
{

View File

@@ -142,8 +142,8 @@ DepthMap::DepthMap(DepthMapType type, int RESOLUTION)
DepthMap::~DepthMap()
{
if (m_cubeMap)
delete m_cubeMap;
// if (m_cubeMap)
// delete m_cubeMap;
}
void DepthMap::bind()

16
src/GLBucket.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include "GLBucket.h"
#include <iostream>
std::unique_ptr<GLBucket> GLBucket::s_instance = std::unique_ptr<GLBucket>(new GLBucket);
GLBucket &GLBucket::instance()
{
return *s_instance.get();
}
void GLBucket::runGlCall(const std::function<void(void)> &f)
{
std::lock_guard<std::mutex> lock(m_mutex);
f();
}

19
src/GLBucket.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <functional>
#include <memory>
#include <mutex>
class GLBucket
{
public:
static GLBucket &instance();
void runGlCall(const std::function<void(void)> &f);
private:
GLBucket() = default;
std::mutex m_mutex;
static std::unique_ptr<GLBucket> s_instance;
};

View File

@@ -1,7 +1,7 @@
#pragma once
#include <glad/glad.h>
#include <chrono>
#include <glad/glad.h>
#include <stdint.h>
#include <string>

View File

@@ -8,7 +8,6 @@
#include "Widget.h"
#include <fstream>
#include <future>
#include <iostream>
JsonParser::JsonParser(const std::string &path)
@@ -33,46 +32,20 @@ JsonParser::JsonParser(const std::string &path)
JsonParser::~JsonParser()
{}
std::vector<Model *> JsonParser::getModels()
std::vector<Model::Prototype> JsonParser::getModelPrototypes() const
{
std::vector<Model *> temp_models;
const Json::Value modelsJson = m_root["models"];
struct ModelSkeleton
{
std::string model_name;
std::string model_path;
};
std::vector<ModelSkeleton> model_skeletons;
std::vector<Model::Prototype> modelPrototypes;
for (unsigned int index = 0; index < modelsJson.size(); index++) {
std::string model_name = modelsJson[index]["unique_name"].asString();
std::string model_path = modelsJson[index]["path"].asString();
ModelSkeleton model_skeleton = {model_name, model_path};
model_skeletons.push_back(model_skeleton);
std::string modelName = modelsJson[index]["unique_name"].asString();
std::string modelPath = modelsJson[index]["path"].asString();
Model::Prototype prototype{modelName, modelPath};
modelPrototypes.push_back(prototype);
}
std::vector<std::future<void>> futures;
std::mutex mutex;
auto *temp_models_ptr = &temp_models;
for (const auto &model_skeleton : model_skeletons) {
auto loadModel = [&]() {
Model *current_model = new Model(model_skeleton.model_name, model_skeleton.model_path);
if (current_model) {
std::lock_guard<std::mutex> lock(mutex);
temp_models_ptr->push_back(current_model);
std::cout << "Loaded Model \"" << model_skeleton.model_name << "\" from \"" << model_skeleton.model_path
<< "\"" << std::endl;
}
};
futures.push_back(std::async(std::launch::async, loadModel));
}
return temp_models;
return modelPrototypes;
}
std::vector<Entity *> JsonParser::getEntities(std::vector<Model *> &models, std::vector<ShaderProgram *> shaderPrograms)
@@ -275,7 +248,9 @@ std::vector<Widget *> JsonParser::getWidgetsFromScreen(const Json::Value &screen
const Json::Value currentWidgetPosition = currentWidgetJson["position"];
const Json::Value currentWidgetDimensions = currentWidgetJson["dimensions"];
std::string name = currentWidgetJson["unique_name"].asString();
Texture *currentWidgetTexture = new Texture(currentWidgetTextureJson.asString().c_str(), TextureType::Diffuse);
Texture::Prototype texturePrototype{currentWidgetTextureJson.asString(), TextureType::Diffuse};
Texture *currentWidgetTexture = new Texture(texturePrototype);
currentWidgetTexture->initializeOnGPU();
Widget *currentWidget =
new Widget(name, currentWidgetTexture, currentWidgetPosition[0].asFloat(),
currentWidgetPosition[1].asFloat(), currentWidgetDimensions[0].asFloat(),

View File

@@ -1,10 +1,11 @@
#pragma once
#include "Model.h"
#include <jsoncpp/json/json.h>
#include <string>
#include <vector>
class Model;
class Entity;
class Light;
class Screen;
@@ -19,7 +20,7 @@ public:
JsonParser(const std::string &path);
~JsonParser();
std::vector<Model *> getModels();
std::vector<Model::Prototype> getModelPrototypes() const;
std::vector<Entity *> getEntities(std::vector<Model *> &models, std::vector<ShaderProgram *> shaderPrograms);
std::vector<Light *> getLights(ShaderProgram *shaderProgram);
std::vector<Screen *> getScreens(ShaderProgram *menuProgram, FrameBuffer *framebuffer);

View File

@@ -43,7 +43,7 @@ class PointLight : public Light
{
public:
PointLight(glm::vec3 position, glm::vec3 color, float intensity, ShaderProgram *shaderProgram);
~PointLight() = default;
~PointLight() override = default;
void setPosition(glm::vec3 position);

View File

@@ -1,11 +1,11 @@
#include "Menu.h"
#include "FrameBuffer.h"
#include "Helper.h"
#include "JsonParser.h"
#include "ShaderProgram.h"
#include "FrameBuffer.h"
#include "Screen.h"
#include "Window.h"
#include "ShaderProgram.h"
#include "Widget.h"
#include "Window.h"
#include "definitions/eventActions.h"
#include <iostream>

View File

@@ -1,13 +1,25 @@
#include "Mesh.h"
#include "Texture.h"
#include "ShaderProgram.h"
#include "Texture.h"
#include "VertexArray.h"
Mesh::Mesh(std::vector<Vertex> vertices, std::vector<uint32_t> indices, std::vector<Texture *> textures)
: m_numElements(indices.size()), m_textures(textures),
m_vertexArray(static_cast<void *>(vertices.data()), static_cast<void *>(indices.data()), vertices.size(),
indices.size())
: m_numElements(indices.size()), m_textures(textures), m_preInitializationVertexData{vertices, indices}
{}
void Mesh::initializeOnGPU()
{
m_vertexArray =
new VertexArray(static_cast<void *>(m_preInitializationVertexData.vertices.data()),
static_cast<void *>(m_preInitializationVertexData.indices.data()),
m_preInitializationVertexData.vertices.size(), m_preInitializationVertexData.indices.size());
}
Mesh::~Mesh()
{
delete m_vertexArray;
}
void Mesh::draw(ShaderProgram *shaderProgram)
{
uint8_t typeNumberCount[static_cast<int>(TextureType::TEXTURE_TYPE_NUM_ITEMS)]{0};
@@ -24,9 +36,9 @@ void Mesh::draw(ShaderProgram *shaderProgram)
}
// Draw elements
m_vertexArray.bind();
m_vertexArray->bind();
glDrawElements(GL_TRIANGLES, m_numElements, GL_UNSIGNED_INT, 0);
m_vertexArray.unbind();
m_vertexArray->unbind();
// Unbind all textures
for (auto it = m_textures.begin(); it != m_textures.end(); it++) {
@@ -36,12 +48,12 @@ void Mesh::draw(ShaderProgram *shaderProgram)
void Mesh::drawWithoutTextures()
{
m_vertexArray.bind();
m_vertexArray->bind();
glDrawElements(GL_TRIANGLES, m_numElements, GL_UNSIGNED_INT, 0);
m_vertexArray.unbind();
m_vertexArray->unbind();
}
VertexArray *Mesh::getVertexArray()
{
return &m_vertexArray;
return m_vertexArray;
}

View File

@@ -1,18 +1,20 @@
#pragma once
#include "definitions/models.h"
#include "VertexArray.h"
#include <vector>
class ShaderProgram;
class Texture;
class VertexArray;
class Mesh
{
public:
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture *> textures);
~Mesh() = default;
~Mesh();
void initializeOnGPU();
void draw(ShaderProgram *shaderProgram);
void drawWithoutTextures();
@@ -20,10 +22,16 @@ public:
VertexArray *getVertexArray();
private:
void setupMesh();
struct PreInitializationVertexData
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
} m_preInitializationVertexData;
bool m_isInitialized = false;
uint32_t m_numElements;
std::vector<Texture *> m_textures;
VertexArray m_vertexArray;
VertexArray *m_vertexArray;
};

View File

@@ -1,36 +1,46 @@
#include "Model.h"
#include "GLBucket.h"
#include "Mesh.h"
#include "ShaderProgram.h"
#include "Texture.h"
#include <fstream>
#include <future>
#include <iostream>
uint32_t Model::s_idCounter = 0;
Model::Model(const std::string &modelName, const std::string &modelPath) : m_uniqueName(modelName)
Model::Model(const Prototype &prototype) : m_uniqueName(prototype.modelName), m_id(s_idCounter++)
{
m_workingPath = modelPath.substr(0, modelPath.find_last_of('/'));
m_workingPath = prototype.modelPath.substr(0, prototype.modelPath.find_last_of('/'));
loadModel(modelPath);
m_id = s_idCounter++;
loadModel(prototype.modelPath);
}
void Model::initializeOnGPU()
{
if (m_isInitialized)
return;
m_isInitialized = true;
for (auto texture : m_textures)
texture->initializeOnGPU();
for (auto mesh : m_meshes)
mesh->initializeOnGPU();
}
Model::~Model()
{
// Go through all loaded textures and delete them
for (auto it = m_loadedTextures.begin(); it != m_loadedTextures.end(); it++) {
for (auto it = m_textures.begin(); it != m_textures.end(); it++) {
delete (*it);
}
}
void Model::draw(ShaderProgram *shaderProgram)
{
if (!m_modelPrepared) {
std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl;
return;
}
// Iterate through every mesh and call the draw function
for (auto mesh : m_meshes) {
mesh->draw(shaderProgram);
@@ -39,11 +49,6 @@ void Model::draw(ShaderProgram *shaderProgram)
void Model::drawWithoutTextures()
{
if (!m_modelPrepared) {
std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl;
return;
}
// Iterate through every mesh and call the draw function
for (auto mesh : m_meshes) {
mesh->drawWithoutTextures();
@@ -83,14 +88,23 @@ void Model::loadModel(const std::string &pathToModel)
textureSources.push_back(currentTextureSource);
}
for (unsigned int i = 0; i < numTextures; i++) {
TexturePrototype texture_prototype;
std::string texturePath = m_workingPath + '/' + textureSources[i].c_str();
// Maybe write a texture loader class in future, that handles all this.
{
std::vector<std::future<void>> futures;
std::mutex mutex;
texture_prototype.texturePath = std::move(texturePath);
texture_prototype.textureType = textureTypes[i];
for (unsigned int i = 0; i < numTextures; i++) {
std::string texturePath = m_workingPath + '/' + textureSources[i].c_str();
Texture::Prototype texturePrototype{texturePath, textureTypes[i]};
auto loadModel = [=, &mutex]() {
Texture *currentTex = new Texture(texturePrototype);
m_modelTexturePrototypes.push_back(texture_prototype);
std::lock_guard<std::mutex> lock(mutex);
m_textures.push_back(currentTex);
};
futures.push_back(std::async(std::launch::async, loadModel));
}
}
// When there is no normal map bound, please use fallback texture
@@ -101,12 +115,10 @@ void Model::loadModel(const std::string &pathToModel)
}
if (!hasNormalMap) {
TexturePrototype texture_prototype;
Texture::Prototype texturePrototype{"data/res/models/tex/fallback_normal.png", TextureType::Normal};
Texture *currentTex = new Texture(texturePrototype);
texture_prototype.texturePath = "data/res/models/tex/fallback_normal.png";
texture_prototype.textureType = TextureType::Normal;
m_modelTexturePrototypes.push_back(texture_prototype);
m_textures.push_back(currentTex);
}
// Here starts the first mesh
@@ -114,9 +126,6 @@ void Model::loadModel(const std::string &pathToModel)
input.read((char *)&numMeshes, sizeof(uint32_t));
for (unsigned int j = 0; j < numMeshes; j++) {
MeshPrototype mesh_prototype;
uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds;
input.read((char *)&numMeshVertices, sizeof(uint32_t));
@@ -131,52 +140,35 @@ void Model::loadModel(const std::string &pathToModel)
std::vector<Vertex> meshVertices;
meshVertices.resize(numMeshVertices);
input.read((char *)meshVertices.data(), vertexBlockSize);
mesh_prototype.meshVertices = std::move(meshVertices);
std::vector<uint32_t> meshIndices;
meshIndices.resize(numMeshIndices);
input.read((char *)meshIndices.data(), indexBlockSize);
mesh_prototype.meshIndices = std::move(meshIndices);
std::vector<uint32_t> meshTextureIds;
std::vector<Texture *> meshTextures;
for (unsigned int i = 0; i < numMeshTextureIds; i++) {
uint32_t currentTextureId;
input.read((char *)&currentTextureId, sizeof(uint32_t));
mesh_prototype.textureIds.push_back(currentTextureId);
meshTextureIds.push_back(currentTextureId);
}
if (!hasNormalMap) {
// This will be the last texture
mesh_prototype.textureIds.push_back(numTextures);
meshTextureIds.push_back(numTextures);
}
m_modelMeshPrototypes.push_back(std::move(mesh_prototype));
for (auto textureId : meshTextureIds) {
meshTextures.push_back(m_textures[textureId]);
}
m_meshes.push_back(new Mesh(std::move(meshVertices), std::move(meshIndices), std::move(meshTextures)));
}
input.close();
}
void Model::prepareModel()
{
m_modelPrepared = true;
// Create textures on GPU
for (auto &it : m_modelTexturePrototypes) {
Texture *newTex = new Texture(it.texturePath.c_str(), it.textureType);
m_loadedTextures.push_back(newTex);
}
// Create meshes on GPU
for (const auto &it : m_modelMeshPrototypes) {
std::vector<Texture *> meshTextures;
for (const auto it2 : it.textureIds) {
meshTextures.push_back(m_loadedTextures[it2]);
}
Mesh *currentMesh = new Mesh(std::move(it.meshVertices), std::move(it.meshIndices), meshTextures);
m_meshes.push_back(currentMesh);
}
}
Mesh *Model::getMesh(unsigned int index)
{
return m_meshes[index];

View File

@@ -9,12 +9,6 @@ class ShaderProgram;
class Mesh;
class Texture;
struct TexturePrototype
{
TextureType textureType;
std::string texturePath;
};
struct MeshPrototype
{
std::vector<uint32_t> textureIds;
@@ -25,10 +19,16 @@ struct MeshPrototype
class Model
{
public:
Model(const std::string &modelName, const std::string &pathToModel);
struct Prototype
{
std::string modelName;
std::string modelPath;
};
Model(const Prototype &prototype);
~Model();
void prepareModel();
void initializeOnGPU();
void draw(ShaderProgram *shaderProgram);
void drawWithoutTextures();
@@ -39,16 +39,13 @@ public:
private:
void loadModel(const std::string &pathToModel);
std::vector<Mesh *> m_meshes;
std::vector<Texture *> m_loadedTextures;
bool m_isInitialized = false;
std::vector<TexturePrototype> m_modelTexturePrototypes;
std::vector<MeshPrototype> m_modelMeshPrototypes;
std::vector<Mesh *> m_meshes;
std::vector<Texture *> m_textures;
std::string m_workingPath;
bool m_modelPrepared = false;
static uint32_t s_idCounter;
uint32_t m_id;
std::string m_uniqueName;

View File

@@ -1,10 +1,10 @@
#include "Screen.h"
#include "Menu.h"
#include "Widget.h"
#include "FrameBuffer.h"
#include "Helper.h"
#include "Menu.h"
#include "ShaderProgram.h"
#include "Texture.h"
#include "Helper.h"
#include "Widget.h"
uint32_t Screen::s_idCounter = 0;

View File

@@ -1,8 +1,8 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <vector>
class Menu;
class Widget;

View File

@@ -2,13 +2,29 @@
#include "ShaderProgram.h"
#include <iostream>
#include <stb/stb_image.h>
Texture::Texture(const std::string &texturePath, TextureType textureType)
: m_texturePath(texturePath), m_textureType(textureType)
Texture::Texture(const Prototype &prototype)
: m_texturePath(prototype.texturePath), m_textureType(prototype.textureType)
{
stbi_set_flip_vertically_on_load(1);
auto *textureBuffer = stbi_load(texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0);
m_textureBuffer = stbi_load(m_texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0);
if (!m_textureBuffer) {
std::cout << "[Warning] Texture " << m_texturePath << " not found!" << std::endl;
return;
}
}
Texture::~Texture()
{
glDeleteTextures(1, &m_textureId);
}
void Texture::initializeOnGPU()
{
if (m_isInitialized)
return;
m_isInitialized = true;
GLenum internalFormat;
GLenum dataFormat;
@@ -16,10 +32,10 @@ Texture::Texture(const std::string &texturePath, TextureType textureType)
internalFormat = GL_RED;
dataFormat = GL_RED;
} else if (m_numComponents == 3) {
internalFormat = (textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8;
internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8;
dataFormat = GL_RGB;
} else if (m_numComponents == 4) {
internalFormat = (textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
dataFormat = GL_RGBA;
}
@@ -34,22 +50,13 @@ Texture::Texture(const std::string &texturePath, TextureType textureType)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (!textureBuffer) {
std::cout << "[Warning] Texture " << texturePath << " not found!" << std::endl;
return;
}
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_textureWidth, m_textureHeight, 0, dataFormat, GL_UNSIGNED_BYTE,
textureBuffer);
m_textureBuffer);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(textureBuffer);
glBindTexture(GL_TEXTURE_2D, 0);
}
Texture::~Texture()
{
glDeleteTextures(1, &m_textureId);
stbi_image_free(m_textureBuffer);
}
void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum)
@@ -176,7 +183,7 @@ CubeMap::CubeMap(int RESOLUTION) : m_textureWidth(RESOLUTION), m_textureHeight(R
CubeMap::~CubeMap()
{
glDeleteTextures(1, &m_textureId);
// glDeleteTextures(1, &m_textureId);
}
void CubeMap::bind(ShaderProgram *shaderProgram)

View File

@@ -4,6 +4,7 @@
#include <cstdint>
#include <glad/glad.h>
#include <stb/stb_image.h>
#include <string>
#include <vector>
@@ -24,9 +25,17 @@ enum cubeMapFaces
class Texture
{
public:
Texture(const std::string &texturePath, TextureType textureType);
struct Prototype
{
std::string texturePath;
TextureType textureType;
};
Texture(const Prototype &prototype);
~Texture();
void initializeOnGPU();
void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum);
void unbind();
@@ -35,8 +44,12 @@ public:
GLuint getTextureId();
private:
bool m_isInitialized = false;
std::string m_texturePath;
stbi_uc *m_textureBuffer;
int32_t m_textureWidth;
int32_t m_textureHeight;
int32_t m_numComponents;

View File

@@ -1,4 +1,5 @@
#include "VertexArray.h"
#include "GLBucket.h"
#include "definitions/models.h"
#include <cstddef>

View File

@@ -2,8 +2,8 @@
#include "Menu.h"
#include "Mesh.h"
#include "ShaderProgram.h"
#include "Window.h"
#include "VertexArray.h"
#include "Window.h"
#include <GLFW/glfw3.h>
@@ -34,6 +34,7 @@ Widget::Widget(std::string &name, Texture *texture, float p_x, float p_y, float
m_widgetVertices = VertexArray::createVertices(widgetVerticesData, 12, widgetTextureCoordinates);
m_widgetIndices.assign(widgetIndicesData, widgetIndicesData + 6);
m_widgetMesh = new Mesh(m_widgetVertices, m_widgetIndices, m_widgetTextures);
m_widgetMesh->initializeOnGPU();
}
Widget::~Widget()

View File

@@ -3,7 +3,6 @@
#include "ShaderProgram.h"
#include "definitions/window.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

View File

@@ -2,6 +2,8 @@
#include "definitions/eventActions.h"
#include <memory>
class GLFWwindow;
class Window

View File

@@ -1,14 +1,16 @@
#include "World.h"
#include "Entity.h"
#include "Controller.h"
#include "Model.h"
#include "Light.h"
#include "JsonParser.h"
#include "Camera.h"
#include "Texture.h"
#include "Controller.h"
#include "Entity.h"
#include "JsonParser.h"
#include "Light.h"
#include "Model.h"
#include "ShaderProgram.h"
#include "Texture.h"
#include <future>
#include <iostream>
#include <thread>
World::World(std::vector<ShaderProgram *> shaderPrograms)
: m_shaderProgram(Controller::getShaderProgramByName(shaderPrograms, "defaultProgram")),
@@ -26,12 +28,31 @@ World::World(std::vector<ShaderProgram *> shaderPrograms)
m_shaderProgram->unbind();
JsonParser modelParser("data/models.json");
m_models = modelParser.getModels();
std::vector<Model::Prototype> modelPrototypes = modelParser.getModelPrototypes();
for (const auto &it : m_models) {
it->prepareModel();
{
std::vector<std::future<void>> futures;
std::mutex mutex;
for (auto &prototype : modelPrototypes) {
auto loadModel = [=, &mutex]() {
Model *current_model = new Model(prototype);
std::cout << "Loaded Model \"" << prototype.modelName << "\" from \"" << prototype.modelPath << "\""
<< std::endl;
std::lock_guard<std::mutex> lock(mutex);
m_models.push_back(current_model);
};
futures.push_back(std::async(std::launch::async, loadModel));
}
}
for (auto &model : m_models)
model->initializeOnGPU();
m_entities = modelParser.getEntities(m_models, shaderPrograms);
m_skybox = modelParser.getSkybox(getModelByName("cube"),
Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram"));

View File

@@ -5,8 +5,8 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include <string>
#include <vector>
class Camera;
class Entity;

View File

0
src/imgui/EntityWindow.h Normal file
View File

View File

@@ -0,0 +1,58 @@
#include "GeneralInfoWindow.h"
#include "../Controller.h"
#include "../Entity.h"
#include "../ShaderProgram.h"
#include "../World.h"
#include <imgui.h>
#include <math.h>
Imgui::GeneralInfoWindow::GeneralInfoWindow(Controller *controller, World *world, ShaderProgram *postProcessingProgram,
bool *rotateEntity, bool *drawShadows, bool *rotateLightSource,
glm::vec3 *lightColor, float *exposure, float *intensity)
: m_controller(controller), m_world(world), m_postProcessingProgram(postProcessingProgram),
m_rotateEntity(rotateEntity), m_drawShadows(drawShadows), m_rotateLightSource(rotateLightSource),
m_lightColor(lightColor), m_exposure(exposure), m_intensity(intensity)
{}
void Imgui::GeneralInfoWindow::addWidgets()
{
ImGui::Begin("Debug Utils");
ImGui::Text("Object");
ImGui::SliderFloat("Rotation", &m_rotation, 0, 2 * M_PI);
ImGui::SliderFloat3("Position", m_translation, -4.0, 4.0);
ImGui::SliderFloat("Scale", &m_scale, 0.02, 2.0);
ImGui::Checkbox("Rotate Object", m_rotateEntity);
Entity *mainObject = m_world->getEntityById(0);
mainObject->setPosition(glm::vec3(m_translation[0], m_translation[1], m_translation[2]));
if (!*m_rotateEntity) {
mainObject->setRotation(glm::vec3(0.f, 1.0f, 0.f), m_rotation);
}
mainObject->setScale(m_scale);
// color picker
ImGui::Text("\nLight Source");
m_controller->updateExposure(m_postProcessingProgram);
ImGui::SliderFloat("Intensity", m_intensity, 0, 250.f);
ImGui::ColorEdit3("Color", m_color);
m_lightColor->x = m_color[0];
m_lightColor->y = m_color[1];
m_lightColor->z = m_color[2];
ImGui::Text("\nMiscellaneous");
ImGui::SliderFloat("Exposure", m_exposure, 0, 5.0f);
ImGui::Checkbox("Draw Shadows", m_drawShadows);
ImGui::Checkbox("Rotate Lightsource", m_rotateLightSource);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / ImGui::GetIO().Framerate,
ImGui::GetIO().Framerate);
ImGui::End();
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "Window.h"
#include <glm/glm.hpp>
class World;
class ShaderProgram;
class Controller;
namespace Imgui {
class GeneralInfoWindow : public Window
{
public:
GeneralInfoWindow(Controller *controller, World *world, ShaderProgram *postProcessingProgram, bool *rotateEntity,
bool *drawShadows, bool *rotateLightSource, glm::vec3 *lightColor, float *exposure,
float *intensity);
private:
void addWidgets() override;
Controller *m_controller;
World *m_world;
ShaderProgram *m_postProcessingProgram;
bool *m_rotateEntity;
bool *m_drawShadows;
bool *m_rotateLightSource;
float m_rotation = 0.0f;
float m_translation[3] = {0.0f, 1.0f, 0.0f};
float m_scale = 0.6f;
float m_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
glm::vec3 *m_lightColor;
float *m_exposure;
float *m_intensity;
};
}; // namespace Imgui

42
src/imgui/Handler.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "Handler.h"
#include "Window.h"
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
Imgui::Handler::Handler(GLFWwindow *window) : m_GLFWwindow(window)
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
// io.IniFilename = nullptr;
// Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(m_GLFWwindow, true);
ImGui_ImplOpenGL3_Init("#version 150");
// Setup Dear ImGui style
ImGui::StyleColorsDark();
}
Imgui::Handler::~Handler()
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
}
void Imgui::Handler::addImguiWindow(std::shared_ptr<Window> window)
{
m_windows.push_back(window);
}
void Imgui::Handler::renderWindows()
{
for (auto window : m_windows)
window->render();
}

26
src/imgui/Handler.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <vector>
class GLFWwindow;
namespace Imgui {
class Window;
class Handler
{
public:
Handler(GLFWwindow *window);
~Handler();
void addImguiWindow(std::shared_ptr<Window> window);
void renderWindows();
private:
std::vector<std::shared_ptr<Window>> m_windows;
GLFWwindow *m_GLFWwindow;
};
} // namespace Imgui

20
src/imgui/Window.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include "Window.h"
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
Imgui::Window::Window()
{}
void Imgui::Window::render()
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
addWidgets();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}

15
src/imgui/Window.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
namespace Imgui {
class Window
{
public:
Window();
void render();
protected:
virtual void addWidgets() = 0;
};
} // namespace Imgui