Refactor object system to ECS
This commit is contained in:
parent
d91c7d7221
commit
5b035874ab
33 changed files with 709 additions and 371 deletions
|
@ -8,7 +8,7 @@ add_subdirectory(3rdparty)
|
||||||
include(cmake/BuildShaders.cmake)
|
include(cmake/BuildShaders.cmake)
|
||||||
include(cmake/CopyData.cmake)
|
include(cmake/CopyData.cmake)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
|
@ -56,7 +56,8 @@ set(GRAPH_SRC
|
||||||
src/stringutils.cpp
|
src/stringutils.cpp
|
||||||
src/animationsystem.cpp
|
src/animationsystem.cpp
|
||||||
src/worldmanager.cpp
|
src/worldmanager.cpp
|
||||||
src/assetmanager.cpp)
|
src/assetmanager.cpp
|
||||||
|
src/entityparser.cpp)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
set(GRAPH_SRC
|
set(GRAPH_SRC
|
||||||
|
@ -69,8 +70,7 @@ add_executable(Graph
|
||||||
|
|
||||||
target_compile_options(Graph
|
target_compile_options(Graph
|
||||||
PUBLIC
|
PUBLIC
|
||||||
-fno-exceptions
|
-fno-exceptions)
|
||||||
-fno-rtti)
|
|
||||||
target_link_libraries(Graph
|
target_link_libraries(Graph
|
||||||
PUBLIC
|
PUBLIC
|
||||||
SDL2::SDL2
|
SDL2::SDL2
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
{
|
{
|
||||||
"meshes": [
|
"entities": [
|
||||||
|
|
||||||
],
|
|
||||||
"lights": [
|
|
||||||
{
|
{
|
||||||
"position": "66,56,25",
|
"name": "sun",
|
||||||
"type": 1
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "66,56,25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Light",
|
||||||
|
"kind": 1,
|
||||||
|
"color": "1,1,1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": {
|
||||||
|
"color": "0.9,0.9,0.9"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,57 +4,96 @@
|
||||||
"world": "test.world",
|
"world": "test.world",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"end": 5,
|
"end": 5,
|
||||||
"meshes": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"name": "suzanne",
|
"name": "suzanne",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Mesh",
|
||||||
"path": "suzanne.obj",
|
"path": "suzanne.obj",
|
||||||
"material": "test.material"
|
"material": "test.material"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "0,0,0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "suzanne2",
|
"name": "suzanne2",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Mesh",
|
||||||
"path": "suzanne.obj",
|
"path": "suzanne.obj",
|
||||||
"material": "test.material"
|
"material": "test.material"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "0,0,0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Light",
|
||||||
|
"color": "1,0,0",
|
||||||
|
"kind": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "camera",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "0,0,0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Camera",
|
||||||
|
"fov": 75
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"animations": [
|
"animations": [
|
||||||
{
|
{
|
||||||
"target": "suzanne",
|
"target": "suzanne",
|
||||||
|
"targetComponent": "Transform",
|
||||||
"property": "position",
|
"property": "position",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
"time": 0,
|
"time": 0,
|
||||||
"value": "0,0,0"
|
"value": "0,2,0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": 1,
|
"time": 1,
|
||||||
"value": "0,2,-3.5"
|
"value": "0,4,-3.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": 3,
|
"time": 3,
|
||||||
"value": "0,0.5,-4"
|
"value": "0,2.5,-4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": 5,
|
"time": 5,
|
||||||
"value": "0,0,-6"
|
"value": "0,2,-6"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "suzanne2",
|
"target": "suzanne2",
|
||||||
|
"targetComponent": "Transform",
|
||||||
"property": "position",
|
"property": "position",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
"time": 0,
|
"time": 0,
|
||||||
"value": "5,0,-2"
|
"value": "5,2,-2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": 2,
|
"time": 2,
|
||||||
"value": "-5,0,-2"
|
"value": "-5,2,-2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "camera",
|
"target": "camera",
|
||||||
|
"targetComponent": "Transform",
|
||||||
"property": "position",
|
"property": "position",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
|
@ -73,30 +112,39 @@
|
||||||
"world": "empty.world",
|
"world": "empty.world",
|
||||||
"start": 5,
|
"start": 5,
|
||||||
"end": 10,
|
"end": 10,
|
||||||
"meshes": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"name": "suzanne",
|
"name": "suzanne",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Mesh",
|
||||||
"path": "suzanne.obj",
|
"path": "suzanne.obj",
|
||||||
"material": "test.material"
|
"material": "test.material"
|
||||||
}
|
|
||||||
],
|
|
||||||
"animations": [
|
|
||||||
{
|
|
||||||
"target": "suzanne",
|
|
||||||
"property": "position",
|
|
||||||
"keyframes": [
|
|
||||||
{
|
|
||||||
"time": 5,
|
|
||||||
"value": "0,5,0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": 10,
|
"type": "Transform",
|
||||||
"value": "0,5,0"
|
"position": "0,5,0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "camera",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "0,0,0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Camera",
|
||||||
|
"fov": 75
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"animations": [
|
||||||
{
|
{
|
||||||
"target": "camera",
|
"target": "camera",
|
||||||
|
"targetComponent": "Transform",
|
||||||
"property": "position",
|
"property": "position",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
|
@ -111,6 +159,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "camera",
|
"target": "camera",
|
||||||
|
"targetComponent": "Camera",
|
||||||
"property": "fov",
|
"property": "fov",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
|
@ -125,6 +174,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "camera",
|
"target": "camera",
|
||||||
|
"targetComponent": "Camera",
|
||||||
"property": "target",
|
"property": "target",
|
||||||
"keyframes": [
|
"keyframes": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,35 @@
|
||||||
{
|
{
|
||||||
"meshes": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"position": "0,0,0",
|
"name": "suzanne",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "0,0,0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Mesh",
|
||||||
"path": "scene.obj",
|
"path": "scene.obj",
|
||||||
"material": "test.material"
|
"material": "test.material"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"lights": [
|
},
|
||||||
{
|
{
|
||||||
"position": "66,56,25",
|
"name": "sun",
|
||||||
"type": 1
|
"components": [
|
||||||
|
{
|
||||||
|
"type": "Transform",
|
||||||
|
"position": "66,56,25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Light",
|
||||||
|
"kind": 1,
|
||||||
|
"color": "1,1,1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"environment": {
|
||||||
|
"color": "0.1,0.1,0.8"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct Mesh;
|
struct MeshAsset;
|
||||||
struct Material;
|
struct MaterialAsset;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
|
||||||
class AssetManager {
|
class AssetManager {
|
||||||
|
@ -12,8 +12,8 @@ public:
|
||||||
renderer = r;
|
renderer = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh* loadMesh(const std::string& path);
|
MeshAsset* loadMesh(const std::string& path);
|
||||||
Material* loadMaterial(const std::string& path);
|
MaterialAsset* loadMaterial(const std::string& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer* renderer = nullptr;
|
Renderer* renderer = nullptr;
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
class Camera {
|
|
||||||
public:
|
|
||||||
glm::vec3 position = glm::vec3(0), target = glm::vec3(0);
|
|
||||||
float fov = 75.0f;
|
|
||||||
float focusDistance = 0.0f;
|
|
||||||
float aperture = 0.0f;
|
|
||||||
float near = 0.1f, far = 100.0f;
|
|
||||||
};
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
class Mesh;
|
#include "ecs.h"
|
||||||
|
|
||||||
struct Keyframe {
|
struct Keyframe {
|
||||||
int time = 0;
|
int time = 0;
|
||||||
|
@ -18,15 +19,15 @@ enum class AnimationProperty {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Animation {
|
struct Animation {
|
||||||
Mesh* target = nullptr;
|
EntityID target;
|
||||||
std::string targetName;
|
std::string targetName, targetComponent;
|
||||||
AnimationProperty property = AnimationProperty::Position;
|
AnimationProperty property = AnimationProperty::Position;
|
||||||
|
|
||||||
std::vector<Keyframe> keyframes;
|
std::vector<Keyframe> keyframes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CinematicMesh {
|
struct CinematicEntity {
|
||||||
std::string name, modelPath, materialPath;
|
nlohmann::json data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shot {
|
struct Shot {
|
||||||
|
@ -35,8 +36,8 @@ struct Shot {
|
||||||
|
|
||||||
std::string world;
|
std::string world;
|
||||||
|
|
||||||
std::vector<CinematicMesh> meshes;
|
std::vector<CinematicEntity> entities;
|
||||||
std::vector<Mesh*> loadedMeshes;
|
std::vector<EntityID> loadedEntities;
|
||||||
std::vector<Animation*> animations;
|
std::vector<Animation*> animations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
struct RenderTarget;
|
struct RenderTarget;
|
||||||
class Camera;
|
struct CameraComponent;
|
||||||
|
|
||||||
class DoFPass {
|
class DoFPass {
|
||||||
public:
|
public:
|
||||||
DoFPass(Renderer& renderer);
|
DoFPass(Renderer& renderer);
|
||||||
~DoFPass();
|
~DoFPass();
|
||||||
|
|
||||||
void render(VkCommandBuffer commandBuffer, Camera& camera, RenderTarget* target);
|
void render(VkCommandBuffer commandBuffer, CameraComponent& camera, RenderTarget* target);
|
||||||
|
|
||||||
void createDescriptorSet(RenderTarget* target);
|
void createDescriptorSet(RenderTarget* target);
|
||||||
|
|
||||||
|
|
136
include/ecs.h
Normal file
136
include/ecs.h
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
#include <array>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
struct InfoComponent {
|
||||||
|
std::string name, tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransformComponent {
|
||||||
|
glm::vec3 position = glm::vec3(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshAsset;
|
||||||
|
struct MaterialAsset;
|
||||||
|
|
||||||
|
struct MeshComponent {
|
||||||
|
MeshAsset* mesh = nullptr;
|
||||||
|
MaterialAsset* material = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LightType {
|
||||||
|
Point,
|
||||||
|
Directional
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LightComponent {
|
||||||
|
LightType type = LightType::Point;
|
||||||
|
glm::vec3 color = glm::vec3(1);
|
||||||
|
|
||||||
|
glm::mat4 matrix = glm::mat4(1.0f);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CameraComponent {
|
||||||
|
float fov = 75.0f, near = 0.1f, far = 100.0f;
|
||||||
|
float focusDistance = 0.0f;
|
||||||
|
float aperture = 0.0f;
|
||||||
|
glm::vec3 target = glm::vec3(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
using EntityID = uint64_t;
|
||||||
|
|
||||||
|
struct World;
|
||||||
|
|
||||||
|
namespace ECS {
|
||||||
|
// components
|
||||||
|
inline std::map<EntityID, InfoComponent*> infos;
|
||||||
|
inline std::map<EntityID, TransformComponent*> transforms;
|
||||||
|
inline std::map<EntityID, MeshComponent*> meshes;
|
||||||
|
inline std::map<EntityID, LightComponent*> lights;
|
||||||
|
inline std::map<EntityID, CameraComponent*> cameras;
|
||||||
|
|
||||||
|
inline std::map<EntityID, ::World*> worlds;
|
||||||
|
inline EntityID lastID = 1;
|
||||||
|
|
||||||
|
static inline EntityID createEntity(World* world) {
|
||||||
|
EntityID newID = lastID++;
|
||||||
|
worlds[newID] = world;
|
||||||
|
|
||||||
|
return newID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void destroyEntity(const EntityID id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline T* addComponent(const EntityID id) {
|
||||||
|
T* t = new T();
|
||||||
|
if constexpr(std::is_same<T, InfoComponent>::value) {
|
||||||
|
infos[id] = t;
|
||||||
|
} else if constexpr(std::is_same<T, TransformComponent>::value) {
|
||||||
|
transforms[id] = t;
|
||||||
|
} else if constexpr(std::is_same<T, MeshComponent>::value) {
|
||||||
|
meshes[id] = t;
|
||||||
|
} else if constexpr(std::is_same<T, LightComponent>::value) {
|
||||||
|
lights[id] = t;
|
||||||
|
} else if constexpr(std::is_same<T, CameraComponent>::value) {
|
||||||
|
cameras[id] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline T* getComponent(const EntityID id) {
|
||||||
|
if constexpr(std::is_same<T, InfoComponent>::value) {
|
||||||
|
return infos[id];
|
||||||
|
} else if constexpr(std::is_same<T, TransformComponent>::value) {
|
||||||
|
return transforms[id];
|
||||||
|
} else if constexpr(std::is_same<T, MeshComponent>::value) {
|
||||||
|
return meshes[id];
|
||||||
|
} else if constexpr(std::is_same<T, LightComponent>::value) {
|
||||||
|
return lights[id];
|
||||||
|
} else if constexpr(std::is_same<T, CameraComponent>::value) {
|
||||||
|
return cameras[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline auto getWorldComponents(World* world) {
|
||||||
|
std::vector<EntityID> entities;
|
||||||
|
for (auto it = worlds.begin(); it != worlds.end(); ++it) {
|
||||||
|
if(it->second == world) {
|
||||||
|
entities.push_back(it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::tuple<EntityID, T*>> components;
|
||||||
|
for(auto ent : entities) {
|
||||||
|
T* t = getComponent<T>(ent);
|
||||||
|
if(t != nullptr)
|
||||||
|
components.push_back(std::tuple(ent, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::vector<EntityID> getWorldEntities(World* world) {
|
||||||
|
std::vector<EntityID> entities;
|
||||||
|
for (auto it = worlds.begin(); it != worlds.end(); ++it) {
|
||||||
|
if(it->second == world)
|
||||||
|
entities.push_back(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static inline void removeComponent(const EntityID id) {
|
||||||
|
delete transforms[id];
|
||||||
|
}
|
||||||
|
};
|
9
include/entityparser.h
Normal file
9
include/entityparser.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
|
||||||
|
struct World;
|
||||||
|
|
||||||
|
EntityID parseEntity(const nlohmann::json& json, World* world);
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
enum class LightType {
|
|
||||||
Point,
|
|
||||||
Directional
|
|
||||||
};
|
|
||||||
|
|
||||||
class Light {
|
|
||||||
public:
|
|
||||||
LightType type = LightType::Point;
|
|
||||||
glm::vec3 position = glm::vec3(0);
|
|
||||||
glm::vec3 color = glm::vec3(1);
|
|
||||||
|
|
||||||
glm::mat4 matrix = glm::mat4(1.0f);
|
|
||||||
};
|
|
|
@ -3,8 +3,7 @@
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class Material {
|
struct MaterialAsset {
|
||||||
public:
|
|
||||||
std::string albedoTexturePath;
|
std::string albedoTexturePath;
|
||||||
|
|
||||||
VkImage albedoImage = nullptr;
|
VkImage albedoImage = nullptr;
|
||||||
|
|
|
@ -6,20 +6,12 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
class Material;
|
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
glm::vec3 position, normal;
|
glm::vec3 position, normal;
|
||||||
glm::vec2 uv;
|
glm::vec2 uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mesh {
|
struct MeshAsset {
|
||||||
public:
|
|
||||||
std::string name, tag;
|
|
||||||
glm::vec3 position;
|
|
||||||
|
|
||||||
Material* material = nullptr;
|
|
||||||
|
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
std::vector<uint32_t> indices;
|
std::vector<uint32_t> indices;
|
||||||
|
|
||||||
|
|
30
include/rendercollection.h
Normal file
30
include/rendercollection.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct TransformComponent;
|
||||||
|
struct MeshComponent;
|
||||||
|
struct LightComponent;
|
||||||
|
struct CameraComponent;
|
||||||
|
|
||||||
|
struct RenderLight {
|
||||||
|
TransformComponent* transform = nullptr;
|
||||||
|
LightComponent* light = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderMesh {
|
||||||
|
TransformComponent* transform = nullptr;
|
||||||
|
MeshComponent* mesh = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderCamera {
|
||||||
|
TransformComponent* transform = nullptr;
|
||||||
|
CameraComponent* camera = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderCollection {
|
||||||
|
std::vector<RenderLight> lights;
|
||||||
|
std::vector<RenderMesh> meshes;
|
||||||
|
|
||||||
|
RenderCamera camera;
|
||||||
|
};
|
|
@ -74,16 +74,16 @@ struct GraphicsConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
class World;
|
class World;
|
||||||
class Mesh;
|
class MeshAsset;
|
||||||
class Camera;
|
class Camera;
|
||||||
class Material;
|
class MaterialAsset;
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
Renderer(GraphicsConfig config);
|
Renderer(GraphicsConfig config);
|
||||||
~Renderer();
|
~Renderer();
|
||||||
|
|
||||||
void render(World& world, Camera& camera, RenderTarget* target);
|
void render(World& world, RenderTarget* target);
|
||||||
|
|
||||||
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldTarget = nullptr);
|
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldTarget = nullptr);
|
||||||
void destroyRenderTarget(RenderTarget* target);
|
void destroyRenderTarget(RenderTarget* target);
|
||||||
|
@ -96,11 +96,11 @@ public:
|
||||||
|
|
||||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||||
|
|
||||||
void fillMeshBuffers(Mesh* mesh);
|
void fillMeshBuffers(MeshAsset* mesh);
|
||||||
void destroyMeshBuffers(Mesh* mesh);
|
void destroyMeshBuffers(MeshAsset* mesh);
|
||||||
|
|
||||||
void fillMaterialBuffers(Material* material);
|
void fillMaterialBuffers(MaterialAsset* material);
|
||||||
void destroyMaterialBuffers(Material* material);
|
void destroyMaterialBuffers(MaterialAsset* material);
|
||||||
|
|
||||||
GraphicsConfig getConfig() const {
|
GraphicsConfig getConfig() const {
|
||||||
return config_;
|
return config_;
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class World;
|
class World;
|
||||||
|
struct RenderCollection;
|
||||||
|
|
||||||
class ShadowPass {
|
class ShadowPass {
|
||||||
public:
|
public:
|
||||||
ShadowPass(Renderer& renderer);
|
ShadowPass(Renderer& renderer);
|
||||||
~ShadowPass();
|
~ShadowPass();
|
||||||
|
|
||||||
void render(VkCommandBuffer commandBuffer, World& world);
|
void render(VkCommandBuffer commandBuffer, RenderCollection& collection);
|
||||||
|
|
||||||
VkImageView getImageView() const {
|
VkImageView getImageView() const {
|
||||||
return shadowImageView_;
|
return shadowImageView_;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ public:
|
||||||
SkyPass(Renderer& renderer);
|
SkyPass(Renderer& renderer);
|
||||||
~SkyPass();
|
~SkyPass();
|
||||||
|
|
||||||
void render(VkCommandBuffer commandBuffer);
|
void render(glm::vec3 color, VkCommandBuffer commandBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "camera.h"
|
struct World {
|
||||||
|
glm::vec3 color;
|
||||||
class Mesh;
|
|
||||||
class Light;
|
|
||||||
|
|
||||||
class World {
|
|
||||||
public:
|
|
||||||
std::vector<Mesh*> meshes;
|
|
||||||
std::vector<Light*> lights;
|
|
||||||
|
|
||||||
Camera camera;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,10 @@ public:
|
||||||
return currentWorld;
|
return currentWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
World* getWorld(const std::string& path) {
|
||||||
|
return loadedWorlds[path];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, World*> loadedWorlds;
|
std::map<std::string, World*> loadedWorlds;
|
||||||
World* currentWorld = nullptr;
|
World* currentWorld = nullptr;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "rendercollection.h"
|
||||||
|
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class World;
|
class World;
|
||||||
struct RenderTarget;
|
struct RenderTarget;
|
||||||
|
@ -12,7 +14,7 @@ public:
|
||||||
WorldPass(Renderer& renderer);
|
WorldPass(Renderer& renderer);
|
||||||
~WorldPass();
|
~WorldPass();
|
||||||
|
|
||||||
void render(VkCommandBuffer commandBuffer, World& world, Camera& camera, RenderTarget* target);
|
void render(VkCommandBuffer commandBuffer, RenderCollection& collection, RenderTarget* target);
|
||||||
|
|
||||||
VkRenderPass getRenderPass() const {
|
VkRenderPass getRenderPass() const {
|
||||||
return renderPass_;
|
return renderPass_;
|
||||||
|
@ -22,7 +24,7 @@ private:
|
||||||
void createRenderPass();
|
void createRenderPass();
|
||||||
void createDescriptorSetLayout();
|
void createDescriptorSetLayout();
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
void createUniformBuffer();
|
void createUniformBuffers();
|
||||||
void createDescriptorSet();
|
void createDescriptorSet();
|
||||||
|
|
||||||
VkRenderPass renderPass_ = nullptr;
|
VkRenderPass renderPass_ = nullptr;
|
||||||
|
@ -32,6 +34,9 @@ private:
|
||||||
VkPipelineLayout pipelineLayout_ = nullptr;
|
VkPipelineLayout pipelineLayout_ = nullptr;
|
||||||
VkPipeline pipeline_ = nullptr;
|
VkPipeline pipeline_ = nullptr;
|
||||||
|
|
||||||
|
VkDeviceMemory sceneMemory_ = nullptr;
|
||||||
|
VkBuffer sceneBuffer_ = nullptr;
|
||||||
|
|
||||||
VkDeviceMemory lightMemory_ = nullptr;
|
VkDeviceMemory lightMemory_ = nullptr;
|
||||||
VkBuffer lightBuffer_ = nullptr;
|
VkBuffer lightBuffer_ = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,14 @@ layout(location = 3) in vec2 inUV;
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
struct Light {
|
struct Light {
|
||||||
vec4 position;
|
vec4 position, color;
|
||||||
vec3 color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform Lights {
|
layout(set = 0, binding = 1) uniform Lights {
|
||||||
Light lights[32];
|
Light lights[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform sampler2D shadowSampler;
|
layout(set = 0, binding = 2) uniform sampler2D shadowSampler;
|
||||||
layout(set = 1, binding = 0) uniform sampler2D albedoSampler;
|
layout(set = 1, binding = 0) uniform sampler2D albedoSampler;
|
||||||
|
|
||||||
layout(constant_id = 0) const int shadowFilterPCF = 1;
|
layout(constant_id = 0) const int shadowFilterPCF = 1;
|
||||||
|
@ -54,7 +53,7 @@ float filterPCF(vec4 sc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 diffuse = vec3(0);
|
vec3 diffuse = vec3(0.0);
|
||||||
for(int i = 0; i < 32; i++) {
|
for(int i = 0; i < 32; i++) {
|
||||||
vec3 lightDir = vec3(0);
|
vec3 lightDir = vec3(0);
|
||||||
if(lights[i].position.w == 0)
|
if(lights[i].position.w == 0)
|
||||||
|
@ -68,7 +67,20 @@ void main() {
|
||||||
|
|
||||||
const float diff = max(dot(norm, lightDir), 0.0);
|
const float diff = max(dot(norm, lightDir), 0.0);
|
||||||
const float shadow = shadowFilterPCF == 1 ? filterPCF(inShadowPos / inShadowPos.w) : textureProj(inShadowPos / inShadowPos.w, vec2(0, 0));
|
const float shadow = shadowFilterPCF == 1 ? filterPCF(inShadowPos / inShadowPos.w) : textureProj(inShadowPos / inShadowPos.w, vec2(0, 0));
|
||||||
diffuse += vec3(diff) * lights[i].color * shadow;
|
|
||||||
|
vec3 add = vec3(diff) * lights[i].color.rgb * shadow;
|
||||||
|
|
||||||
|
if(lights[i].position.w == 1) {
|
||||||
|
const float radius = 15.0;
|
||||||
|
const float dist = distance(inFragPos, lights[i].position.xyz);
|
||||||
|
|
||||||
|
float att = clamp(1.0 - dist / radius, 0.0, 1.0);
|
||||||
|
att *= att;
|
||||||
|
|
||||||
|
add *= att;
|
||||||
|
}
|
||||||
|
|
||||||
|
diffuse += add;
|
||||||
}
|
}
|
||||||
|
|
||||||
outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0);
|
outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0);
|
||||||
|
|
|
@ -9,8 +9,12 @@ layout(location = 1) out vec4 outShadowPos;
|
||||||
layout(location = 2) out vec3 outNormal;
|
layout(location = 2) out vec3 outNormal;
|
||||||
layout(location = 3) out vec2 outUV;
|
layout(location = 3) out vec2 outUV;
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
layout(set = 0, binding = 0) uniform SceneInfo {
|
||||||
mat4 vp, lightSpace;
|
mat4 vp, lightSpace;
|
||||||
|
} sceneInfo;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConstants {
|
||||||
|
mat4 m;
|
||||||
} pushConstants;
|
} pushConstants;
|
||||||
|
|
||||||
const mat4 biasMat = mat4(
|
const mat4 biasMat = mat4(
|
||||||
|
@ -20,9 +24,9 @@ const mat4 biasMat = mat4(
|
||||||
0.5, 0.5, 0.0, 1.0);
|
0.5, 0.5, 0.0, 1.0);
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = pushConstants.vp * vec4(inPosition, 1.0);
|
gl_Position = sceneInfo.vp * pushConstants.m * vec4(inPosition, 1.0);
|
||||||
outFragPos = inPosition;
|
outFragPos = vec3(pushConstants.m * vec4(inPosition, 1.0));
|
||||||
outShadowPos = (biasMat * pushConstants.lightSpace) * vec4(inPosition, 1.0);
|
outShadowPos = (biasMat * sceneInfo.lightSpace) * vec4(inPosition, 1.0);
|
||||||
outNormal = inNormal;
|
outNormal = mat3(transpose(inverse(pushConstants.m))) * inNormal;
|
||||||
outUV = inUV;
|
outUV = inUV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,11 @@ layout(location = 0) in vec2 inUV;
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConstants {
|
||||||
|
vec3 color;
|
||||||
|
} pushConstants;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
outColor = vec4(0.1, 0.1, 0.8, 1.0);
|
outColor = vec4(pushConstants.color, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
|
||||||
#include <json.hpp>
|
#include <json.hpp>
|
||||||
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
@ -10,6 +9,7 @@
|
||||||
#include "worldmanager.h"
|
#include "worldmanager.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "assetmanager.h"
|
#include "assetmanager.h"
|
||||||
|
#include "entityparser.h"
|
||||||
|
|
||||||
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
||||||
std::ifstream file("data/" + path);
|
std::ifstream file("data/" + path);
|
||||||
|
@ -26,18 +26,17 @@ Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
||||||
shot->end = shotObject["end"];
|
shot->end = shotObject["end"];
|
||||||
shot->world = shotObject["world"];
|
shot->world = shotObject["world"];
|
||||||
|
|
||||||
for(auto meshObject : shotObject["meshes"]) {
|
for(auto entityObject : shotObject["entities"]) {
|
||||||
CinematicMesh mesh;
|
CinematicEntity entity;
|
||||||
mesh.name = meshObject["name"];
|
entity.data = entityObject;
|
||||||
mesh.modelPath = meshObject["path"];
|
|
||||||
mesh.materialPath = meshObject["material"];
|
|
||||||
|
|
||||||
shot->meshes.push_back(mesh);
|
shot->entities.push_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto animationObject : shotObject["animations"]) {
|
for(auto animationObject : shotObject["animations"]) {
|
||||||
auto animation = new Animation();
|
auto animation = new Animation();
|
||||||
animation->targetName = animationObject["target"];
|
animation->targetName = animationObject["target"];
|
||||||
|
animation->targetComponent = animationObject["targetComponent"];
|
||||||
|
|
||||||
const auto property = animationObject["property"];
|
const auto property = animationObject["property"];
|
||||||
if(property == "position")
|
if(property == "position")
|
||||||
|
@ -113,10 +112,9 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
||||||
{
|
{
|
||||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||||
|
|
||||||
if(animation->target == nullptr)
|
if(animation->targetComponent == "Transform") {
|
||||||
worldManager.getCurrentWorld()->camera.position = pos;
|
TransformComponent* transform = ECS::getComponent<TransformComponent>(animation->target);
|
||||||
else {
|
transform->position = pos;
|
||||||
animation->target->position = pos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -124,13 +122,20 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
||||||
{
|
{
|
||||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||||
|
|
||||||
worldManager.getCurrentWorld()->camera.target = pos;
|
if(animation->targetComponent == "Camera") {
|
||||||
|
CameraComponent* camera = ECS::getComponent<CameraComponent>(animation->target);
|
||||||
|
camera->target = pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AnimationProperty::FoV:
|
case AnimationProperty::FoV:
|
||||||
{
|
{
|
||||||
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
|
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
|
||||||
worldManager.getCurrentWorld()->camera.fov = pos;
|
|
||||||
|
if(animation->targetComponent == "Camera") {
|
||||||
|
CameraComponent* camera = ECS::getComponent<CameraComponent>(animation->target);
|
||||||
|
camera->fov = pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -140,51 +145,27 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationSystem::preloadShot(Shot* shot) {
|
void AnimationSystem::preloadShot(Shot* shot) {
|
||||||
std::cout << "preloading shot..." << std::endl;
|
|
||||||
|
|
||||||
worldManager.loadWorld(shot->world);
|
worldManager.loadWorld(shot->world);
|
||||||
|
|
||||||
for(auto cimMesh : shot->meshes) {
|
for(auto cimEntity : shot->entities) {
|
||||||
Mesh* mesh = assetManager.loadMesh(cimMesh.modelPath);
|
EntityID entity = parseEntity(cimEntity.data, worldManager.getWorld(shot->world));
|
||||||
mesh->name = cimMesh.name;
|
|
||||||
mesh->material = assetManager.loadMaterial(cimMesh.materialPath);
|
|
||||||
mesh->tag = "cinematic";
|
|
||||||
|
|
||||||
for(auto animation : shot->animations) {
|
for(auto animation : shot->animations) {
|
||||||
if(animation->targetName == mesh->name)
|
if(animation->targetName == ECS::getComponent<InfoComponent>(entity)->name)
|
||||||
animation->target = mesh;
|
animation->target = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
shot->loadedMeshes.push_back(mesh);
|
shot->loadedEntities.push_back(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationSystem::loadShot(Shot* shot) {
|
void AnimationSystem::loadShot(Shot* shot) {
|
||||||
std::cout << "loading shot..." << std::endl;
|
|
||||||
|
|
||||||
worldManager.switchWorld(shot->world);
|
worldManager.switchWorld(shot->world);
|
||||||
|
|
||||||
for(auto mesh : shot->loadedMeshes)
|
|
||||||
worldManager.getCurrentWorld()->meshes.push_back(mesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationSystem::unloadShot(Shot* shot) {
|
void AnimationSystem::unloadShot(Shot* shot) {
|
||||||
std::cout << "unloading shot..." << std::endl;
|
|
||||||
|
|
||||||
World* world = worldManager.getCurrentWorld();
|
World* world = worldManager.getCurrentWorld();
|
||||||
|
|
||||||
for(auto mesh : world->meshes) {
|
for(auto entity : shot->loadedEntities)
|
||||||
if(mesh->tag == "cinematic") {
|
ECS::destroyEntity(entity);
|
||||||
//renderer->destroyMaterialBuffers(mesh->material);
|
|
||||||
delete mesh->material;
|
|
||||||
|
|
||||||
//renderer->destroyMeshBuffers(mesh);
|
|
||||||
delete mesh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
world->meshes.erase(std::remove_if(world->meshes.begin(),
|
|
||||||
world->meshes.end(),
|
|
||||||
[](Mesh* m){return m->tag == "cinematic";}),
|
|
||||||
world->meshes.end());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,15 @@
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
Mesh* AssetManager::loadMesh(const std::string& path) {
|
MeshAsset* AssetManager::loadMesh(const std::string& path) {
|
||||||
std::string fixedPath = "data/" + path;
|
std::string fixedPath = "data/" + path;
|
||||||
|
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene* scene = importer.ReadFile(fixedPath.c_str(), aiProcess_Triangulate);
|
const aiScene* scene = importer.ReadFile(fixedPath.c_str(), aiProcess_Triangulate);
|
||||||
|
if(scene == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
Mesh* mesh = new Mesh();
|
MeshAsset* mesh = new MeshAsset();
|
||||||
|
|
||||||
unsigned int indexOffset = 0;
|
unsigned int indexOffset = 0;
|
||||||
for(unsigned mi = 0; mi < scene->mNumMeshes; mi++) {
|
for(unsigned mi = 0; mi < scene->mNumMeshes; mi++) {
|
||||||
|
@ -46,13 +48,15 @@ Mesh* AssetManager::loadMesh(const std::string& path) {
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
Material* AssetManager::loadMaterial(const std::string& path) {
|
MaterialAsset* AssetManager::loadMaterial(const std::string& path) {
|
||||||
std::ifstream file("data/" + path);
|
std::ifstream file("data/" + path);
|
||||||
|
if(!file)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
file >> json;
|
file >> json;
|
||||||
|
|
||||||
Material* material = new Material();
|
MaterialAsset* material = new MaterialAsset();
|
||||||
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
||||||
|
|
||||||
renderer->fillMaterialBuffers(material);
|
renderer->fillMaterialBuffers(material);
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "camera.h"
|
#include "rendercollection.h"
|
||||||
|
#include "ecs.h"
|
||||||
|
|
||||||
DoFPass::DoFPass(Renderer& renderer) : renderer_(renderer) {
|
DoFPass::DoFPass(Renderer& renderer) : renderer_(renderer) {
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
|
@ -28,7 +29,7 @@ DoFPass::~DoFPass() {
|
||||||
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
|
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoFPass::render(VkCommandBuffer commandBuffer, Camera& camera, RenderTarget* target) {
|
void DoFPass::render(VkCommandBuffer commandBuffer, CameraComponent& camera, RenderTarget* target) {
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
viewport.width = target->extent.width / renderer_.getConfig().dofDownscale;
|
viewport.width = target->extent.width / renderer_.getConfig().dofDownscale;
|
||||||
viewport.height = target->extent.height / renderer_.getConfig().dofDownscale;
|
viewport.height = target->extent.height / renderer_.getConfig().dofDownscale;
|
||||||
|
|
44
src/entityparser.cpp
Normal file
44
src/entityparser.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "entityparser.h"
|
||||||
|
|
||||||
|
#include "assetmanager.h"
|
||||||
|
#include "stringutils.h"
|
||||||
|
|
||||||
|
EntityID parseEntity(const nlohmann::json& json, World* world) {
|
||||||
|
EntityID entity = ECS::createEntity(world);
|
||||||
|
|
||||||
|
InfoComponent* info = ECS::addComponent<InfoComponent>(entity);
|
||||||
|
info->name = json["name"];
|
||||||
|
|
||||||
|
for(auto componentObject : json["components"]) {
|
||||||
|
const auto& componentType = componentObject["type"];
|
||||||
|
|
||||||
|
if(componentType == "Transform") {
|
||||||
|
TransformComponent* transform = ECS::addComponent<TransformComponent>(entity);
|
||||||
|
|
||||||
|
auto tokens = tokenize(componentObject["position"]);
|
||||||
|
|
||||||
|
transform->position[0] = atof(tokens[0].c_str());
|
||||||
|
transform->position[1] = atof(tokens[1].c_str());
|
||||||
|
transform->position[2] = atof(tokens[2].c_str());
|
||||||
|
} else if(componentType == "Mesh") {
|
||||||
|
MeshComponent* mesh = ECS::addComponent<MeshComponent>(entity);
|
||||||
|
|
||||||
|
mesh->mesh = assetManager.loadMesh(componentObject["path"]);
|
||||||
|
mesh->material = assetManager.loadMaterial(componentObject["material"]);
|
||||||
|
} else if(componentType == "Light") {
|
||||||
|
LightComponent* light = ECS::addComponent<LightComponent>(entity);
|
||||||
|
|
||||||
|
auto tokens = tokenize(componentObject["color"]);
|
||||||
|
|
||||||
|
light->color[0] = atof(tokens[0].c_str());
|
||||||
|
light->color[1] = atof(tokens[1].c_str());
|
||||||
|
light->color[2] = atof(tokens[2].c_str());
|
||||||
|
|
||||||
|
light->type = componentObject["kind"];
|
||||||
|
} else if(componentType == "Camera") {
|
||||||
|
CameraComponent* camera = ECS::addComponent<CameraComponent>(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
32
src/main.cpp
32
src/main.cpp
|
@ -14,8 +14,6 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "light.h"
|
|
||||||
#include "camera.h"
|
|
||||||
#include "animationsystem.h"
|
#include "animationsystem.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -152,6 +150,13 @@ int main(int argc, char* argv[]) {
|
||||||
else {
|
else {
|
||||||
worldManager.loadWorld("test.world");
|
worldManager.loadWorld("test.world");
|
||||||
worldManager.switchWorld("test.world");
|
worldManager.switchWorld("test.world");
|
||||||
|
|
||||||
|
EntityID entity = ECS::createEntity(worldManager.getCurrentWorld());
|
||||||
|
|
||||||
|
TransformComponent* transform = ECS::addComponent<TransformComponent>(entity);
|
||||||
|
transform->position = glm::vec3(5, 5, 5);
|
||||||
|
|
||||||
|
ECS::addComponent<CameraComponent>(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
float currentTime = 0.0f, lastTime = 0.0f;
|
float currentTime = 0.0f, lastTime = 0.0f;
|
||||||
|
@ -211,17 +216,10 @@ int main(int argc, char* argv[]) {
|
||||||
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
|
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
|
||||||
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
|
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
|
||||||
|
|
||||||
ImGui::DragFloat3("Light Position", &worldManager.getCurrentWorld()->lights[0]->position[0]);
|
|
||||||
ImGui::DragFloat3("Camera Position", &worldManager.getCurrentWorld()->camera.position[0], 0.1f);
|
|
||||||
ImGui::DragFloat3("Target", &worldManager.getCurrentWorld()->camera.target[0], 0.1f);
|
|
||||||
ImGui::DragFloat("Aperture", &worldManager.getCurrentWorld()->camera.aperture, 0.01f, 0.0f, 1.0f);
|
|
||||||
ImGui::DragFloat("Focus Distance", &worldManager.getCurrentWorld()->camera.focusDistance);
|
|
||||||
ImGui::Text("dpack[2] = %f", (100 - worldManager.getCurrentWorld()->camera.focusDistance) / 100.0f);
|
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
renderer->render(*worldManager.getCurrentWorld(), worldManager.getCurrentWorld()->camera, target);
|
renderer->render(*worldManager.getCurrentWorld(), target);
|
||||||
|
|
||||||
if(record) {
|
if(record) {
|
||||||
static int frameNum = 0;
|
static int frameNum = 0;
|
||||||
|
@ -232,20 +230,6 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*for(auto mesh : world->meshes) {
|
|
||||||
renderer->destroyMaterialBuffers(mesh->material);
|
|
||||||
delete mesh->material;
|
|
||||||
|
|
||||||
renderer->destroyMeshBuffers(mesh);
|
|
||||||
delete mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto light : world->lights) {
|
|
||||||
delete light;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete world;*/
|
|
||||||
|
|
||||||
renderer->destroyRenderTarget(target);
|
renderer->destroyRenderTarget(target);
|
||||||
|
|
||||||
vkDestroySurfaceKHR(renderer->getInstance(), surface, nullptr);
|
vkDestroySurfaceKHR(renderer->getInstance(), surface, nullptr);
|
||||||
|
|
|
@ -11,8 +11,10 @@
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "camera.h"
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
#include "rendercollection.h"
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
Renderer::Renderer(GraphicsConfig config) : config_(config) {
|
Renderer::Renderer(GraphicsConfig config) : config_(config) {
|
||||||
createInstance();
|
createInstance();
|
||||||
|
@ -65,7 +67,37 @@ Renderer::~Renderer() {
|
||||||
vkDestroyInstance(instance_, nullptr);
|
vkDestroyInstance(instance_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
|
void Renderer::render(World& world, RenderTarget* target) {
|
||||||
|
RenderCollection collection;
|
||||||
|
|
||||||
|
// generate collection
|
||||||
|
{
|
||||||
|
auto meshes = ECS::getWorldComponents<MeshComponent>(&world);
|
||||||
|
for(auto [id, mesh] : meshes) {
|
||||||
|
RenderMesh renderMesh;
|
||||||
|
renderMesh.mesh = mesh;
|
||||||
|
renderMesh.transform = ECS::getComponent<TransformComponent>(id);
|
||||||
|
|
||||||
|
collection.meshes.push_back(renderMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lights = ECS::getWorldComponents<LightComponent>(&world);
|
||||||
|
for(auto [id, light] : lights) {
|
||||||
|
RenderLight renderLight;
|
||||||
|
renderLight.light = light;
|
||||||
|
renderLight.transform = ECS::getComponent<TransformComponent>(id);
|
||||||
|
|
||||||
|
collection.lights.push_back(renderLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cameras = ECS::getWorldComponents<CameraComponent>(&world);
|
||||||
|
|
||||||
|
auto [id, camera] = cameras[0];
|
||||||
|
|
||||||
|
collection.camera.camera = camera;
|
||||||
|
collection.camera.transform = ECS::getComponent<TransformComponent>(id);
|
||||||
|
}
|
||||||
|
|
||||||
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &target->imageIndex);
|
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &target->imageIndex);
|
||||||
|
|
||||||
target->currentResource = (target->imageIndex + 1) % numFrameResources;
|
target->currentResource = (target->imageIndex + 1) % numFrameResources;
|
||||||
|
@ -80,7 +112,7 @@ void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
|
||||||
|
|
||||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||||
|
|
||||||
shadowPass_->render(commandBuffer, world);
|
shadowPass_->render(commandBuffer, collection);
|
||||||
|
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
viewport.width = target->extent.width;
|
viewport.width = target->extent.width;
|
||||||
|
@ -107,12 +139,12 @@ void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
|
||||||
|
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
worldPass_->render(commandBuffer, world, camera, target);
|
worldPass_->render(commandBuffer, collection, target);
|
||||||
skyPass_->render(commandBuffer);
|
skyPass_->render(world.color, commandBuffer);
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
||||||
dofPass_->render(commandBuffer, camera, target);
|
dofPass_->render(commandBuffer, *collection.camera.camera, target);
|
||||||
|
|
||||||
// reset after dof pass
|
// reset after dof pass
|
||||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||||
|
@ -994,7 +1026,7 @@ uint32_t Renderer::findMemoryType(const uint32_t typeFilter, const VkMemoryPrope
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::fillMeshBuffers(Mesh* mesh) {
|
void Renderer::fillMeshBuffers(MeshAsset* mesh) {
|
||||||
// vertex
|
// vertex
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo bufferInfo = {};
|
VkBufferCreateInfo bufferInfo = {};
|
||||||
|
@ -1050,7 +1082,7 @@ void Renderer::fillMeshBuffers(Mesh* mesh) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::fillMaterialBuffers(Material* material) {
|
void Renderer::fillMaterialBuffers(MaterialAsset* material) {
|
||||||
int width = 0, height = 0, channels = 0;
|
int width = 0, height = 0, channels = 0;
|
||||||
stbi_uc* pixels = stbi_load(material->albedoTexturePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
stbi_uc* pixels = stbi_load(material->albedoTexturePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||||
if(pixels == nullptr)
|
if(pixels == nullptr)
|
||||||
|
@ -1139,7 +1171,7 @@ void Renderer::fillMaterialBuffers(Material* material) {
|
||||||
vkUpdateDescriptorSets(device_, 1, &albedoDescriptorWrite, 0, nullptr);
|
vkUpdateDescriptorSets(device_, 1, &albedoDescriptorWrite, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::destroyMaterialBuffers(Material* material) {
|
void Renderer::destroyMaterialBuffers(MaterialAsset* material) {
|
||||||
vkDeviceWaitIdle(device_);
|
vkDeviceWaitIdle(device_);
|
||||||
|
|
||||||
vkFreeDescriptorSets(device_, descriptorPool_, 1, &material->set);
|
vkFreeDescriptorSets(device_, descriptorPool_, 1, &material->set);
|
||||||
|
@ -1150,7 +1182,7 @@ void Renderer::destroyMaterialBuffers(Material* material) {
|
||||||
vkDestroyImage(device_, material->albedoImage, nullptr);
|
vkDestroyImage(device_, material->albedoImage, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::destroyMeshBuffers(Mesh* mesh) {
|
void Renderer::destroyMeshBuffers(MeshAsset* mesh) {
|
||||||
vkDeviceWaitIdle(device_);
|
vkDeviceWaitIdle(device_);
|
||||||
|
|
||||||
vkFreeMemory(device_, mesh->indexMemory, nullptr);
|
vkFreeMemory(device_, mesh->indexMemory, nullptr);
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "light.h"
|
#include "rendercollection.h"
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
|
||||||
ShadowPass::ShadowPass(Renderer& renderer) : renderer_(renderer) {
|
ShadowPass::ShadowPass(Renderer& renderer) : renderer_(renderer) {
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
|
@ -28,7 +30,7 @@ ShadowPass::~ShadowPass() {
|
||||||
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
|
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowPass::render(VkCommandBuffer commandBuffer, World& world) {
|
void ShadowPass::render(VkCommandBuffer commandBuffer, RenderCollection& collection) {
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
viewport.width = renderer_.getConfig().shadowResolution;
|
viewport.width = renderer_.getConfig().shadowResolution;
|
||||||
viewport.height = renderer_.getConfig().shadowResolution;
|
viewport.height = renderer_.getConfig().shadowResolution;
|
||||||
|
@ -59,23 +61,22 @@ void ShadowPass::render(VkCommandBuffer commandBuffer, World& world) {
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||||||
|
|
||||||
glm::mat4 lightSpace = glm::mat4(1.0f);
|
glm::mat4 lightSpace = glm::mat4(1.0f);
|
||||||
//lightSpace = glm::perspective(glm::radians(75.0f), 1.0f, 0.1f, 100.0f);
|
|
||||||
lightSpace = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 100.0f);
|
lightSpace = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 100.0f);
|
||||||
lightSpace *= glm::lookAt(world.lights[0]->position, glm::vec3(0), glm::vec3(0, -1, 0));
|
lightSpace *= glm::lookAt(collection.lights[0].transform->position, glm::vec3(0), glm::vec3(0, -1, 0));
|
||||||
|
|
||||||
world.lights[0]->matrix = lightSpace;
|
collection.lights[0].light->matrix = lightSpace;
|
||||||
|
|
||||||
for(const auto& mesh : world.meshes) {
|
for(const auto& mesh : collection.meshes) {
|
||||||
glm::mat4 mvp = world.lights[0]->matrix;
|
glm::mat4 mvp = collection.lights[0].light->matrix;
|
||||||
mvp = glm::translate(mvp, mesh->position);
|
mvp = glm::translate(mvp, mesh.transform->position);
|
||||||
|
|
||||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);
|
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);
|
||||||
|
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||||
vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(commandBuffer, mesh.mesh->mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
|
||||||
vkCmdDrawIndexed(commandBuffer, mesh->indices.size(), 1, 0, 0, 0);
|
vkCmdDrawIndexed(commandBuffer, mesh.mesh->mesh->indices.size(), 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
|
@ -13,8 +13,11 @@ SkyPass::~SkyPass() {
|
||||||
vkDestroyPipelineLayout(renderer_.getDevice(), pipelineLayout_, nullptr);
|
vkDestroyPipelineLayout(renderer_.getDevice(), pipelineLayout_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyPass::render(VkCommandBuffer commandBuffer) {
|
void SkyPass::render(glm::vec3 color, VkCommandBuffer commandBuffer) {
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||||||
|
|
||||||
|
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(glm::vec3), &color);
|
||||||
|
|
||||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +86,14 @@ void SkyPass::createPipeline() {
|
||||||
dynamicState.dynamicStateCount = dynamicStates.size();
|
dynamicState.dynamicStateCount = dynamicStates.size();
|
||||||
dynamicState.pDynamicStates = dynamicStates.data();
|
dynamicState.pDynamicStates = dynamicStates.data();
|
||||||
|
|
||||||
|
VkPushConstantRange pushConstant = {};
|
||||||
|
pushConstant.size = sizeof(glm::vec3);
|
||||||
|
pushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||||
|
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
|
||||||
|
|
||||||
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);
|
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);
|
||||||
|
|
||||||
|
|
|
@ -9,42 +9,27 @@
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "assetmanager.h"
|
#include "assetmanager.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "light.h"
|
#include "entityparser.h"
|
||||||
|
#include "ecs.h"
|
||||||
|
|
||||||
void WorldManager::loadWorld(const std::string& path) {
|
void WorldManager::loadWorld(const std::string& path) {
|
||||||
std::ifstream file("data/" + path);
|
std::ifstream file("data/" + path);
|
||||||
if(!file)
|
if(!file)
|
||||||
std::cout << "failed to load " << path << std::endl;
|
return;
|
||||||
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
file >> json;
|
file >> json;
|
||||||
|
|
||||||
World* world = new World();
|
World* world = new World();
|
||||||
|
|
||||||
for(auto meshObject : json["meshes"]) {
|
auto tokens = tokenize(json["environment"]["color"]);
|
||||||
Mesh* mesh = assetManager.loadMesh(meshObject["path"]);
|
|
||||||
mesh->material = assetManager.loadMaterial(meshObject["material"]);
|
|
||||||
|
|
||||||
auto tokens = tokenize(meshObject["position"]);
|
world->color[0] = atof(tokens[0].c_str());
|
||||||
|
world->color[1] = atof(tokens[1].c_str());
|
||||||
|
world->color[2] = atof(tokens[2].c_str());
|
||||||
|
|
||||||
mesh->position[0] = atof(tokens[0].c_str());
|
for(auto entityObject : json["entities"])
|
||||||
mesh->position[1] = atof(tokens[1].c_str());
|
EntityID entity = parseEntity(entityObject, world);
|
||||||
mesh->position[2] = atof(tokens[2].c_str());
|
|
||||||
|
|
||||||
world->meshes.push_back(mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto lightObject : json["lights"]) {
|
|
||||||
Light* light = new Light();
|
|
||||||
|
|
||||||
auto tokens = tokenize(lightObject["position"]);
|
|
||||||
|
|
||||||
light->position[0] = atof(tokens[0].c_str());
|
|
||||||
light->position[1] = atof(tokens[1].c_str());
|
|
||||||
light->position[2] = atof(tokens[2].c_str());
|
|
||||||
|
|
||||||
world->lights.push_back(light);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadedWorlds[path] = world;
|
loadedWorlds[path] = world;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
#include "worldpass.h"
|
#include "worldpass.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "light.h"
|
|
||||||
#include "camera.h"
|
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
#include "ecs.h"
|
||||||
|
|
||||||
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
createDescriptorSetLayout();
|
createDescriptorSetLayout();
|
||||||
createPipeline();
|
createPipeline();
|
||||||
createUniformBuffer();
|
createUniformBuffers();
|
||||||
createDescriptorSet();
|
createDescriptorSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,24 +30,40 @@ WorldPass::~WorldPass() {
|
||||||
vkDestroyBuffer(renderer_.getDevice(), lightBuffer_, nullptr);
|
vkDestroyBuffer(renderer_.getDevice(), lightBuffer_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& camera, RenderTarget* target) {
|
void WorldPass::render(VkCommandBuffer commandBuffer, RenderCollection& collection, RenderTarget* target) {
|
||||||
|
glm::mat4* sceneData;
|
||||||
|
vkMapMemory(renderer_.getDevice(), sceneMemory_, 0, sizeof(glm::mat4) * 2, 0, reinterpret_cast<void**>(&sceneData));
|
||||||
|
|
||||||
|
glm::mat4 vp;
|
||||||
|
vp = glm::perspective(glm::radians(collection.camera.camera->fov), (float)target->extent.width / target->extent.height, collection.camera.camera->near, collection.camera.camera->far);
|
||||||
|
vp *= glm::lookAt(collection.camera.transform->position, collection.camera.camera->target, glm::vec3(0, -1, 0));
|
||||||
|
|
||||||
|
memcpy(sceneData, &vp, sizeof(glm::mat4));
|
||||||
|
|
||||||
|
sceneData++;
|
||||||
|
|
||||||
|
memcpy(sceneData, &collection.lights[0].light->matrix, sizeof(glm::mat4));
|
||||||
|
|
||||||
|
vkUnmapMemory(renderer_.getDevice(), sceneMemory_);
|
||||||
|
|
||||||
struct ShaderLight {
|
struct ShaderLight {
|
||||||
glm::vec4 position;
|
glm::vec4 position, color;
|
||||||
glm::vec3 color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ShaderLight* data;
|
ShaderLight* data;
|
||||||
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 3) * 32, 0, reinterpret_cast<void**>(&data));
|
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (8) * 32, 0, reinterpret_cast<void**>(&data));
|
||||||
|
|
||||||
for(const auto& light : world.lights) {
|
memset(data, 0, sizeof(float) * (8) * 32);
|
||||||
|
|
||||||
|
for(const auto& light : collection.lights) {
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
if(light->type == LightType::Point)
|
if(light.light->type == LightType::Point)
|
||||||
position = light->position;
|
position = light.transform->position;
|
||||||
else
|
else
|
||||||
position = glm::normalize(glm::vec3(0) - light->position);
|
position = glm::normalize(glm::vec3(0) - light.transform->position);
|
||||||
|
|
||||||
data->position = glm::vec4(position, ((int)light->type) + 1);
|
data->position = glm::vec4(position, ((int)light.light->type) + 1);
|
||||||
data->color = light->color;
|
data->color = glm::vec4(light.light->color, 0.0);
|
||||||
|
|
||||||
data++;
|
data++;
|
||||||
}
|
}
|
||||||
|
@ -57,23 +73,19 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr);
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr);
|
||||||
|
|
||||||
for(const auto& mesh : world.meshes) {
|
for(const auto& mesh : collection.meshes) {
|
||||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh->material->set, 0, nullptr);
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh.mesh->material->set, 0, nullptr);
|
||||||
|
|
||||||
glm::mat4 vp;
|
glm::mat4 m(1.0f);
|
||||||
vp = glm::perspective(glm::radians(camera.fov), (float)target->extent.width / target->extent.height, camera.near, camera.far);
|
m = glm::translate(m, mesh.transform->position);
|
||||||
vp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
|
|
||||||
vp = glm::translate(vp, mesh->position);
|
|
||||||
|
|
||||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &vp);
|
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &m);
|
||||||
|
|
||||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), sizeof(glm::mat4), &world.lights[0]->matrix);
|
|
||||||
|
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||||
vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
vkCmdBindIndexBuffer(commandBuffer, mesh.mesh->mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
|
||||||
vkCmdDrawIndexed(commandBuffer, mesh->indices.size(), 1, 0, 0, 0);
|
vkCmdDrawIndexed(commandBuffer, mesh.mesh->mesh->indices.size(), 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,18 +158,25 @@ void WorldPass::createRenderPass() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPass::createDescriptorSetLayout() {
|
void WorldPass::createDescriptorSetLayout() {
|
||||||
|
VkDescriptorSetLayoutBinding sceneBufferBinding = {};
|
||||||
|
sceneBufferBinding.descriptorCount = 1;
|
||||||
|
sceneBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
sceneBufferBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding lightBufferBinding = {};
|
VkDescriptorSetLayoutBinding lightBufferBinding = {};
|
||||||
lightBufferBinding.descriptorCount = 1;
|
lightBufferBinding.descriptorCount = 1;
|
||||||
|
lightBufferBinding.binding = 1;
|
||||||
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding shadowBinding = {};
|
VkDescriptorSetLayoutBinding shadowBinding = {};
|
||||||
shadowBinding.descriptorCount = 1;
|
shadowBinding.descriptorCount = 1;
|
||||||
shadowBinding.binding = 1;
|
shadowBinding.binding = 2;
|
||||||
shadowBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
shadowBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
shadowBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
shadowBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
const std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
|
const std::array<VkDescriptorSetLayoutBinding, 3> bindings = {
|
||||||
|
sceneBufferBinding,
|
||||||
lightBufferBinding,
|
lightBufferBinding,
|
||||||
shadowBinding
|
shadowBinding
|
||||||
};
|
};
|
||||||
|
@ -275,7 +294,7 @@ void WorldPass::createPipeline() {
|
||||||
dynamicState.pDynamicStates = dynamicStates.data();
|
dynamicState.pDynamicStates = dynamicStates.data();
|
||||||
|
|
||||||
VkPushConstantRange mvpPushConstant = {};
|
VkPushConstantRange mvpPushConstant = {};
|
||||||
mvpPushConstant.size = sizeof(glm::mat4) * 2;
|
mvpPushConstant.size = sizeof(glm::mat4);
|
||||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
|
||||||
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
||||||
|
@ -313,10 +332,34 @@ void WorldPass::createPipeline() {
|
||||||
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
|
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPass::createUniformBuffer() {
|
void WorldPass::createUniformBuffers() {
|
||||||
|
// scene
|
||||||
|
{
|
||||||
VkBufferCreateInfo bufferInfo = {};
|
VkBufferCreateInfo bufferInfo = {};
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
bufferInfo.size = sizeof(float) * (4 + 3) * 32;
|
bufferInfo.size = sizeof(glm::mat4) * 2;
|
||||||
|
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
vkCreateBuffer(renderer_.getDevice(), &bufferInfo, nullptr, &sceneBuffer_);
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(renderer_.getDevice(), sceneBuffer_, &memRequirements);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocInfo = {};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
allocInfo.allocationSize = memRequirements.size;
|
||||||
|
allocInfo.memoryTypeIndex = renderer_.findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
|
vkAllocateMemory(renderer_.getDevice(), &allocInfo, nullptr, &sceneMemory_);
|
||||||
|
vkBindBufferMemory(renderer_.getDevice(), sceneBuffer_, sceneMemory_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// light
|
||||||
|
{
|
||||||
|
VkBufferCreateInfo bufferInfo = {};
|
||||||
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bufferInfo.size = sizeof(float) * (8) * 32;
|
||||||
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
@ -332,6 +375,7 @@ void WorldPass::createUniformBuffer() {
|
||||||
|
|
||||||
vkAllocateMemory(renderer_.getDevice(), &allocInfo, nullptr, &lightMemory_);
|
vkAllocateMemory(renderer_.getDevice(), &allocInfo, nullptr, &lightMemory_);
|
||||||
vkBindBufferMemory(renderer_.getDevice(), lightBuffer_, lightMemory_, 0);
|
vkBindBufferMemory(renderer_.getDevice(), lightBuffer_, lightMemory_, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPass::createDescriptorSet() {
|
void WorldPass::createDescriptorSet() {
|
||||||
|
@ -343,41 +387,54 @@ void WorldPass::createDescriptorSet() {
|
||||||
|
|
||||||
vkAllocateDescriptorSets(renderer_.getDevice(), &allocInfo, &descriptorSet_);
|
vkAllocateDescriptorSets(renderer_.getDevice(), &allocInfo, &descriptorSet_);
|
||||||
|
|
||||||
VkDescriptorBufferInfo bufferInfo = {};
|
VkDescriptorBufferInfo sceneBufferInfo = {};
|
||||||
bufferInfo.buffer = lightBuffer_;
|
sceneBufferInfo.buffer = sceneBuffer_;
|
||||||
bufferInfo.range = sizeof(float) * (4 + 3) * 32;
|
sceneBufferInfo .range = sizeof(glm::mat4) * 2;
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo lightBufferInfo = {};
|
||||||
|
lightBufferInfo.buffer = lightBuffer_;
|
||||||
|
lightBufferInfo.range = sizeof(float) * (8) * 32;
|
||||||
|
|
||||||
VkDescriptorImageInfo imageInfo = {};
|
VkDescriptorImageInfo imageInfo = {};
|
||||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
imageInfo.imageView = renderer_.getShadowPass().getImageView();
|
imageInfo.imageView = renderer_.getShadowPass().getImageView();
|
||||||
imageInfo.sampler = renderer_.getShadowPass().getSampler();
|
imageInfo.sampler = renderer_.getShadowPass().getSampler();
|
||||||
|
|
||||||
VkWriteDescriptorSet bufferDescriptorWrite = {};
|
VkWriteDescriptorSet sceneBufferDescriptorWrite = {};
|
||||||
bufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
sceneBufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
bufferDescriptorWrite.descriptorCount = 1;
|
sceneBufferDescriptorWrite.descriptorCount = 1;
|
||||||
bufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
sceneBufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
bufferDescriptorWrite.dstSet = descriptorSet_;
|
sceneBufferDescriptorWrite.dstSet = descriptorSet_;
|
||||||
bufferDescriptorWrite.pBufferInfo = &bufferInfo;
|
sceneBufferDescriptorWrite.pBufferInfo = &sceneBufferInfo;
|
||||||
|
|
||||||
|
VkWriteDescriptorSet lightBufferDescriptorWrite = {};
|
||||||
|
lightBufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
lightBufferDescriptorWrite.descriptorCount = 1;
|
||||||
|
lightBufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
lightBufferDescriptorWrite.dstBinding = 1;
|
||||||
|
lightBufferDescriptorWrite.dstSet = descriptorSet_;
|
||||||
|
lightBufferDescriptorWrite.pBufferInfo = &lightBufferInfo;
|
||||||
|
|
||||||
VkWriteDescriptorSet shadowDescriptorWrite = {};
|
VkWriteDescriptorSet shadowDescriptorWrite = {};
|
||||||
shadowDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
shadowDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
shadowDescriptorWrite.descriptorCount = 1;
|
shadowDescriptorWrite.descriptorCount = 1;
|
||||||
shadowDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
shadowDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
shadowDescriptorWrite.dstBinding = 1;
|
shadowDescriptorWrite.dstBinding = 2;
|
||||||
shadowDescriptorWrite.dstSet = descriptorSet_;
|
shadowDescriptorWrite.dstSet = descriptorSet_;
|
||||||
shadowDescriptorWrite.pImageInfo = &imageInfo;
|
shadowDescriptorWrite.pImageInfo = &imageInfo;
|
||||||
|
|
||||||
const std::array<VkWriteDescriptorSet, 2> descriptorWrites = {
|
const std::array<VkWriteDescriptorSet, 3> descriptorWrites = {
|
||||||
bufferDescriptorWrite,
|
sceneBufferDescriptorWrite,
|
||||||
|
lightBufferDescriptorWrite,
|
||||||
shadowDescriptorWrite
|
shadowDescriptorWrite
|
||||||
};
|
};
|
||||||
|
|
||||||
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
||||||
|
|
||||||
float* data;
|
float* data;
|
||||||
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 3) * 32, 0, reinterpret_cast<void**>(&data));
|
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (8) * 32, 0, reinterpret_cast<void**>(&data));
|
||||||
|
|
||||||
for(uint32_t i = 0; i < (4 + 3) * 32; i++)
|
for(uint32_t i = 0; i < (8) * 32; i++)
|
||||||
data[i] = 0.0f;
|
data[i] = 0.0f;
|
||||||
|
|
||||||
vkUnmapMemory(renderer_.getDevice(), lightMemory_);
|
vkUnmapMemory(renderer_.getDevice(), lightMemory_);
|
||||||
|
|
Reference in a new issue