Archived
1
Fork 0

Add level editor

This commit is contained in:
Joshua Goins 2018-12-21 06:32:37 -05:00
parent 086c26265e
commit 707396f384
13 changed files with 263 additions and 48 deletions

View file

@ -44,8 +44,7 @@ IMPORTED_LOCATION ${ASSIMP_IMPORTED_PATH})
INTERFACE_INCLUDE_DIRECTORIES ${ASSIMP_INCLUDE_DIRS})
endif()
set(GRAPH_SRC
src/main.cpp
set(ENGINE_SRC
src/renderer.cpp
src/worldpass.cpp
src/postpass.cpp
@ -61,18 +60,17 @@ set(GRAPH_SRC
src/smaapass.cpp)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(GRAPH_SRC
${GRAPH_SRC}
set(ENGINE_SRC
${ENGINE_SRC}
src/imguipass.cpp)
endif()
add_executable(Graph
${GRAPH_SRC})
target_compile_options(Graph
add_library(Engine
${ENGINE_SRC})
target_compile_options(Engine
PUBLIC
-fno-exceptions)
target_link_libraries(Graph
target_link_libraries(Engine
PUBLIC
SDL2::SDL2
Vulkan::Vulkan
@ -82,17 +80,23 @@ target_link_libraries(Graph
SMAA::SMAA)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_libraries(Graph
target_link_libraries(Engine
PUBLIC
imgui::imgui)
endif()
target_include_directories(Graph
target_include_directories(Engine
PUBLIC
include
PRIVATE
${GLM_INCLUDE_DIRS})
add_executable(Graph
src/main.cpp)
target_link_libraries(Graph
PRIVATE
Engine)
add_shaders(Graph
shaders/mesh.vert
shaders/mesh.frag
@ -121,3 +125,5 @@ add_data(Graph
data/test.material
data/empty.world
data/player.obj)
add_subdirectory(tools)

View file

@ -30,7 +30,7 @@ enum class LightType {
struct LightComponent {
LightType type = LightType::Point;
glm::vec3 color = glm::vec3(1);
glm::mat4 matrix = glm::mat4(1.0f);
};
@ -45,28 +45,28 @@ using EntityID = uint64_t;
struct World;
namespace ECS {
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();
@ -81,10 +81,10 @@ namespace ECS {
} 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) {
@ -99,36 +99,36 @@ namespace ECS {
return cameras[id];
}
}
template<class T>
static inline auto getWorldComponents(World* world) {
static inline auto getWorldComponents(World* world) {
std::vector<EntityID> entities;
for (auto it = worlds.begin(); it != worlds.end(); ++it) {
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];

View file

@ -85,6 +85,9 @@ struct RenderTarget {
struct GraphicsConfig {
int shadowResolution, dofDownscale;
bool vsync = true, filterPCF;
#ifdef DEBUG
bool enableImgui = true;
#endif
};
struct World;

View file

@ -33,7 +33,8 @@ Renderer::Renderer(GraphicsConfig config) : config_(config) {
postPass_ = new PostPass(*this);
dofPass_ = new DoFPass(*this);
#ifdef DEBUG
imguiPass_ = new ImGuiPass(*this);
if(config.enableImgui)
imguiPass_ = new ImGuiPass(*this);
#endif
skyPass_ = new SkyPass(*this);
smaaPass_ = new SMAAPass(*this);
@ -45,7 +46,8 @@ Renderer::~Renderer() {
delete smaaPass_;
delete skyPass_;
#ifdef DEBUG
delete imguiPass_;
if(config_.enableImgui)
delete imguiPass_;
#endif
delete dofPass_;
delete postPass_;
@ -168,7 +170,8 @@ void Renderer::render(World& world, RenderTarget* target) {
postPass_->render(commandBuffer, target);
#ifdef DEBUG
imguiPass_->render(commandBuffer, target);
if(config_.enableImgui)
imguiPass_->render(commandBuffer, target);
#endif
vkCmdEndRenderPass(commandBuffer);
@ -729,6 +732,8 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
delete[] target->commandBuffers;
vkFreeDescriptorSets(device_, descriptorPool_, target->numImages, target->blendDescriptorSets);
vkFreeDescriptorSets(device_, descriptorPool_, target->numImages, target->edgeDescriptorSets);
vkFreeDescriptorSets(device_, descriptorPool_, target->numImages, target->dofSets);
vkFreeDescriptorSets(device_, descriptorPool_, target->numImages, target->postSets);
@ -799,6 +804,8 @@ void Renderer::destroyRenderTarget(RenderTarget* target) {
delete[] target->swapchainImageViews;
delete[] target->swapchainImages;
delete[] target->blendDescriptorSets;
delete[] target->edgeDescriptorSets;
delete[] target->dofSets;
delete[] target->postSets;
@ -1512,8 +1519,8 @@ void Renderer::createPresentationRenderPass() {
void Renderer::createDescriptorPool() {
const std::array<VkDescriptorPoolSize, 2> poolSizes = {
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 25},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 25}
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 50},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 50}
};
VkDescriptorPoolCreateInfo poolInfo = {};
@ -1521,7 +1528,7 @@ void Renderer::createDescriptorPool() {
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
poolInfo.poolSizeCount = poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = 25;
poolInfo.maxSets = 50;
vkCreateDescriptorPool(device_, &poolInfo, nullptr, &descriptorPool_);
}

View file

@ -62,8 +62,7 @@ void SMAAPass::render(VkCommandBuffer commandBuffer, RenderTarget* target) {
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = edgeRenderPass;
renderPassInfo.framebuffer = target->edgeFramebuffers[target->currentResource];
renderPassInfo.renderArea.extent.width = 1280;
renderPassInfo.renderArea.extent.height = 720;
renderPassInfo.renderArea.extent = target->extent;
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearValue;
@ -410,21 +409,10 @@ void SMAAPass::createPipelines() {
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkViewport viewport = {};
viewport.width = 1280;
viewport.height = 720;
viewport.maxDepth = 1.0f;
VkRect2D scissor = {};
scissor.extent.width = 1280;
scissor.extent.height = 720;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
@ -451,6 +439,16 @@ void SMAAPass::createPipelines() {
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
const std::array<VkDynamicState, 2> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = dynamicStates.size();
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
@ -468,6 +466,7 @@ void SMAAPass::createPipelines() {
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = edgePipelineLayout;
pipelineInfo.renderPass = edgeRenderPass;

1
tools/CMakeLists.txt Normal file
View file

@ -0,0 +1 @@
add_subdirectory(leveleditor)

View file

@ -0,0 +1,15 @@
find_package(Qt5Widgets CONFIG REQUIRED)
set(INCLUDE_FILES
include/mainwindow.h
include/renderwindow.h)
qt5_wrap_cpp(EDITOR_SRC ${INCLUDE_FILES})
add_executable(LevelEditor
src/main.cpp
src/mainwindow.cpp
src/renderwindow.cpp
${EDITOR_SRC})
target_include_directories(LevelEditor PRIVATE include)
target_link_libraries(LevelEditor Qt5::Widgets Engine)

View file

@ -0,0 +1,7 @@
#pragma once
class Renderer;
struct Context {
Renderer* renderer;
};

View file

@ -0,0 +1,10 @@
#pragma once
#include <QMainWindow>
struct Context;
class MainWindow : public QMainWindow {
public:
MainWindow(Context& context);
};

View file

@ -0,0 +1,29 @@
#pragma once
#include <QWindow>
#include <vulkan/vulkan.h>
#include "context.h"
struct RenderTarget;
class RendererWindow : public QWindow {
Q_OBJECT
public:
RendererWindow(Context& context);
~RendererWindow();
protected:
void exposeEvent(QExposeEvent* event) override;
bool event(QEvent* event) override;
private:
void init();
void render();
VkSurfaceKHR surface = nullptr;
RenderTarget* target = nullptr;
bool initialized = false;
Context& context;
};

View file

@ -0,0 +1,63 @@
#include <QApplication>
#include <QVulkanInstance>
#include "mainwindow.h"
#include "platform.h"
#include "context.h"
#include "renderer.h"
#include "worldmanager.h"
#include "assetmanager.h"
#include "ecs.h"
static std::vector<std::string> extensionList;
std::vector<const char*> platform::getRequiredExtensions() {
QVulkanInstance instance;
instance.create();
for(const auto& extension : instance.extensions())
extensionList.push_back(extension.data());
instance.destroy();
std::vector<const char*> extensions;
for(const auto& extension : extensionList)
extensions.push_back(extension.c_str());
return extensions;
}
uint32_t platform::getTime() {
return 0;
}
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
GraphicsConfig config;
config.shadowResolution = 256;
config.dofDownscale = 2;
config.filterPCF = true;
config.enableImgui = false;
Context context;
context.renderer = new Renderer(config);
assetManager.setRenderer(context.renderer);
worldManager.loadWorld("test.world");
worldManager.switchWorld("test.world");
EntityID entity = ECS::createEntity(worldManager.getCurrentWorld());
auto cameraTransform = ECS::addComponent<TransformComponent>(entity);
cameraTransform->position = glm::vec3(5, 5, 5);
auto cameraComponent = ECS::addComponent<CameraComponent>(entity);
cameraComponent->fov = 70.0f;
MainWindow window(context);
window.show();
return app.exec();
}

View file

@ -0,0 +1,20 @@
#include "mainwindow.h"
#include <QVulkanWindow>
#include "renderwindow.h"
#include "renderer.h"
MainWindow::MainWindow(Context& context) {
setWindowTitle("Level Editor");
QVulkanInstance* instance = new QVulkanInstance();
instance->setVkInstance(context.renderer->getInstance());
instance->create();
RendererWindow* window = new RendererWindow(context);
window->setVulkanInstance(instance);
QWidget* wrapper = QWidget::createWindowContainer(window);
setCentralWidget(wrapper);
}

View file

@ -0,0 +1,55 @@
#include "renderwindow.h"
#include <QVulkanInstance>
#include <QResizeEvent>
#include "renderer.h"
#include "worldmanager.h"
RendererWindow::RendererWindow(Context& context) : QWindow(), context(context) {
setSurfaceType(SurfaceType::VulkanSurface);
}
RendererWindow::~RendererWindow() {
}
void RendererWindow::exposeEvent(QExposeEvent*) {
if (isExposed() && !initialized) {
init();
render();
initialized = true;
}
}
bool RendererWindow::event(QEvent* event) {
switch(event->type()) {
case QEvent::UpdateRequest:
render();
break;
default:
break;
}
return QWindow::event(event);
}
void RendererWindow::init() {
surface = QVulkanInstance::surfaceForWindow(this);
target = context.renderer->createSurfaceRenderTarget(surface);
}
void RendererWindow::render() {
context.renderer->render(*worldManager.getCurrentWorld(), target);
const auto width = size().width();
const auto height = size().height();
if(target->extent.width != width || target->extent.height != height)
target = context.renderer->createSurfaceRenderTarget(surface, target);
vulkanInstance()->presentQueued(this);
requestUpdate();
}