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/CopyData.cmake)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_package(Vulkan REQUIRED)
|
||||
|
@ -56,7 +56,8 @@ set(GRAPH_SRC
|
|||
src/stringutils.cpp
|
||||
src/animationsystem.cpp
|
||||
src/worldmanager.cpp
|
||||
src/assetmanager.cpp)
|
||||
src/assetmanager.cpp
|
||||
src/entityparser.cpp)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(GRAPH_SRC
|
||||
|
@ -69,8 +70,7 @@ add_executable(Graph
|
|||
|
||||
target_compile_options(Graph
|
||||
PUBLIC
|
||||
-fno-exceptions
|
||||
-fno-rtti)
|
||||
-fno-exceptions)
|
||||
target_link_libraries(Graph
|
||||
PUBLIC
|
||||
SDL2::SDL2
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"meshes": [
|
||||
|
||||
],
|
||||
"lights": [
|
||||
"entities": [
|
||||
{
|
||||
"position": "66,56,25",
|
||||
"type": 1
|
||||
"name": "sun",
|
||||
"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",
|
||||
"start": 0,
|
||||
"end": 5,
|
||||
"meshes": [
|
||||
"entities": [
|
||||
{
|
||||
"name": "suzanne",
|
||||
"components": [
|
||||
{
|
||||
"type": "Mesh",
|
||||
"path": "suzanne.obj",
|
||||
"material": "test.material"
|
||||
},
|
||||
{
|
||||
"type": "Transform",
|
||||
"position": "0,0,0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "suzanne2",
|
||||
"components": [
|
||||
{
|
||||
"type": "Mesh",
|
||||
"path": "suzanne.obj",
|
||||
"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": [
|
||||
{
|
||||
"target": "suzanne",
|
||||
"targetComponent": "Transform",
|
||||
"property": "position",
|
||||
"keyframes": [
|
||||
{
|
||||
"time": 0,
|
||||
"value": "0,0,0"
|
||||
"value": "0,2,0"
|
||||
},
|
||||
{
|
||||
"time": 1,
|
||||
"value": "0,2,-3.5"
|
||||
"value": "0,4,-3.5"
|
||||
},
|
||||
{
|
||||
"time": 3,
|
||||
"value": "0,0.5,-4"
|
||||
"value": "0,2.5,-4"
|
||||
},
|
||||
{
|
||||
"time": 5,
|
||||
"value": "0,0,-6"
|
||||
"value": "0,2,-6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "suzanne2",
|
||||
"targetComponent": "Transform",
|
||||
"property": "position",
|
||||
"keyframes": [
|
||||
{
|
||||
"time": 0,
|
||||
"value": "5,0,-2"
|
||||
"value": "5,2,-2"
|
||||
},
|
||||
{
|
||||
"time": 2,
|
||||
"value": "-5,0,-2"
|
||||
"value": "-5,2,-2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "camera",
|
||||
"targetComponent": "Transform",
|
||||
"property": "position",
|
||||
"keyframes": [
|
||||
{
|
||||
|
@ -73,30 +112,39 @@
|
|||
"world": "empty.world",
|
||||
"start": 5,
|
||||
"end": 10,
|
||||
"meshes": [
|
||||
"entities": [
|
||||
{
|
||||
"name": "suzanne",
|
||||
"components": [
|
||||
{
|
||||
"type": "Mesh",
|
||||
"path": "suzanne.obj",
|
||||
"material": "test.material"
|
||||
}
|
||||
],
|
||||
"animations": [
|
||||
{
|
||||
"target": "suzanne",
|
||||
"property": "position",
|
||||
"keyframes": [
|
||||
{
|
||||
"time": 5,
|
||||
"value": "0,5,0"
|
||||
},
|
||||
{
|
||||
"time": 10,
|
||||
"value": "0,5,0"
|
||||
"type": "Transform",
|
||||
"position": "0,5,0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "camera",
|
||||
"components": [
|
||||
{
|
||||
"type": "Transform",
|
||||
"position": "0,0,0"
|
||||
},
|
||||
{
|
||||
"type": "Camera",
|
||||
"fov": 75
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"animations": [
|
||||
{
|
||||
"target": "camera",
|
||||
"targetComponent": "Transform",
|
||||
"property": "position",
|
||||
"keyframes": [
|
||||
{
|
||||
|
@ -111,6 +159,7 @@
|
|||
},
|
||||
{
|
||||
"target": "camera",
|
||||
"targetComponent": "Camera",
|
||||
"property": "fov",
|
||||
"keyframes": [
|
||||
{
|
||||
|
@ -125,6 +174,7 @@
|
|||
},
|
||||
{
|
||||
"target": "camera",
|
||||
"targetComponent": "Camera",
|
||||
"property": "target",
|
||||
"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",
|
||||
"material": "test.material"
|
||||
}
|
||||
],
|
||||
"lights": [
|
||||
]
|
||||
},
|
||||
{
|
||||
"position": "66,56,25",
|
||||
"type": 1
|
||||
"name": "sun",
|
||||
"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>
|
||||
|
||||
struct Mesh;
|
||||
struct Material;
|
||||
struct MeshAsset;
|
||||
struct MaterialAsset;
|
||||
class Renderer;
|
||||
|
||||
class AssetManager {
|
||||
|
@ -12,8 +12,8 @@ public:
|
|||
renderer = r;
|
||||
}
|
||||
|
||||
Mesh* loadMesh(const std::string& path);
|
||||
Material* loadMaterial(const std::string& path);
|
||||
MeshAsset* loadMesh(const std::string& path);
|
||||
MaterialAsset* loadMaterial(const std::string& path);
|
||||
|
||||
private:
|
||||
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 <glm/glm.hpp>
|
||||
#include <json.hpp>
|
||||
|
||||
class Mesh;
|
||||
#include "ecs.h"
|
||||
|
||||
struct Keyframe {
|
||||
int time = 0;
|
||||
|
@ -18,15 +19,15 @@ enum class AnimationProperty {
|
|||
};
|
||||
|
||||
struct Animation {
|
||||
Mesh* target = nullptr;
|
||||
std::string targetName;
|
||||
EntityID target;
|
||||
std::string targetName, targetComponent;
|
||||
AnimationProperty property = AnimationProperty::Position;
|
||||
|
||||
std::vector<Keyframe> keyframes;
|
||||
};
|
||||
|
||||
struct CinematicMesh {
|
||||
std::string name, modelPath, materialPath;
|
||||
struct CinematicEntity {
|
||||
nlohmann::json data;
|
||||
};
|
||||
|
||||
struct Shot {
|
||||
|
@ -35,8 +36,8 @@ struct Shot {
|
|||
|
||||
std::string world;
|
||||
|
||||
std::vector<CinematicMesh> meshes;
|
||||
std::vector<Mesh*> loadedMeshes;
|
||||
std::vector<CinematicEntity> entities;
|
||||
std::vector<EntityID> loadedEntities;
|
||||
std::vector<Animation*> animations;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
|
||||
class Renderer;
|
||||
struct RenderTarget;
|
||||
class Camera;
|
||||
struct CameraComponent;
|
||||
|
||||
class DoFPass {
|
||||
public:
|
||||
DoFPass(Renderer& renderer);
|
||||
~DoFPass();
|
||||
|
||||
void render(VkCommandBuffer commandBuffer, Camera& camera, RenderTarget* target);
|
||||
void render(VkCommandBuffer commandBuffer, CameraComponent& camera, 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 <glm/glm.hpp>
|
||||
|
||||
class Material {
|
||||
public:
|
||||
struct MaterialAsset {
|
||||
std::string albedoTexturePath;
|
||||
|
||||
VkImage albedoImage = nullptr;
|
||||
|
|
|
@ -6,20 +6,12 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class Material;
|
||||
|
||||
struct Vertex {
|
||||
glm::vec3 position, normal;
|
||||
glm::vec2 uv;
|
||||
};
|
||||
|
||||
class Mesh {
|
||||
public:
|
||||
std::string name, tag;
|
||||
glm::vec3 position;
|
||||
|
||||
Material* material = nullptr;
|
||||
|
||||
struct MeshAsset {
|
||||
std::vector<Vertex> vertices;
|
||||
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 Mesh;
|
||||
class MeshAsset;
|
||||
class Camera;
|
||||
class Material;
|
||||
class MaterialAsset;
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer(GraphicsConfig config);
|
||||
~Renderer();
|
||||
|
||||
void render(World& world, Camera& camera, RenderTarget* target);
|
||||
void render(World& world, RenderTarget* target);
|
||||
|
||||
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldTarget = nullptr);
|
||||
void destroyRenderTarget(RenderTarget* target);
|
||||
|
@ -96,11 +96,11 @@ public:
|
|||
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
|
||||
void fillMeshBuffers(Mesh* mesh);
|
||||
void destroyMeshBuffers(Mesh* mesh);
|
||||
void fillMeshBuffers(MeshAsset* mesh);
|
||||
void destroyMeshBuffers(MeshAsset* mesh);
|
||||
|
||||
void fillMaterialBuffers(Material* material);
|
||||
void destroyMaterialBuffers(Material* material);
|
||||
void fillMaterialBuffers(MaterialAsset* material);
|
||||
void destroyMaterialBuffers(MaterialAsset* material);
|
||||
|
||||
GraphicsConfig getConfig() const {
|
||||
return config_;
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
class Renderer;
|
||||
class World;
|
||||
struct RenderCollection;
|
||||
|
||||
class ShadowPass {
|
||||
public:
|
||||
ShadowPass(Renderer& renderer);
|
||||
~ShadowPass();
|
||||
|
||||
void render(VkCommandBuffer commandBuffer, World& world);
|
||||
void render(VkCommandBuffer commandBuffer, RenderCollection& collection);
|
||||
|
||||
VkImageView getImageView() const {
|
||||
return shadowImageView_;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Renderer;
|
||||
|
||||
|
@ -9,7 +10,7 @@ public:
|
|||
SkyPass(Renderer& renderer);
|
||||
~SkyPass();
|
||||
|
||||
void render(VkCommandBuffer commandBuffer);
|
||||
void render(glm::vec3 color, VkCommandBuffer commandBuffer);
|
||||
|
||||
private:
|
||||
void createPipeline();
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
class Mesh;
|
||||
class Light;
|
||||
|
||||
class World {
|
||||
public:
|
||||
std::vector<Mesh*> meshes;
|
||||
std::vector<Light*> lights;
|
||||
|
||||
Camera camera;
|
||||
struct World {
|
||||
glm::vec3 color;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,10 @@ public:
|
|||
return currentWorld;
|
||||
}
|
||||
|
||||
World* getWorld(const std::string& path) {
|
||||
return loadedWorlds[path];
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, World*> loadedWorlds;
|
||||
World* currentWorld = nullptr;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "rendercollection.h"
|
||||
|
||||
class Renderer;
|
||||
class World;
|
||||
struct RenderTarget;
|
||||
|
@ -12,7 +14,7 @@ public:
|
|||
WorldPass(Renderer& renderer);
|
||||
~WorldPass();
|
||||
|
||||
void render(VkCommandBuffer commandBuffer, World& world, Camera& camera, RenderTarget* target);
|
||||
void render(VkCommandBuffer commandBuffer, RenderCollection& collection, RenderTarget* target);
|
||||
|
||||
VkRenderPass getRenderPass() const {
|
||||
return renderPass_;
|
||||
|
@ -22,7 +24,7 @@ private:
|
|||
void createRenderPass();
|
||||
void createDescriptorSetLayout();
|
||||
void createPipeline();
|
||||
void createUniformBuffer();
|
||||
void createUniformBuffers();
|
||||
void createDescriptorSet();
|
||||
|
||||
VkRenderPass renderPass_ = nullptr;
|
||||
|
@ -32,6 +34,9 @@ private:
|
|||
VkPipelineLayout pipelineLayout_ = nullptr;
|
||||
VkPipeline pipeline_ = nullptr;
|
||||
|
||||
VkDeviceMemory sceneMemory_ = nullptr;
|
||||
VkBuffer sceneBuffer_ = nullptr;
|
||||
|
||||
VkDeviceMemory lightMemory_ = nullptr;
|
||||
VkBuffer lightBuffer_ = nullptr;
|
||||
|
||||
|
|
|
@ -8,15 +8,14 @@ layout(location = 3) in vec2 inUV;
|
|||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
struct Light {
|
||||
vec4 position;
|
||||
vec3 color;
|
||||
vec4 position, color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 0) uniform Lights {
|
||||
layout(set = 0, binding = 1) uniform Lights {
|
||||
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(constant_id = 0) const int shadowFilterPCF = 1;
|
||||
|
@ -54,7 +53,7 @@ float filterPCF(vec4 sc) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
vec3 diffuse = vec3(0);
|
||||
vec3 diffuse = vec3(0.0);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
vec3 lightDir = vec3(0);
|
||||
if(lights[i].position.w == 0)
|
||||
|
@ -68,7 +67,20 @@ void main() {
|
|||
|
||||
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));
|
||||
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);
|
||||
|
|
|
@ -9,8 +9,12 @@ layout(location = 1) out vec4 outShadowPos;
|
|||
layout(location = 2) out vec3 outNormal;
|
||||
layout(location = 3) out vec2 outUV;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
layout(set = 0, binding = 0) uniform SceneInfo {
|
||||
mat4 vp, lightSpace;
|
||||
} sceneInfo;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 m;
|
||||
} pushConstants;
|
||||
|
||||
const mat4 biasMat = mat4(
|
||||
|
@ -20,9 +24,9 @@ const mat4 biasMat = mat4(
|
|||
0.5, 0.5, 0.0, 1.0);
|
||||
|
||||
void main() {
|
||||
gl_Position = pushConstants.vp * vec4(inPosition, 1.0);
|
||||
outFragPos = inPosition;
|
||||
outShadowPos = (biasMat * pushConstants.lightSpace) * vec4(inPosition, 1.0);
|
||||
outNormal = inNormal;
|
||||
gl_Position = sceneInfo.vp * pushConstants.m * vec4(inPosition, 1.0);
|
||||
outFragPos = vec3(pushConstants.m * vec4(inPosition, 1.0));
|
||||
outShadowPos = (biasMat * sceneInfo.lightSpace) * vec4(inPosition, 1.0);
|
||||
outNormal = mat3(transpose(inverse(pushConstants.m))) * inNormal;
|
||||
outUV = inUV;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,11 @@ layout(location = 0) in vec2 inUV;
|
|||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec3 color;
|
||||
} pushConstants;
|
||||
|
||||
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 <sstream>
|
||||
#include <iostream>
|
||||
#include <json.hpp>
|
||||
|
||||
#include "mesh.h"
|
||||
|
@ -10,6 +9,7 @@
|
|||
#include "worldmanager.h"
|
||||
#include "world.h"
|
||||
#include "assetmanager.h"
|
||||
#include "entityparser.h"
|
||||
|
||||
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
|
@ -26,18 +26,17 @@ Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
|||
shot->end = shotObject["end"];
|
||||
shot->world = shotObject["world"];
|
||||
|
||||
for(auto meshObject : shotObject["meshes"]) {
|
||||
CinematicMesh mesh;
|
||||
mesh.name = meshObject["name"];
|
||||
mesh.modelPath = meshObject["path"];
|
||||
mesh.materialPath = meshObject["material"];
|
||||
for(auto entityObject : shotObject["entities"]) {
|
||||
CinematicEntity entity;
|
||||
entity.data = entityObject;
|
||||
|
||||
shot->meshes.push_back(mesh);
|
||||
shot->entities.push_back(entity);
|
||||
}
|
||||
|
||||
for(auto animationObject : shotObject["animations"]) {
|
||||
auto animation = new Animation();
|
||||
animation->targetName = animationObject["target"];
|
||||
animation->targetComponent = animationObject["targetComponent"];
|
||||
|
||||
const auto property = animationObject["property"];
|
||||
if(property == "position")
|
||||
|
@ -113,10 +112,9 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
|||
{
|
||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||
|
||||
if(animation->target == nullptr)
|
||||
worldManager.getCurrentWorld()->camera.position = pos;
|
||||
else {
|
||||
animation->target->position = pos;
|
||||
if(animation->targetComponent == "Transform") {
|
||||
TransformComponent* transform = ECS::getComponent<TransformComponent>(animation->target);
|
||||
transform->position = pos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -124,13 +122,20 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
|||
{
|
||||
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;
|
||||
case AnimationProperty::FoV:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -140,51 +145,27 @@ void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
|||
}
|
||||
|
||||
void AnimationSystem::preloadShot(Shot* shot) {
|
||||
std::cout << "preloading shot..." << std::endl;
|
||||
|
||||
worldManager.loadWorld(shot->world);
|
||||
|
||||
for(auto cimMesh : shot->meshes) {
|
||||
Mesh* mesh = assetManager.loadMesh(cimMesh.modelPath);
|
||||
mesh->name = cimMesh.name;
|
||||
mesh->material = assetManager.loadMaterial(cimMesh.materialPath);
|
||||
mesh->tag = "cinematic";
|
||||
for(auto cimEntity : shot->entities) {
|
||||
EntityID entity = parseEntity(cimEntity.data, worldManager.getWorld(shot->world));
|
||||
|
||||
for(auto animation : shot->animations) {
|
||||
if(animation->targetName == mesh->name)
|
||||
animation->target = mesh;
|
||||
if(animation->targetName == ECS::getComponent<InfoComponent>(entity)->name)
|
||||
animation->target = entity;
|
||||
}
|
||||
|
||||
shot->loadedMeshes.push_back(mesh);
|
||||
shot->loadedEntities.push_back(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::loadShot(Shot* shot) {
|
||||
std::cout << "loading shot..." << std::endl;
|
||||
|
||||
worldManager.switchWorld(shot->world);
|
||||
|
||||
for(auto mesh : shot->loadedMeshes)
|
||||
worldManager.getCurrentWorld()->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
void AnimationSystem::unloadShot(Shot* shot) {
|
||||
std::cout << "unloading shot..." << std::endl;
|
||||
|
||||
World* world = worldManager.getCurrentWorld();
|
||||
|
||||
for(auto mesh : world->meshes) {
|
||||
if(mesh->tag == "cinematic") {
|
||||
//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());
|
||||
for(auto entity : shot->loadedEntities)
|
||||
ECS::destroyEntity(entity);
|
||||
}
|
||||
|
|
|
@ -11,13 +11,15 @@
|
|||
#include "material.h"
|
||||
#include "renderer.h"
|
||||
|
||||
Mesh* AssetManager::loadMesh(const std::string& path) {
|
||||
MeshAsset* AssetManager::loadMesh(const std::string& path) {
|
||||
std::string fixedPath = "data/" + path;
|
||||
|
||||
Assimp::Importer importer;
|
||||
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;
|
||||
for(unsigned mi = 0; mi < scene->mNumMeshes; mi++) {
|
||||
|
@ -46,13 +48,15 @@ Mesh* AssetManager::loadMesh(const std::string& path) {
|
|||
return mesh;
|
||||
}
|
||||
|
||||
Material* AssetManager::loadMaterial(const std::string& path) {
|
||||
MaterialAsset* AssetManager::loadMaterial(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
if(!file)
|
||||
return nullptr;
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
Material* material = new Material();
|
||||
MaterialAsset* material = new MaterialAsset();
|
||||
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
||||
|
||||
renderer->fillMaterialBuffers(material);
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include <stb_image.h>
|
||||
|
||||
#include "renderer.h"
|
||||
#include "camera.h"
|
||||
#include "rendercollection.h"
|
||||
#include "ecs.h"
|
||||
|
||||
DoFPass::DoFPass(Renderer& renderer) : renderer_(renderer) {
|
||||
createRenderPass();
|
||||
|
@ -28,7 +29,7 @@ DoFPass::~DoFPass() {
|
|||
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 = {};
|
||||
viewport.width = target->extent.width / 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 "world.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "camera.h"
|
||||
#include "animationsystem.h"
|
||||
#include "material.h"
|
||||
#include "config.h"
|
||||
|
@ -152,6 +150,13 @@ int main(int argc, char* argv[]) {
|
|||
else {
|
||||
worldManager.loadWorld("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;
|
||||
|
@ -211,17 +216,10 @@ int main(int argc, char* argv[]) {
|
|||
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
|
||||
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();
|
||||
#endif
|
||||
|
||||
renderer->render(*worldManager.getCurrentWorld(), worldManager.getCurrentWorld()->camera, target);
|
||||
renderer->render(*worldManager.getCurrentWorld(), target);
|
||||
|
||||
if(record) {
|
||||
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);
|
||||
|
||||
vkDestroySurfaceKHR(renderer->getInstance(), surface, nullptr);
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "mesh.h"
|
||||
#include "camera.h"
|
||||
#include "material.h"
|
||||
#include "rendercollection.h"
|
||||
#include "ecs.h"
|
||||
#include "world.h"
|
||||
|
||||
Renderer::Renderer(GraphicsConfig config) : config_(config) {
|
||||
createInstance();
|
||||
|
@ -65,7 +67,37 @@ Renderer::~Renderer() {
|
|||
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);
|
||||
|
||||
target->currentResource = (target->imageIndex + 1) % numFrameResources;
|
||||
|
@ -80,7 +112,7 @@ void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
|
|||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
|
||||
shadowPass_->render(commandBuffer, world);
|
||||
shadowPass_->render(commandBuffer, collection);
|
||||
|
||||
VkViewport viewport = {};
|
||||
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);
|
||||
|
||||
worldPass_->render(commandBuffer, world, camera, target);
|
||||
skyPass_->render(commandBuffer);
|
||||
worldPass_->render(commandBuffer, collection, target);
|
||||
skyPass_->render(world.color, commandBuffer);
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
dofPass_->render(commandBuffer, camera, target);
|
||||
dofPass_->render(commandBuffer, *collection.camera.camera, target);
|
||||
|
||||
// reset after dof pass
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||
|
@ -994,7 +1026,7 @@ uint32_t Renderer::findMemoryType(const uint32_t typeFilter, const VkMemoryPrope
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Renderer::fillMeshBuffers(Mesh* mesh) {
|
||||
void Renderer::fillMeshBuffers(MeshAsset* mesh) {
|
||||
// vertex
|
||||
{
|
||||
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;
|
||||
stbi_uc* pixels = stbi_load(material->albedoTexturePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
if(pixels == nullptr)
|
||||
|
@ -1139,7 +1171,7 @@ void Renderer::fillMaterialBuffers(Material* material) {
|
|||
vkUpdateDescriptorSets(device_, 1, &albedoDescriptorWrite, 0, nullptr);
|
||||
}
|
||||
|
||||
void Renderer::destroyMaterialBuffers(Material* material) {
|
||||
void Renderer::destroyMaterialBuffers(MaterialAsset* material) {
|
||||
vkDeviceWaitIdle(device_);
|
||||
|
||||
vkFreeDescriptorSets(device_, descriptorPool_, 1, &material->set);
|
||||
|
@ -1150,7 +1182,7 @@ void Renderer::destroyMaterialBuffers(Material* material) {
|
|||
vkDestroyImage(device_, material->albedoImage, nullptr);
|
||||
}
|
||||
|
||||
void Renderer::destroyMeshBuffers(Mesh* mesh) {
|
||||
void Renderer::destroyMeshBuffers(MeshAsset* mesh) {
|
||||
vkDeviceWaitIdle(device_);
|
||||
|
||||
vkFreeMemory(device_, mesh->indexMemory, nullptr);
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "renderer.h"
|
||||
#include "world.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "rendercollection.h"
|
||||
#include "ecs.h"
|
||||
#include "mesh.h"
|
||||
|
||||
ShadowPass::ShadowPass(Renderer& renderer) : renderer_(renderer) {
|
||||
createRenderPass();
|
||||
|
@ -28,7 +30,7 @@ ShadowPass::~ShadowPass() {
|
|||
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
|
||||
}
|
||||
|
||||
void ShadowPass::render(VkCommandBuffer commandBuffer, World& world) {
|
||||
void ShadowPass::render(VkCommandBuffer commandBuffer, RenderCollection& collection) {
|
||||
VkViewport viewport = {};
|
||||
viewport.width = 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_);
|
||||
|
||||
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::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) {
|
||||
glm::mat4 mvp = world.lights[0]->matrix;
|
||||
mvp = glm::translate(mvp, mesh->position);
|
||||
for(const auto& mesh : collection.meshes) {
|
||||
glm::mat4 mvp = collection.lights[0].light->matrix;
|
||||
mvp = glm::translate(mvp, mesh.transform->position);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);
|
||||
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
|
||||
vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||
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);
|
||||
|
|
|
@ -13,8 +13,11 @@ SkyPass::~SkyPass() {
|
|||
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_);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(glm::vec3), &color);
|
||||
|
||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -83,8 +86,14 @@ void SkyPass::createPipeline() {
|
|||
dynamicState.dynamicStateCount = dynamicStates.size();
|
||||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPushConstantRange pushConstant = {};
|
||||
pushConstant.size = sizeof(glm::vec3);
|
||||
pushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
|
||||
|
||||
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);
|
||||
|
||||
|
|
|
@ -9,42 +9,27 @@
|
|||
#include "world.h"
|
||||
#include "assetmanager.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "entityparser.h"
|
||||
#include "ecs.h"
|
||||
|
||||
void WorldManager::loadWorld(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
if(!file)
|
||||
std::cout << "failed to load " << path << std::endl;
|
||||
return;
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
World* world = new World();
|
||||
|
||||
for(auto meshObject : json["meshes"]) {
|
||||
Mesh* mesh = assetManager.loadMesh(meshObject["path"]);
|
||||
mesh->material = assetManager.loadMaterial(meshObject["material"]);
|
||||
auto tokens = tokenize(json["environment"]["color"]);
|
||||
|
||||
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());
|
||||
mesh->position[1] = atof(tokens[1].c_str());
|
||||
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);
|
||||
}
|
||||
for(auto entityObject : json["entities"])
|
||||
EntityID entity = parseEntity(entityObject, world);
|
||||
|
||||
loadedWorlds[path] = world;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
#include "worldpass.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "renderer.h"
|
||||
#include "world.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "camera.h"
|
||||
#include "material.h"
|
||||
#include "ecs.h"
|
||||
|
||||
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
||||
createRenderPass();
|
||||
createDescriptorSetLayout();
|
||||
createPipeline();
|
||||
createUniformBuffer();
|
||||
createUniformBuffers();
|
||||
createDescriptorSet();
|
||||
}
|
||||
|
||||
|
@ -30,24 +30,40 @@ WorldPass::~WorldPass() {
|
|||
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 {
|
||||
glm::vec4 position;
|
||||
glm::vec3 color;
|
||||
glm::vec4 position, color;
|
||||
};
|
||||
|
||||
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;
|
||||
if(light->type == LightType::Point)
|
||||
position = light->position;
|
||||
if(light.light->type == LightType::Point)
|
||||
position = light.transform->position;
|
||||
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->color = light->color;
|
||||
data->position = glm::vec4(position, ((int)light.light->type) + 1);
|
||||
data->color = glm::vec4(light.light->color, 0.0);
|
||||
|
||||
data++;
|
||||
}
|
||||
|
@ -57,23 +73,19 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
|
|||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr);
|
||||
|
||||
for(const auto& mesh : world.meshes) {
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh->material->set, 0, nullptr);
|
||||
for(const auto& mesh : collection.meshes) {
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh.mesh->material->set, 0, nullptr);
|
||||
|
||||
glm::mat4 vp;
|
||||
vp = glm::perspective(glm::radians(camera.fov), (float)target->extent.width / target->extent.height, camera.near, camera.far);
|
||||
vp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
|
||||
vp = glm::translate(vp, mesh->position);
|
||||
glm::mat4 m(1.0f);
|
||||
m = glm::translate(m, mesh.transform->position);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &vp);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), sizeof(glm::mat4), &world.lights[0]->matrix);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &m);
|
||||
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
|
||||
vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||
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() {
|
||||
VkDescriptorSetLayoutBinding sceneBufferBinding = {};
|
||||
sceneBufferBinding.descriptorCount = 1;
|
||||
sceneBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
sceneBufferBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
VkDescriptorSetLayoutBinding lightBufferBinding = {};
|
||||
lightBufferBinding.descriptorCount = 1;
|
||||
lightBufferBinding.binding = 1;
|
||||
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
VkDescriptorSetLayoutBinding shadowBinding = {};
|
||||
shadowBinding.descriptorCount = 1;
|
||||
shadowBinding.binding = 1;
|
||||
shadowBinding.binding = 2;
|
||||
shadowBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
shadowBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
const std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
|
||||
const std::array<VkDescriptorSetLayoutBinding, 3> bindings = {
|
||||
sceneBufferBinding,
|
||||
lightBufferBinding,
|
||||
shadowBinding
|
||||
};
|
||||
|
@ -275,7 +294,7 @@ void WorldPass::createPipeline() {
|
|||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPushConstantRange mvpPushConstant = {};
|
||||
mvpPushConstant.size = sizeof(glm::mat4) * 2;
|
||||
mvpPushConstant.size = sizeof(glm::mat4);
|
||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
||||
|
@ -313,10 +332,34 @@ void WorldPass::createPipeline() {
|
|||
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
|
||||
}
|
||||
|
||||
void WorldPass::createUniformBuffer() {
|
||||
void WorldPass::createUniformBuffers() {
|
||||
// scene
|
||||
{
|
||||
VkBufferCreateInfo bufferInfo = {};
|
||||
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.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
|
@ -332,6 +375,7 @@ void WorldPass::createUniformBuffer() {
|
|||
|
||||
vkAllocateMemory(renderer_.getDevice(), &allocInfo, nullptr, &lightMemory_);
|
||||
vkBindBufferMemory(renderer_.getDevice(), lightBuffer_, lightMemory_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldPass::createDescriptorSet() {
|
||||
|
@ -343,41 +387,54 @@ void WorldPass::createDescriptorSet() {
|
|||
|
||||
vkAllocateDescriptorSets(renderer_.getDevice(), &allocInfo, &descriptorSet_);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo = {};
|
||||
bufferInfo.buffer = lightBuffer_;
|
||||
bufferInfo.range = sizeof(float) * (4 + 3) * 32;
|
||||
VkDescriptorBufferInfo sceneBufferInfo = {};
|
||||
sceneBufferInfo.buffer = sceneBuffer_;
|
||||
sceneBufferInfo .range = sizeof(glm::mat4) * 2;
|
||||
|
||||
VkDescriptorBufferInfo lightBufferInfo = {};
|
||||
lightBufferInfo.buffer = lightBuffer_;
|
||||
lightBufferInfo.range = sizeof(float) * (8) * 32;
|
||||
|
||||
VkDescriptorImageInfo imageInfo = {};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.imageView = renderer_.getShadowPass().getImageView();
|
||||
imageInfo.sampler = renderer_.getShadowPass().getSampler();
|
||||
|
||||
VkWriteDescriptorSet bufferDescriptorWrite = {};
|
||||
bufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
bufferDescriptorWrite.descriptorCount = 1;
|
||||
bufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
bufferDescriptorWrite.dstSet = descriptorSet_;
|
||||
bufferDescriptorWrite.pBufferInfo = &bufferInfo;
|
||||
VkWriteDescriptorSet sceneBufferDescriptorWrite = {};
|
||||
sceneBufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
sceneBufferDescriptorWrite.descriptorCount = 1;
|
||||
sceneBufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
sceneBufferDescriptorWrite.dstSet = descriptorSet_;
|
||||
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 = {};
|
||||
shadowDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
shadowDescriptorWrite.descriptorCount = 1;
|
||||
shadowDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
shadowDescriptorWrite.dstBinding = 1;
|
||||
shadowDescriptorWrite.dstBinding = 2;
|
||||
shadowDescriptorWrite.dstSet = descriptorSet_;
|
||||
shadowDescriptorWrite.pImageInfo = &imageInfo;
|
||||
|
||||
const std::array<VkWriteDescriptorSet, 2> descriptorWrites = {
|
||||
bufferDescriptorWrite,
|
||||
const std::array<VkWriteDescriptorSet, 3> descriptorWrites = {
|
||||
sceneBufferDescriptorWrite,
|
||||
lightBufferDescriptorWrite,
|
||||
shadowDescriptorWrite
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
||||
|
||||
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;
|
||||
|
||||
vkUnmapMemory(renderer_.getDevice(), lightMemory_);
|
||||
|
|
Reference in a new issue