Archived
1
Fork 0

Refactor object system to ECS

This commit is contained in:
Joshua Goins 2018-12-19 12:19:52 -05:00
parent d91c7d7221
commit 5b035874ab
33 changed files with 709 additions and 371 deletions

View file

@ -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

View file

@ -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"
}
} }

View file

@ -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": [
{ {

View file

@ -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"
}
} }

View file

@ -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;

View file

@ -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;
};

View file

@ -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;
}; };

View file

@ -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
View 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
View file

@ -0,0 +1,9 @@
#pragma once
#include <json.hpp>
#include "ecs.h"
struct World;
EntityID parseEntity(const nlohmann::json& json, World* world);

View file

@ -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);
};

View file

@ -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;

View file

@ -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;

View 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;
};

View file

@ -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_;

View file

@ -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_;

View file

@ -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();

View file

@ -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;
}; };

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;
} }

View file

@ -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);
} }

View file

@ -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());
} }

View file

@ -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);

View file

@ -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
View 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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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_);

View file

@ -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;
} }

View file

@ -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_);