begin changing style

This commit is contained in:
Bailey Harrison 2023-04-29 15:22:25 +01:00
parent 440ad2de82
commit c5b7a09e63
40 changed files with 1500 additions and 1428 deletions

3
README
View File

@ -1,3 +1,6 @@
a random game engine thing. Now finally with ECS!
Use the 'dev' branch for WIP.
Uses the google style guide:
https://google.github.io/styleguide/cppguide.html

View File

@ -1,3 +1,6 @@
#pragma once
#ifndef ENGINE_CONFIG_H_
#define ENGINE_CONFIG_H_
#define ENGINE_VERSION "@PROJECT_VERSION@"
#endif

View File

@ -1,59 +1,53 @@
#pragma once
#ifndef ENGINE_INCLUDE_APPLICATION_H_
#define ENGINE_INCLUDE_APPLICATION_H_
#include "resource_manager.hpp"
#include "gfx.hpp"
#include "gfx_device.hpp"
#include <assert.h>
#include <filesystem>
#include <memory>
#include <string>
#include <unordered_map>
#include <glm/mat4x4.hpp>
#include <memory>
#include <string>
#include <filesystem>
#include <unordered_map>
#include <assert.h>
#include "gfx.hpp"
#include "gfx_device.hpp"
#include "input_manager.hpp"
#include "resource_manager.hpp"
#include "scene_manager.hpp"
#include "window.hpp"
namespace engine {
class Window; // "window.hpp"
class GFXDevice; // "gfx_device.hpp"
class InputManager; // "input_manager.hpp"
class SceneManager; // "scene_manager.hpp"
namespace resources {
class Shader;
class Texture;
}
struct RenderData {
std::unique_ptr<GFXDevice> gfxdev;
gfx::DrawBuffer* drawBuffer = nullptr;
gfx::DrawBuffer* draw_buffer = nullptr;
/* uniforms for engine globals */
const gfx::DescriptorSetLayout* globalSetLayout;
const gfx::DescriptorSet* globalSet;
const gfx::DescriptorSetLayout* global_set_layout;
const gfx::DescriptorSet* global_set;
struct GlobalSetUniformBuffer {
glm::mat4 proj;
};
gfx::UniformBuffer* globalSetUniformBuffer;
gfx::UniformBuffer* global_set_uniform_buffer;
/* uniforms for per-frame data */
const gfx::DescriptorSetLayout* frameSetLayout;
const gfx::DescriptorSet* frameSet;
const gfx::DescriptorSetLayout* frame_set_layout;
const gfx::DescriptorSet* frame_set;
struct FrameSetUniformBuffer {
glm::mat4 view;
};
gfx::UniformBuffer* frameSetUniformBuffer;
gfx::UniformBuffer* frame_set_uniform_buffer;
/* this descriptor set is bound per-material */
const gfx::DescriptorSetLayout* materialSetLayout;
const gfx::DescriptorSetLayout* material_set_layout;
std::unordered_map<gfx::SamplerInfo, const gfx::Sampler*> samplers{};
};
class Application {
public:
Application(const char* appName, const char* appVersion, gfx::GraphicsSettings graphicsSettings);
Application(const char* app_name, const char* app_version,
gfx::GraphicsSettings graphics_settings);
~Application();
Application(const Application&) = delete;
Application& operator=(const Application&) = delete;
@ -61,69 +55,72 @@ namespace engine {
/* resource stuff */
template <typename T>
void registerResourceManager()
void RegisterResourceManager()
{
size_t hash = typeid(T).hash_code();
assert(m_resourceManagers.contains(hash) == false && "Registering resource manager type more than once.");
m_resourceManagers.emplace(hash, std::make_unique<ResourceManager<T>>());
assert(resource_managers_.contains(hash) == false &&
"Registering resource manager type more than once.");
resource_managers_.emplace(hash, std::make_unique<ResourceManager<T>>());
}
template <typename T>
std::shared_ptr<T> addResource(const std::string& name, std::unique_ptr<T>&& resource)
std::shared_ptr<T> AddResource(const std::string& name,
std::unique_ptr<T>&& resource)
{
auto resourceManager = getResourceManager<T>();
return resourceManager->add(name, std::move(resource));
auto resource_manager = GetResourceManager<T>();
return resource_manager->Add(name, std::move(resource));
}
template <typename T>
std::shared_ptr<T> getResource(const std::string& name)
std::shared_ptr<T> GetResource(const std::string& name)
{
auto resourceManager = getResourceManager<T>();
return resourceManager->get(name);
auto resource_manager = GetResourceManager<T>();
return resource_manager->Get(name);
}
/* methods */
void gameLoop();
void GameLoop();
void setFrameLimiter(bool on) { m_enableFrameLimiter = on; }
void SetFrameLimiter(bool on) { enable_frame_limiter_ = on; }
/* getters */
Window* window() { return m_window.get(); }
GFXDevice* gfx() { return renderData.gfxdev.get(); }
InputManager* inputManager() { return m_inputManager.get(); }
SceneManager* sceneManager() { return m_sceneManager.get(); }
Window* window() { return window_.get(); }
GFXDevice* gfxdev() { return render_data_.gfxdev.get(); }
InputManager* input_manager() { return input_manager_.get(); }
SceneManager* scene_manager() { return scene_manager_.get(); }
std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); }
std::string GetResourcePath(const std::string relative_path) {
return (resources_path_ / relative_path).string();
}
RenderData renderData{};
RenderData render_data_{};
private:
std::unique_ptr<Window> m_window;
std::unique_ptr<InputManager> m_inputManager;
std::unique_ptr<SceneManager> m_sceneManager;
std::unique_ptr<Window> window_;
std::unique_ptr<InputManager> input_manager_;
std::unique_ptr<SceneManager> scene_manager_;
std::unordered_map<size_t, std::unique_ptr<IResourceManager>>
resource_managers_{};
std::filesystem::path resources_path_;
std::filesystem::path m_resourcesPath;
bool m_enableFrameLimiter = true;
/* resource stuff */
std::unordered_map<size_t, std::unique_ptr<IResourceManager>> m_resourceManagers{};
bool enable_frame_limiter_ = true;
template <typename T>
ResourceManager<T>* getResourceManager()
ResourceManager<T>* GetResourceManager()
{
size_t hash = typeid(T).hash_code();
auto it = m_resourceManagers.find(hash);
if (it == m_resourceManagers.end()) {
auto it = resource_managers_.find(hash);
if (it == resource_managers_.end()) {
throw std::runtime_error("Cannot find resource manager.");
}
auto ptr = it->second.get();
auto castedPtr = dynamic_cast<ResourceManager<T>*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
auto casted_ptr = dynamic_cast<ResourceManager<T>*>(ptr);
assert(casted_ptr != nullptr);
return casted_ptr;
}
};
}
#endif

View File

@ -1,20 +1,18 @@
#pragma once
#ifndef ENGINE_INCLUDE_ECS_SYSTEM_H_
#define ENGINE_INCLUDE_ECS_SYSTEM_H_
#include <set>
#include <vector>
#include <map>
#include <string>
#include <bitset>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <assert.h>
#include <typeinfo>
#include <map>
#include <set>
namespace engine {
class Scene;
constexpr size_t MAX_COMPONENTS = 64;
constexpr size_t kMaxComponents = 64;
class IComponentArray {
public:
@ -25,49 +23,54 @@ namespace engine {
class ComponentArray : public IComponentArray {
public:
void insertData(uint32_t entity, T component)
void InsertData(uint32_t entity, T component)
{
assert(m_componentArray.find(entity) == m_componentArray.end() && "Adding component which already exists to entity");
m_componentArray.emplace(entity, component);
assert(component_array_.find(entity) == component_array_.end() &&
"Adding component which already exists to entity");
component_array_.emplace(entity, component);
}
void deleteData(uint32_t entity)
void DeleteData(uint32_t entity)
{
m_componentArray.erase(entity);
component_array_.erase(entity);
}
T* getData(uint32_t entity)
T* GetData(uint32_t entity)
{
if (m_componentArray.contains(entity)) {
return &(m_componentArray.at(entity));
if (component_array_.contains(entity)) {
return &(component_array_.at(entity));
} else {
return nullptr;
}
}
private:
std::map<uint32_t, T> m_componentArray{};
std::map<uint32_t, T> component_array_{};
};
class System {
public:
System(Scene* scene, std::set<size_t> requiredComponentHashes);
System(Scene* scene, std::set<size_t> required_component_hashes);
virtual ~System() {}
System(const System&) = delete;
System& operator=(const System&) = delete;
virtual void onUpdate(float ts) = 0;
virtual void OnUpdate(float ts) = 0;
virtual void onComponentInsert(uint32_t) {}
virtual void onComponentRemove(uint32_t) {}
virtual void OnComponentInsert(uint32_t) {}
virtual void OnComponentRemove(uint32_t) {}
Scene* const m_scene;
Scene* const scene_;
std::bitset<MAX_COMPONENTS> m_signature;
std::set<uint32_t> m_entities{}; // entities that contain the required components
std::bitset<kMaxComponents> signature_;
// entities that contain the needed components
std::set<uint32_t> entities_{};
};
}
} // namespace engine
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef ENGINE_INCLUDE_ENGINE_API_H_
#define ENGINE_INCLUDE_ENGINE_API_H_
/*
#ifndef ENGINE_API
@ -15,3 +16,5 @@
*/
#define ENGINE_API
#endif

View File

@ -1,30 +1,30 @@
#pragma once
#ifndef ENGINE_INCLUDE_EVENT_SYSTEM_H_
#define ENGINE_INCLUDE_EVENT_SYSTEM_H_
#include <cstddef>
#include <cstdint>
#include <memory>
#include <queue>
#include <unordered_map>
#include <memory>
#include <cstdlib>
#include <cassert>
#include <typeinfo>
namespace engine {
enum class EventSubscriberKind {
ENTITY,
kEntity,
};
// Event handler base-class
template <typename T>
class EventHandler {
public:
virtual void onEvent(T data) = 0;
virtual void OnEvent(T data) = 0;
};
// Event queue interface to allow for different type queues to be in the map
class IEventQueue {
public:
virtual ~IEventQueue() {}
virtual void dispatchEvents() = 0;
virtual void DespatchEvents() = 0;
};
template <typename T>
@ -32,34 +32,37 @@ namespace engine {
// holds events of type T and subscribers to those events
public:
void subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
void Subscribe(EventSubscriberKind kind, uint32_t id,
EventHandler<T>* handler)
{
// For the time being, ignore kind (TODO)
(void)kind;
assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
m_subscribers.emplace(id, handler);
assert(subscribers_.contains(id) == false &&
"subscribing to an event with ID that's already in use!");
subscribers_.emplace(id, handler);
}
void queueEvent(EventSubscriberKind kind, uint32_t id, T event)
void QueueEvent(EventSubscriberKind kind, uint32_t id, T event)
{
// For the time being, ignore kind (TODO)
(void)kind;
assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
EventHandler<T>* handler = m_subscribers.at(id);
m_eventQueue.emplace(handler, event);
assert(subscribers_.contains(id) &&
"Attempt to submit event to non-existing subscriber!");
EventHandler<T>* handler = subscribers_.at(id);
event_queue_.emplace(handler, event);
}
void dispatchEvents() override
void DespatchEvents() override
{
while (m_eventQueue.empty() == false) {
auto [handler, event] = m_eventQueue.front();
handler->onEvent(event);
m_eventQueue.pop();
while (event_queue_.empty() == false) {
auto [handler, event] = event_queue_.front();
handler->OnEvent(event);
event_queue_.pop();
}
}
private:
std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
std::unordered_map<uint32_t, EventHandler<T>*> subscribers_;
struct QueuedEvent {
@ -70,7 +73,7 @@ namespace engine {
EventHandler<T>* handler;
T event;
};
std::queue<QueuedEvent> m_eventQueue{};
std::queue<QueuedEvent> event_queue_{};
};
@ -83,43 +86,51 @@ namespace engine {
~EventSystem() {}
template <typename T>
void registerEventType()
void RegisterEventType()
{
size_t hash = typeid(T).hash_code();
assert(m_eventQueues.contains(hash) == false && "Registering an event queue more than once!");
m_eventQueues.emplace(hash, std::make_unique<EventQueue<T>>());
assert(event_queues_.contains(hash) == false &&
"Registering an event queue more than once!");
event_queues_.emplace(hash, std::make_unique<EventQueue<T>>());
}
template <typename T>
void subscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
void SubscribeToEventType(EventSubscriberKind kind, uint32_t id,
EventHandler<T>* handler)
{
size_t hash = typeid(T).hash_code();
assert(m_eventQueues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_eventQueues.at(hash).get());
assert(event_queues_.contains(hash) &&
"Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(
event_queues_.at(hash).get());
assert(queue != nullptr && "This cast should work?!! wot");
queue->subscribe(kind, id, handler);
queue->Subscribe(kind, id, handler);
}
template <typename T>
void queueEvent(EventSubscriberKind kind, uint32_t subscriberID, T event)
void QueueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
{
size_t hash = typeid(T).hash_code();
assert(m_eventQueues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_eventQueues.at(hash).get());
assert(event_queues_.contains(hash) &&
"Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(
event_queues_.at(hash).get());
assert(queue != nullptr && "This cast should work?!! wot");
queue->queueEvent(kind, subscriberID, event);
queue->QueueEvent(kind, subscriber_id, event);
}
void dispatchEvents()
void DespatchEvents()
{
for (auto& [hash, queue] : m_eventQueues) {
queue->dispatchEvents();
for (auto& [hash, queue] : event_queues_) {
queue->DespatchEvents();
}
}
private:
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> m_eventQueues{};
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> event_queues_{};
};
}
} // namespace engine
#endif

View File

@ -1,13 +1,15 @@
#pragma once
#ifndef ENGINE_INCLUDE_GFX_H_
#define ENGINE_INCLUDE_GFX_H_
#include <cstdint>
#include <vector>
#include <type_traits>
#include <functional>
#include <type_traits>
#include <vector>
// Enums and structs for the graphics abstraction
namespace engine::gfx {
namespace engine {
namespace gfx {
// handles (incomplete types)
struct Pipeline;
@ -20,11 +22,11 @@ namespace engine::gfx {
struct Sampler;
enum class MSAALevel {
MSAA_OFF,
MSAA_2X,
MSAA_4X,
MSAA_8X,
MSAA_16X,
kOff,
k2X,
k4X,
k8X,
k16X,
};
struct GraphicsSettings {
@ -32,65 +34,68 @@ namespace engine::gfx {
GraphicsSettings()
{
// sane defaults
enableValidation = true;
enable_validation = true;
vsync = true;
waitForPresent = true; // not all GPUs/drivers support immediate present with V-sync enabled
msaaLevel = MSAALevel::MSAA_OFF;
// not all GPUs/drivers support immediate present with V-sync enabled
wait_for_present = true;
msaa_level = MSAALevel::kOff;
}
bool enableValidation;
bool enable_validation;
bool vsync;
// idle CPU after render until the frame has been presented (no affect with V-sync disabled)
bool waitForPresent;
MSAALevel msaaLevel;
// idle CPU after render until the frame has been presented
// (no affect with V-sync disabled)
bool wait_for_present;
MSAALevel msaa_level;
};
enum class ShaderType {
VERTEX,
FRAGMENT,
kVertex,
kFragment,
};
enum class BufferType {
VERTEX,
INDEX,
UNIFORM,
kVertex,
kIndex,
kUniform,
};
enum class Primitive {
POINTS,
LINES,
LINE_STRIP,
TRIANGLES,
TRIANGLE_STRIP,
kPoints,
kLines,
kLineStrip,
kTriangles,
kTriangleStrip,
};
enum class VertexAttribFormat {
FLOAT2,
FLOAT3,
FLOAT4
kFloat2,
kFloat3,
kFloat4
};
enum class Filter : int {
LINEAR,
NEAREST,
kLinear,
kNearest,
};
enum class DescriptorType {
UNIFORM_BUFFER,
COMBINED_IMAGE_SAMPLER,
kUniformBuffer,
kCombinedImageSampler,
};
namespace ShaderStageFlags {
enum Bits : uint32_t {
VERTEX = 1 << 0,
FRAGMENT = 1 << 1,
kVertex = 1 << 0,
kFragment = 1 << 1,
};
typedef std::underlying_type<Bits>::type Flags;
}
struct VertexAttribDescription {
VertexAttribDescription(uint32_t location, VertexAttribFormat format, uint32_t offset) :
VertexAttribDescription(uint32_t location, VertexAttribFormat format,
uint32_t offset) :
location(location),
format(format),
offset(offset) {}
@ -101,33 +106,34 @@ namespace engine::gfx {
struct VertexFormat {
uint32_t stride;
std::vector<VertexAttribDescription> attributeDescriptions;
std::vector<VertexAttribDescription> attribute_descriptions;
};
struct PipelineInfo {
const char* vertShaderPath;
const char* fragShaderPath;
VertexFormat vertexFormat;
bool alphaBlending;
bool backfaceCulling;
std::vector<const DescriptorSetLayout*> descriptorSetLayouts;
const char* vert_shader_path;
const char* frag_shader_path;
VertexFormat vertex_format;
bool alpha_blending;
bool backface_culling;
std::vector<const DescriptorSetLayout*> descriptor_set_layouts;
};
struct DescriptorSetLayoutBinding {
DescriptorType descriptorType = DescriptorType::UNIFORM_BUFFER;
ShaderStageFlags::Flags stageFlags = 0;
DescriptorType descriptor_type = DescriptorType::kUniformBuffer;
ShaderStageFlags::Flags stage_flags = 0;
};
struct SamplerInfo {
Filter minify;
Filter magnify;
Filter mipmap;
bool anisotropicFiltering;
bool anisotropic_filtering;
bool operator==(const SamplerInfo&) const = default;
};
}
} // namespace gfx
} // namespace engine
namespace std {
template<>
@ -140,7 +146,7 @@ namespace std {
size_t h1 = hash<int>()(static_cast<int>(k.minify));
size_t h2 = hash<int>()(static_cast<int>(k.magnify));
size_t h3 = hash<int>()(static_cast<int>(k.mipmap));
size_t h4 = hash<bool>()(k.anisotropicFiltering);
size_t h4 = hash<bool>()(k.anisotropic_filtering);
return ((h1 & 0xFF) << 24) |
((h2 & 0xFF) << 16) |
@ -149,4 +155,6 @@ namespace std {
}
};
}
} // namespace std
#endif

View File

@ -1,71 +1,108 @@
#pragma once
#include "gfx.hpp"
#ifndef ENGINE_INCLUDE_GFX_DEVICE_H_
#define ENGINE_INCLUDE_GFX_DEVICE_H_
#include <memory>
#include "gfx.hpp"
struct SDL_Window; // <SDL_video.h>
namespace engine {
class GFXDevice {
public:
GFXDevice(const char* appName, const char* appVersion, SDL_Window* window, gfx::GraphicsSettings settings);
GFXDevice(const char* app_name, const char* app_version, SDL_Window* window,
gfx::GraphicsSettings settings);
GFXDevice(const GFXDevice&) = delete;
GFXDevice& operator=(const GFXDevice&) = delete;
~GFXDevice();
void getViewportSize(uint32_t *w, uint32_t *h);
void GetViewportSize(uint32_t* w, uint32_t* h);
gfx::DrawBuffer* beginRender();
void finishRender(gfx::DrawBuffer* drawBuffer);
gfx::DrawBuffer* BeginRender();
void cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline);
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
void cmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data);
void cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber);
void FinishRender(gfx::DrawBuffer* draw_buffer);
gfx::Pipeline* createPipeline(const gfx::PipelineInfo& info);
void destroyPipeline(const gfx::Pipeline* pipeline);
void CmdBindPipeline(gfx::DrawBuffer* draw_buffer,
const gfx::Pipeline* pipeline);
gfx::DescriptorSetLayout* createDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings);
void destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
void CmdBindVertexBuffer(gfx::DrawBuffer* draw_buffer, uint32_t binding,
const gfx::Buffer* buffer);
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
// This updates all copies of the descriptor. This cannot be used after any frames have been renderered
void updateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range);
void updateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler);
void CmdBindIndexBuffer(gfx::DrawBuffer* draw_buffer,
const gfx::Buffer* buffer);
gfx::UniformBuffer* createUniformBuffer(uint64_t size, const void* initialData);
void destroyUniformBuffer(const gfx::UniformBuffer* descriptorBuffer);
void CmdDrawIndexed(gfx::DrawBuffer* draw_buffer, uint32_t index_count,
uint32_t instance_count, uint32_t first_index,
int32_t vertex_offset, uint32_t first_instance);
void writeUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data);
void CmdPushConstants(gfx::DrawBuffer* draw_buffer,
const gfx::Pipeline* pipeline, uint32_t offset,
uint32_t size, const void* data);
void CmdBindDescriptorSet(gfx::DrawBuffer* draw_buffer,
const gfx::Pipeline* pipeline,
const gfx::DescriptorSet* set, uint32_t set_number);
gfx::Pipeline* CreatePipeline(const gfx::PipelineInfo& info);
void DestroyPipeline(const gfx::Pipeline* pipeline);
gfx::DescriptorSetLayout* CreateDescriptorSetLayout(
const std::vector<gfx::DescriptorSetLayoutBinding>& bindings);
void DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
gfx::DescriptorSet* AllocateDescriptorSet(
const gfx::DescriptorSetLayout* layout);
// This updates all copies of the descriptor.
// This cannot be used after any frames have been renderered
void UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set,
uint32_t binding,
const gfx::UniformBuffer* buffer,
size_t offset, size_t range);
void UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set,
uint32_t binding,
const gfx::Image* image,
const gfx::Sampler* sampler);
gfx::UniformBuffer* CreateUniformBuffer(uint64_t size,
const void* initial_data);
void DestroyUniformBuffer(const gfx::UniformBuffer* descriptor_buffer);
void WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset,
uint64_t size, const void* data);
// Loads data into staging buffer and copies that into a single GPU buffer.
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
void destroyBuffer(const gfx::Buffer* buffer);
gfx::Buffer* CreateBuffer(gfx::BufferType type, uint64_t size,
const void* data);
gfx::Image* createImage(uint32_t w, uint32_t h, const void* imageData);
void destroyImage(const gfx::Image* image);
void DestroyBuffer(const gfx::Buffer* buffer);
const gfx::Sampler* createSampler(const gfx::SamplerInfo& info);
void destroySampler(const gfx::Sampler* sampler);
gfx::Image* CreateImage(uint32_t w, uint32_t h, const void* image_data);
uint64_t getFrameCount();
void DestroyImage(const gfx::Image* image);
void logPerformanceInfo();
const gfx::Sampler* CreateSampler(const gfx::SamplerInfo& info);
void DestroySampler(const gfx::Sampler* sampler);
uint64_t GetFrameCount();
void LogPerformanceInfo();
// wait until all the active GPU queues have finished working
void waitIdle();
void WaitIdle();
private:
struct Impl;
std::unique_ptr<Impl> pimpl;
};
}
} // namespace engine
#endif

View File

@ -1,55 +1,93 @@
#pragma once
#ifndef ENGINE_INCLUDE_INPUT_MANAGER_H_
#define ENGINE_INCLUDE_INPUT_MANAGER_H_
#include "engine_api.h"
#include <array>
#include <string>
#include <vector>
#include "window.hpp"
#include "inputs/mouse.hpp"
#include "inputs/keyboard.hpp"
#include <vector>
#include <array>
#include <string>
namespace engine {
class Window; // "window.hpp"
enum class InputDevice : int {
MOUSE,
KEYBOARD,
CONTROLLER,
SIZE
kMouse,
kKeyboard,
kController,
kSize
};
// This class should be used to get platform/input-device independent input
class ENGINE_API InputManager {
class InputManager {
public:
// requires a window reference to get input from
InputManager(const Window* win);
/* The Window object here is stored for the duration of the InputManager.
* 'win' must point to a valid Window object. */
InputManager(const Window* win) : win_(win) {
assert(win != nullptr);
enabled_devices_.fill(true);
}
InputManager(const InputManager&) = delete;
InputManager& operator=(const InputManager&) = delete;
~InputManager();
// Add a mouse input
void addInputButton(const std::string& name, inputs::MouseButton button);
void addInputAxis(const std::string& name, inputs::MouseAxis axis);
void addInputButtonAsAxis(const std::string& name, inputs::MouseButton high, inputs::MouseButton low);
// Add a keyboard input
void addInputButton(const std::string& name, inputs::Key button);
void addInputButtonAsAxis(const std::string& name, inputs::Key high, inputs::Key low);
~InputManager() {}
void delInputButton(int index);
void delInputAxis(int index);
void AddInputButton(const std::string& name, inputs::MouseButton button) {
AddInputDeviceButton(name, InputDevice::kMouse,
static_cast<int>(button));
}
void setDeviceActive(enum InputDevice device, bool active);
bool getDeviceActive(enum InputDevice device) const;
void AddInputButton(const std::string& name, inputs::Key button) {
AddInputDeviceButton(name, InputDevice::kKeyboard,
static_cast<int>(button));
}
float getAxis(const std::string& axisName) const;
bool getButton(const std::string& buttonName) const;
bool getButtonPress(const std::string& buttonName) const;
bool getButtonRelease(const std::string& buttonName) const;
void AddInputAxis(const std::string& name, inputs::MouseAxis axis) {
AddInputDeviceAxis(name, InputDevice::kMouse, static_cast<int>(axis));
}
void AddInputButtonAsAxis(const std::string& name, inputs::MouseButton high,
inputs::MouseButton low) {
AddInputDeviceButtonAsAxis(name, InputDevice::kMouse,
static_cast<int>(high), static_cast<int>(low));
}
void AddInputButtonAsAxis(const std::string& name, inputs::Key high,
inputs::Key low) {
AddInputDeviceButtonAsAxis(name, InputDevice::kKeyboard,
static_cast<int>(high), static_cast<int>(low));
}
void DelInputButton(int index) {
std::vector<struct ButtonEntry>::iterator it = button_entries_.begin();
std::advance(it, index);
button_entries_.erase(it);
}
void DelInputAxis(int index) {
std::vector<struct AxisEntry>::iterator it = axis_entries_.begin();
std::advance(it, index);
axis_entries_.erase(it);
}
void SetDeviceActive(enum InputDevice device, bool active) {
enabled_devices_[static_cast<int>(device)] = active;
}
bool GetDeviceActive(enum InputDevice device) const {
return enabled_devices_[static_cast<int>(device)];
}
float GetAxis(const std::string& axis_name) const;
bool GetButton(const std::string& button_name) const;
bool GetButtonPress(const std::string& button_name) const;
bool GetButtonRelease(const std::string& button_name) const;
private:
@ -63,31 +101,54 @@ namespace engine {
std::string name;
enum InputDevice device;
int axis;
bool isButtonAxis;
bool is_button_axis;
int high;
int low;
};
const Window* const m_win;
const Window* win_;
std::vector<struct ButtonEntry> m_buttonEntries;
std::vector<struct AxisEntry> m_axisEntries;
std::vector<struct ButtonEntry> button_entries_;
std::vector<struct AxisEntry> axis_entries_;
std::array<bool, static_cast<int>(InputDevice::SIZE)> m_enabledDevices;
std::array<bool, static_cast<int>(InputDevice::kSize)> enabled_devices_;
// private methods
float getDeviceAxis(enum InputDevice device, int axis) const;
bool getDeviceButton(enum InputDevice device, int button) const;
float GetDeviceAxis(enum InputDevice device, int axis) const;
bool GetDeviceButton(enum InputDevice device, int button) const;
bool getDeviceButtonDown(enum InputDevice device, int button) const;
bool getDeviceButtonUp(enum InputDevice device, int button) const;
float getButtonAxis(enum InputDevice device, int high, int low) const;
bool GetDeviceButtonUp(enum InputDevice device, int button) const;
void addInputButton(const std::string& name, InputDevice device, int button);
void addInputAxis(const std::string& name, InputDevice device, int axis);
void addInputButtonAsAxis(const std::string& name, InputDevice device, int high, int low);
float GetButtonAxis(enum InputDevice device, int high, int low) const {
float value = 0.0f;
if (GetDeviceButton(device, high)) value += 1.0f;
if (low != 0) {
if (GetDeviceButton(device, low)) value += -1.0f;
}
return value;
}
void AddInputDeviceButton(const std::string& name, InputDevice device,
int button) {
button_entries_.push_back({ name, device, button });
}
void AddInputDeviceAxis(const std::string& name, InputDevice device,
int axis) {
axis_entries_.push_back({ name, device, axis, false, 0, 0 });
}
void AddInputDeviceButtonAsAxis(const std::string& name, InputDevice device,
int high, int low) {
axis_entries_.push_back({ name, device, 0, true, high, low });
}
};
}
} // namespace engine
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef ENGINE_INCLUDE_LOG_H_
#define ENGINE_INCLUDE_LOG_H_
#ifdef NDEBUG
#define SPDLOG_ACTIVE_LEVEL 2 // info
@ -14,3 +15,5 @@
#define LOG_WARN SPDLOG_WARN
#define LOG_ERROR SPDLOG_ERROR
#define LOG_CRITICAL SPDLOG_CRITICAL
#endif

View File

@ -1,4 +1,5 @@
#pragma once
#ifndef ENGINE_INCLUDE_LOGGER_H_
#define ENGINE_INCLUDE_LOGGER_H_
#include "log.hpp"
@ -11,14 +12,14 @@
namespace engine {
// To be executed in the target application, NOT engine.dll
void setupLog(const char* appName)
{
void SetupLog(const char* appName) {
const std::string LOG_FILENAME{ std::string(appName) + ".log"};
#ifdef NDEBUG
// RELEASE
const std::filesystem::path log_path{ std::filesystem::temp_directory_path() / LOG_FILENAME };
const std::filesystem::path log_path{
std::filesystem::temp_directory_path() / LOG_FILENAME};
#else
// DEBUG
const std::filesystem::path log_path{ LOG_FILENAME };
@ -26,15 +27,18 @@ namespace engine {
std::vector<spdlog::sink_ptr> sinks;
sinks.emplace_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_path.string(), true));
sinks.emplace_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(
log_path.string(), true));
sinks.back()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v");
sinks.emplace_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
sinks.back()->set_pattern("[%H:%M:%S.%e] [%l] %v");
auto logger = std::make_shared<spdlog::logger>(appName, sinks.begin(), sinks.end());
auto logger = std::make_shared<spdlog::logger>(appName, sinks.begin(),
sinks.end());
logger->set_level(spdlog::level::trace); // Logs below INFO are ignored through macros in release (see log.hpp)
// Logs below INFO are ignored through macros in release (see log.hpp)
logger->set_level(spdlog::level::trace);
spdlog::register_logger(logger);
spdlog::set_default_logger(logger);
@ -44,4 +48,6 @@ namespace engine {
}
}
} // namespace engine
#endif

View File

@ -1,10 +1,11 @@
#pragma once
#ifndef ENGINE_INCLUDE_RESOURCE_MANAGER_H_
#define ENGINE_INCLUDE_RESOURCE_MANAGER_H_
#include <unordered_map>
#include <vector>
#include <string>
#include <memory>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
namespace engine {
@ -17,31 +18,31 @@ namespace engine {
class ResourceManager : public IResourceManager {
public:
std::shared_ptr<T> add(const std::string& name, std::unique_ptr<T>&& resource)
std::shared_ptr<T> Add(const std::string& name, std::unique_ptr<T>&& resource)
{
if (m_resources.contains(name) == false) {
std::shared_ptr<T> resourceSharedPtr(std::move(resource));
m_resources.emplace(name, resourceSharedPtr);
return resourceSharedPtr;
if (resources_.contains(name) == false) {
std::shared_ptr<T> resource_shared(std::move(resource));
resources_.emplace(name, resource_shared);
return resource_shared;
}
else {
throw std::runtime_error("Cannot add a resource which already exists");
}
}
void addPersistent(const std::string& name, std::unique_ptr<T>&& resource)
void AddPersistent(const std::string& name, std::unique_ptr<T>&& resource)
{
m_persistentResources.push_back(add(name, std::move(resource)));
persistent_resources_.push_back(Add(name, std::move(resource)));
}
std::shared_ptr<T> get(const std::string& name)
std::shared_ptr<T> Get(const std::string& name)
{
if (m_resources.contains(name)) {
std::weak_ptr<T> ptr = m_resources.at(name);
if (resources_.contains(name)) {
std::weak_ptr<T> ptr = resources_.at(name);
if (ptr.expired() == false) {
return ptr.lock();
} else {
m_resources.erase(name);
resources_.erase(name);
}
}
// resource doesn't exist:
@ -50,9 +51,12 @@ namespace engine {
}
private:
std::unordered_map<std::string, std::weak_ptr<T>> m_resources{};
std::vector<std::shared_ptr<T>> m_persistentResources{}; // This array owns persistent resources
std::unordered_map<std::string, std::weak_ptr<T>> resources_{};
// This array owns persistent resources
std::vector<std::shared_ptr<T>> persistent_resources_{};
};
}
} // namespace engine
#endif

View File

@ -1,15 +1,14 @@
#pragma once
#ifndef ENGINE_INCLUDE_SCENE_H_
#define ENGINE_INCLUDE_SCENE_H_
#include "log.hpp"
#include <cassert>
#include <cstdint>
#include <map>
#include <typeinfo>
#include "ecs_system.hpp"
#include "event_system.hpp"
#include <map>
#include <cstdint>
#include <typeinfo>
#include <assert.h>
namespace engine {
class Application;
@ -22,119 +21,125 @@ namespace engine {
Scene& operator=(const Scene&) = delete;
~Scene();
void update(float ts);
void Update(float ts);
Application* app() { return m_app; }
Application* app() { return app_; }
EventSystem* events() { return m_eventSystem.get(); }
EventSystem* event_system() { return event_system_.get(); }
/* ecs stuff */
uint32_t createEntity(const std::string& tag, uint32_t parent = 0);
uint32_t CreateEntity(const std::string& tag, uint32_t parent = 0);
uint32_t getEntity(const std::string& tag, uint32_t parent = 0);
size_t getComponentSignaturePosition(size_t hash);
size_t GetComponentSignaturePosition(size_t hash);
template <typename T>
void registerComponent()
{
size_t hash = typeid(T).hash_code();
assert(m_componentArrays.contains(hash) == false && "Registering component type more than once.");
m_componentArrays.emplace(hash, std::make_unique<ComponentArray<T>>());
assert(component_arrays_.contains(hash) == false &&
"Registering component type more than once.");
component_arrays_.emplace(hash, std::make_unique<ComponentArray<T>>());
size_t componentSignaturePosition = m_nextSignaturePosition++;
assert(componentSignaturePosition < MAX_COMPONENTS && "Registering too many components!");
assert(m_componentSignaturePositions.contains(hash) == false);
m_componentSignaturePositions.emplace(hash, componentSignaturePosition);
size_t signature_position = next_signature_position_;
++next_signature_position_;
assert(signature_position < kMaxComponents &&
"Registering too many components!");
assert(component_signature_positions_.contains(hash) == false);
component_signature_positions_.emplace(hash, signature_position);
}
template <typename T>
T* getComponent(uint32_t entity)
T* GetComponent(uint32_t entity)
{
auto array = getComponentArray<T>();
return array->getData(entity);
auto array = GetComponentArray<T>();
return array->GetData(entity);
}
template <typename T>
T* addComponent(uint32_t entity)
T* AddComponent(uint32_t entity)
{
size_t hash = typeid(T).hash_code();
auto array = getComponentArray<T>();
array->insertData(entity, T{}); // errors if entity already exists in array
auto array = GetComponentArray<T>();
array->InsertData(entity, T{}); // errors if entity already exists in array
// set the component bit for this entity
size_t componentSignaturePosition = m_componentSignaturePositions.at(hash);
auto& signatureRef = m_signatures.at(entity);
signatureRef.set(componentSignaturePosition);
size_t signature_position = component_signature_positions_.at(hash);
auto& signature_ref = signatures_.at(entity);
signature_ref.set(signature_position);
for (auto& [systemName, system] : m_systems)
for (auto& [system_name, system] : systems_)
{
if (system->m_entities.contains(entity)) continue;
if ((system->m_signature & signatureRef) == system->m_signature) {
system->m_entities.insert(entity);
system->onComponentInsert(entity);
if (system->entities_.contains(entity)) continue;
if ((system->signature_ & signature_ref) == system->signature_) {
system->entities_.insert(entity);
system->OnComponentInsert(entity);
}
}
return array->getData(entity);
return array->GetData(entity);
}
template <typename T>
void registerSystem()
void RegisterSystem()
{
size_t hash = typeid(T).hash_code();
assert(m_systems.find(hash) == m_systems.end() && "Registering system more than once.");
m_systems.emplace(hash, std::make_unique<T>(this));
assert(systems_.find(hash) == systems_.end() &&
"Registering system more than once.");
systems_.emplace(hash, std::make_unique<T>(this));
}
template <typename T>
T* getSystem()
T* GetSystem()
{
size_t hash = typeid(T).hash_code();
auto it = m_systems.find(hash);
if (it == m_systems.end()) {
auto it = systems_.find(hash);
if (it == systems_.end()) {
throw std::runtime_error("Cannot find ecs system.");
}
auto ptr = it->second.get();
auto castedPtr = dynamic_cast<T*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
auto casted_ptr = dynamic_cast<T*>(ptr);
assert(casted_ptr != nullptr);
return casted_ptr;
}
private:
Application* const m_app;
uint32_t m_nextEntityID = 1000;
Application* const app_;
uint32_t next_entity_id_ = 1000;
/* ecs stuff */
size_t m_nextSignaturePosition = 0;
size_t next_signature_position_ = 0;
// maps component hashes to signature positions
std::map<size_t, size_t> m_componentSignaturePositions{};
std::map<size_t, size_t> component_signature_positions_{};
// maps entity ids to their signatures
std::map<uint32_t, std::bitset<MAX_COMPONENTS>> m_signatures{};
std::map<uint32_t, std::bitset<kMaxComponents>> signatures_{};
// maps component hashes to their arrays
std::map<size_t, std::unique_ptr<IComponentArray>> m_componentArrays{};
std::map<size_t, std::unique_ptr<IComponentArray>> component_arrays_{};
// maps system hashes to their class instantiations
std::map<size_t, std::unique_ptr<System>> m_systems{};
std::map<size_t, std::unique_ptr<System>> systems_{};
template <typename T>
ComponentArray<T>* getComponentArray()
ComponentArray<T>* GetComponentArray()
{
size_t hash = typeid(T).hash_code();
auto it = m_componentArrays.find(hash);
if (it == m_componentArrays.end()) {
auto it = component_arrays_.find(hash);
if (it == component_arrays_.end()) {
throw std::runtime_error("Cannot find component array.");
}
auto ptr = it->second.get();
auto castedPtr = dynamic_cast<ComponentArray<T>*>(ptr);
assert(castedPtr != nullptr);
return castedPtr;
auto casted_ptr = dynamic_cast<ComponentArray<T>*>(ptr);
assert(casted_ptr != nullptr);
return casted_ptr;
}
std::unique_ptr<EventSystem> m_eventSystem{};
std::unique_ptr<EventSystem> event_system_{};
};
}
} // namespace engine
#endif

View File

@ -1,14 +1,15 @@
#pragma once
#ifndef ENGINE_INCLUDE_SCENE_MANAGER_H_
#define ENGINE_INCLUDE_SCENE_MANAGER_H_
#include "resource_manager.hpp"
#include <vector>
#include <memory>
#include <vector>
#include "scene.hpp"
#include "resource_manager.hpp"
namespace engine {
class Application;
class Scene; // "scene.hpp"
class SceneManager {
@ -19,16 +20,18 @@ namespace engine {
SceneManager& operator=(const SceneManager&) = delete;
// creates an empty scene and sets it as active
Scene* createEmptyScene();
Scene* CreateEmptyScene();
void updateActiveScene(float ts);
void UpdateActiveScene(float ts);
private:
Application* const m_app;
Application* const app_;
std::vector<std::unique_ptr<Scene>> m_scenes;
int m_activeSceneIndex = -1;
std::vector<std::unique_ptr<Scene>> scenes_;
int active_scene_index_ = -1;
};
}
} // namespace engine
#endif

View File

@ -1,11 +1,13 @@
#pragma once
#include "ecs_system.hpp"
#include "components/collider.hpp"
#include <cstdint>
#include <vector>
#include <glm/mat4x4.hpp>
#include "components/collider.hpp"
#include "ecs_system.hpp"
namespace engine {
class PhysicsSystem : public System {
@ -13,9 +15,9 @@ namespace engine {
public:
PhysicsSystem(Scene* scene);
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
void onComponentInsert(uint32_t entity) override;
void OnComponentInsert(uint32_t entity) override;
struct CollisionEvent {
bool isCollisionEnter; // false == collision exit

View File

@ -18,7 +18,7 @@ namespace engine {
RenderSystem(Scene* scene);
~RenderSystem();
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
void setCameraEntity(uint32_t entity);

View File

@ -10,7 +10,7 @@ namespace engine {
Render2DSystem(Scene* scene);
~Render2DSystem();
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
private:

View File

@ -9,7 +9,7 @@ namespace engine {
public:
TransformSystem(Scene* scene);
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
uint32_t getChildEntity(uint32_t parent, const std::string& tag);

View File

@ -9,7 +9,7 @@ namespace engine {
public:
UISystem(Scene* scene);
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
private:

View File

@ -1,18 +1,22 @@
#pragma once
#ifndef ENGINE_INCLUDE_UTIL_H_
#define ENGINE_INCLUDE_UTIL_H_
#include <cstdio>
namespace engine {
inline bool versionFromCharArray(const char* version, int* major, int* minor, int* patch)
{
inline bool versionFromCharArray(const char* version, int* major, int* minor,
int* patch) {
if (sscanf(version, "%d.%d.%d", major, minor, patch) != 3) {
*major = 0;
*minor = 0;
*patch = 0;
return false;
}
} else {
return true;
}
}
} // namespace engine
#endif

View File

@ -1,23 +1,22 @@
#pragma once
#include "engine_api.h"
#include "inputs/keyboard.hpp"
#include "inputs/mouse.hpp"
#include <SDL.h>
#include <glm/vec2.hpp>
#ifndef ENGINE_INCLUDE_WINDOW_H_
#define ENGINE_INCLUDE_WINDOW_H_
#include <array>
#include <string>
#include <glm/vec2.hpp>
#include <SDL.h>
#include "inputs/keyboard.hpp"
#include "inputs/mouse.hpp"
namespace engine {
class ENGINE_API Window {
class Window {
public:
Window(const std::string& title, bool resizable = true, bool fullscreen = true);
Window(const std::string& title, bool resizable = true,
bool fullscreen = true);
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
~Window();
@ -52,7 +51,8 @@ namespace engine {
bool isFullscreen() const;
// Relative mouse mode captures the cursor for FPS style use. Returns false if unsupported.
// Relative mouse mode captures the cursor for FPS style use.
// Returns false if unsupported.
bool setRelativeMouseMode(bool enabled);
// returns true if relative mouse mode is enabled
@ -196,3 +196,5 @@ namespace engine {
};
}
#endif

View File

@ -1,28 +1,29 @@
#include "application.hpp"
#include "log.hpp"
#include "window.hpp"
#include "gfx_device.hpp"
#include "input_manager.hpp"
#include "scene_manager.hpp"
#include "scene.hpp"
#include "resources/mesh.hpp"
#include "resources/material.hpp"
#include "resources/shader.hpp"
#include "resources/texture.hpp"
#include <filesystem>
#include <memory>
#include <stdexcept>
#include <string>
#include <thread>
#include <glm/mat4x4.hpp>
// To allow the FPS-limiter to put the thread to sleep
#include <thread>
#include "gfx.hpp"
#include "gfx_device.hpp"
#include "input_manager.hpp"
#include "log.hpp"
#include "resources/material.hpp"
#include "resources/mesh.hpp"
#include "resources/shader.hpp"
#include "resources/texture.hpp"
#include "scene.hpp"
#include "scene_manager.hpp"
#include "window.hpp"
#ifdef _MSC_VER
#include <windows.h>
#include <direct.h>
#define MAX_PATH 260
#define WIN_MAX_PATH 260
#endif
namespace engine {
@ -33,7 +34,7 @@ namespace engine {
#ifdef _MSC_VER
CHAR exeDirBuf[MAX_PATH + 1];
GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1);
GetModuleFileNameA(NULL, exeDirBuf, WIN_MAX_PATH + 1);
std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path();
(void)_chdir((const char*)std::filesystem::absolute(cwd).c_str());
#else
@ -60,57 +61,57 @@ namespace engine {
Application::Application(const char* appName, const char* appVersion, gfx::GraphicsSettings graphicsSettings)
{
m_window = std::make_unique<Window>(appName, true, false);
m_inputManager = std::make_unique<InputManager>(window());
m_sceneManager = std::make_unique<SceneManager>(this);
window_ = std::make_unique<Window>(appName, true, false);
input_manager_ = std::make_unique<InputManager>(window_.get());
scene_manager_ = std::make_unique<SceneManager>(this);
// get base path for resources
m_resourcesPath = getResourcesPath();
resources_path_ = getResourcesPath();
// register resource managers
registerResourceManager<resources::Texture>();
registerResourceManager<resources::Shader>();
registerResourceManager<resources::Material>();
registerResourceManager<resources::Mesh>();
RegisterResourceManager<resources::Texture>();
RegisterResourceManager<resources::Shader>();
RegisterResourceManager<resources::Material>();
RegisterResourceManager<resources::Mesh>();
// initialise the render data
renderData.gfxdev = std::make_unique<GFXDevice>(appName, appVersion, m_window->getHandle(), graphicsSettings);
render_data_.gfxdev = std::make_unique<GFXDevice>(appName, appVersion, window_->getHandle(), graphicsSettings);
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
{
auto& binding0 = globalSetBindings.emplace_back();
binding0.descriptorType = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stageFlags = gfx::ShaderStageFlags::VERTEX;
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
}
renderData.globalSetLayout = gfx()->createDescriptorSetLayout(globalSetBindings);
renderData.globalSet = gfx()->allocateDescriptorSet(renderData.globalSetLayout);
render_data_.global_set_layout = gfxdev()->CreateDescriptorSetLayout(globalSetBindings);
render_data_.global_set = gfxdev()->AllocateDescriptorSet(render_data_.global_set_layout);
RenderData::GlobalSetUniformBuffer globalSetUniformBufferData{
.proj = glm::mat4{ 1.0f },
};
renderData.globalSetUniformBuffer = gfx()->createUniformBuffer(sizeof(RenderData::GlobalSetUniformBuffer), &globalSetUniformBufferData);
gfx()->updateDescriptorUniformBuffer(renderData.globalSet, 0, renderData.globalSetUniformBuffer, 0, sizeof(RenderData::GlobalSetUniformBuffer));
render_data_.global_set_uniform_buffer = gfxdev()->CreateUniformBuffer(sizeof(RenderData::GlobalSetUniformBuffer), &globalSetUniformBufferData);
gfxdev()->UpdateDescriptorUniformBuffer(render_data_.global_set, 0, render_data_.global_set_uniform_buffer, 0, sizeof(RenderData::GlobalSetUniformBuffer));
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
{
auto& binding0 = frameSetBindings.emplace_back();
binding0.descriptorType = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stageFlags = gfx::ShaderStageFlags::VERTEX;
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
}
renderData.frameSetLayout = gfx()->createDescriptorSetLayout(frameSetBindings);
renderData.frameSet = gfx()->allocateDescriptorSet(renderData.frameSetLayout);
render_data_.frame_set_layout = gfxdev()->CreateDescriptorSetLayout(frameSetBindings);
render_data_.frame_set = gfxdev()->AllocateDescriptorSet(render_data_.frame_set_layout);
RenderData::FrameSetUniformBuffer initialSetOneData{
.view = glm::mat4{ 1.0f },
};
renderData.frameSetUniformBuffer = gfx()->createUniformBuffer(sizeof(RenderData::FrameSetUniformBuffer), &initialSetOneData);
gfx()->updateDescriptorUniformBuffer(renderData.frameSet, 0, renderData.frameSetUniformBuffer, 0, sizeof(RenderData::FrameSetUniformBuffer));
render_data_.frame_set_uniform_buffer = gfxdev()->CreateUniformBuffer(sizeof(RenderData::FrameSetUniformBuffer), &initialSetOneData);
gfxdev()->UpdateDescriptorUniformBuffer(render_data_.frame_set, 0, render_data_.frame_set_uniform_buffer, 0, sizeof(RenderData::FrameSetUniformBuffer));
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
{
auto& binding0 = materialSetBindings.emplace_back();
binding0.descriptorType = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
binding0.stageFlags = gfx::ShaderStageFlags::FRAGMENT;
binding0.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
binding0.stage_flags = gfx::ShaderStageFlags::kFragment;
}
renderData.materialSetLayout = gfx()->createDescriptorSetLayout(materialSetBindings);
render_data_.material_set_layout = gfxdev()->CreateDescriptorSetLayout(materialSetBindings);
// default resources
{
@ -118,54 +119,54 @@ namespace engine {
vertParams.hasNormal = true;
vertParams.hasUV0 = true;
auto texturedShader = std::make_unique<resources::Shader>(
&renderData,
getResourcePath("engine/shaders/standard.vert").c_str(),
getResourcePath("engine/shaders/standard.frag").c_str(),
&render_data_,
GetResourcePath("engine/shaders/standard.vert").c_str(),
GetResourcePath("engine/shaders/standard.frag").c_str(),
vertParams,
false,
true
);
getResourceManager<resources::Shader>()->addPersistent("builtin.standard", std::move(texturedShader));
GetResourceManager<resources::Shader>()->AddPersistent("builtin.standard", std::move(texturedShader));
}
{
resources::Shader::VertexParams vertParams{};
vertParams.hasNormal = true;
vertParams.hasUV0 = true;
auto skyboxShader = std::make_unique<resources::Shader>(
&renderData,
getResourcePath("engine/shaders/skybox.vert").c_str(),
getResourcePath("engine/shaders/skybox.frag").c_str(),
&render_data_,
GetResourcePath("engine/shaders/skybox.vert").c_str(),
GetResourcePath("engine/shaders/skybox.frag").c_str(),
vertParams,
false,
true
);
getResourceManager<resources::Shader>()->addPersistent("builtin.skybox", std::move(skyboxShader));
GetResourceManager<resources::Shader>()->AddPersistent("builtin.skybox", std::move(skyboxShader));
}
{
auto whiteTexture = std::make_unique<resources::Texture>(
&renderData,
getResourcePath("engine/textures/white.png"),
&render_data_,
GetResourcePath("engine/textures/white.png"),
resources::Texture::Filtering::OFF
);
getResourceManager<resources::Texture>()->addPersistent("builtin.white", std::move(whiteTexture));
GetResourceManager<resources::Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
}
}
Application::~Application()
{
for (const auto& [info, sampler] : renderData.samplers) {
gfx()->destroySampler(sampler);
for (const auto& [info, sampler] : render_data_.samplers) {
gfxdev()->DestroySampler(sampler);
}
gfx()->destroyDescriptorSetLayout(renderData.materialSetLayout);
gfxdev()->DestroyDescriptorSetLayout(render_data_.material_set_layout);
gfx()->destroyUniformBuffer(renderData.frameSetUniformBuffer);
gfx()->destroyDescriptorSetLayout(renderData.frameSetLayout);
gfxdev()->DestroyUniformBuffer(render_data_.frame_set_uniform_buffer);
gfxdev()->DestroyDescriptorSetLayout(render_data_.frame_set_layout);
gfx()->destroyUniformBuffer(renderData.globalSetUniformBuffer);
gfx()->destroyDescriptorSetLayout(renderData.globalSetLayout);
gfxdev()->DestroyUniformBuffer(render_data_.global_set_uniform_buffer);
gfxdev()->DestroyDescriptorSetLayout(render_data_.global_set_layout);
}
void Application::gameLoop()
void Application::GameLoop()
{
LOG_TRACE("Begin game loop...");
@ -174,31 +175,31 @@ namespace engine {
auto beginFrame = std::chrono::steady_clock::now();
auto endFrame = beginFrame + FRAMETIME_LIMIT;
auto lastTick = m_window->getNanos();
auto lastTick = window_->getNanos();
// single-threaded game loop
while (m_window->isRunning()) {
while (window_->isRunning()) {
/* logic */
m_sceneManager->updateActiveScene(m_window->dt());
scene_manager_->UpdateActiveScene(window_->dt());
if(m_window->getKeyPress(inputs::Key::K_F)) [[unlikely]] {
m_window->infoBox("fps", std::to_string(m_window->getFPS()) + " fps " + std::to_string(m_window->dt() * 1000.0f) + " ms");
if(window_->getKeyPress(inputs::Key::K_F)) [[unlikely]] {
window_->infoBox("fps", std::to_string(window_->getFPS()) + " fps " + std::to_string(window_->dt() * 1000.0f) + " ms");
}
uint64_t now = m_window->getNanos();
uint64_t now = window_->getNanos();
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
lastTick = now;
LOG_INFO("fps: {}", m_window->getAvgFPS());
gfx()->logPerformanceInfo();
m_window->resetAvgFPS();
LOG_INFO("fps: {}", window_->getAvgFPS());
gfxdev()->LogPerformanceInfo();
window_->resetAvgFPS();
}
/* poll events */
m_window->getInputAndEvents();
window_->getInputAndEvents();
/* fps limiter */
if (m_enableFrameLimiter) {
if (enable_frame_limiter_) {
std::this_thread::sleep_until(endFrame);
}
beginFrame = endFrame;
@ -206,7 +207,7 @@ namespace engine {
}
gfx()->waitIdle();
gfxdev()->WaitIdle();
}
}

View File

@ -5,11 +5,11 @@
namespace engine {
System::System(Scene* scene, std::set<size_t> requiredComponentHashes)
: m_scene(scene)
: scene_(scene)
{
for (size_t componentHash : requiredComponentHashes) {
size_t componentSignaturePosition = m_scene->getComponentSignaturePosition(componentHash);
m_signature.set(componentSignaturePosition);
size_t componentSignaturePosition = scene_->GetComponentSignaturePosition(componentHash);
signature_.set(componentSignaturePosition);
}
}

View File

@ -130,11 +130,11 @@ namespace engine {
static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
{
switch (fmt) {
case gfx::VertexAttribFormat::FLOAT2:
case gfx::VertexAttribFormat::kFloat2:
return VK_FORMAT_R32G32_SFLOAT;
case gfx::VertexAttribFormat::FLOAT3:
case gfx::VertexAttribFormat::kFloat3:
return VK_FORMAT_R32G32B32_SFLOAT;
case gfx::VertexAttribFormat::FLOAT4:
case gfx::VertexAttribFormat::kFloat4:
return VK_FORMAT_R32G32B32A32_SFLOAT;
}
throw std::runtime_error("Unknown vertex attribute format");
@ -143,11 +143,11 @@ namespace engine {
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
{
switch (type) {
case gfx::BufferType::VERTEX:
case gfx::BufferType::kVertex:
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
case gfx::BufferType::INDEX:
case gfx::BufferType::kIndex:
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
case gfx::BufferType::UNIFORM:
case gfx::BufferType::kUniform:
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
default:
throw std::runtime_error("This buffer type does not have usage bits");
@ -157,9 +157,9 @@ namespace engine {
[[maybe_unused]] static VkFilter getFilter(gfx::Filter filter)
{
switch (filter) {
case gfx::Filter::LINEAR:
case gfx::Filter::kLinear:
return VK_FILTER_LINEAR;
case gfx::Filter::NEAREST:
case gfx::Filter::kNearest:
return VK_FILTER_NEAREST;
}
throw std::runtime_error("Unknown filter");
@ -168,9 +168,9 @@ namespace engine {
[[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter)
{
switch (filter) {
case gfx::Filter::LINEAR:
case gfx::Filter::kLinear:
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
case gfx::Filter::NEAREST:
case gfx::Filter::kNearest:
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
}
throw std::runtime_error("Unknown filter");
@ -179,15 +179,15 @@ namespace engine {
[[maybe_unused]] static VkSampleCountFlags getSampleCountFlags(gfx::MSAALevel level)
{
switch (level) {
case gfx::MSAALevel::MSAA_OFF:
case gfx::MSAALevel::kOff:
return VK_SAMPLE_COUNT_1_BIT;
case gfx::MSAALevel::MSAA_2X:
case gfx::MSAALevel::k2X:
return VK_SAMPLE_COUNT_2_BIT;
case gfx::MSAALevel::MSAA_4X:
case gfx::MSAALevel::k4X:
return VK_SAMPLE_COUNT_4_BIT;
case gfx::MSAALevel::MSAA_8X:
case gfx::MSAALevel::k8X:
return VK_SAMPLE_COUNT_8_BIT;
case gfx::MSAALevel::MSAA_16X:
case gfx::MSAALevel::k16X:
return VK_SAMPLE_COUNT_16_BIT;
default:
throw std::runtime_error("Unknown MSAA level");
@ -197,9 +197,9 @@ namespace engine {
static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
{
switch (type) {
case gfx::DescriptorType::UNIFORM_BUFFER:
case gfx::DescriptorType::kUniformBuffer:
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case gfx::DescriptorType::COMBINED_IMAGE_SAMPLER:
case gfx::DescriptorType::kCombinedImageSampler:
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
default:
throw std::runtime_error("Unknown descriptor type");
@ -209,8 +209,8 @@ namespace engine {
static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags)
{
VkShaderStageFlags out = 0;
if (flags & gfx::ShaderStageFlags::VERTEX) out |= VK_SHADER_STAGE_VERTEX_BIT;
if (flags & gfx::ShaderStageFlags::FRAGMENT) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
if (flags & gfx::ShaderStageFlags::kVertex) out |= VK_SHADER_STAGE_VERTEX_BIT;
if (flags & gfx::ShaderStageFlags::kFragment) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
return out;
}
@ -365,7 +365,7 @@ namespace engine {
throw std::runtime_error("The loaded Vulkan version must be at least 1.3");
}
pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion, pimpl->graphicsSettings.enableValidation, MessageSeverity::SEV_WARNING);
pimpl->instance = createVulkanInstance(pimpl->window, appName, appVersion, pimpl->graphicsSettings.enable_validation, MessageSeverity::SEV_WARNING);
if (SDL_Vulkan_CreateSurface(pimpl->window, pimpl->instance.instance, &pimpl->surface) == false) {
throw std::runtime_error("Unable to create window surface");
@ -440,7 +440,7 @@ namespace engine {
pimpl->swapchainInfo.surface = pimpl->surface;
pimpl->swapchainInfo.window = pimpl->window;
pimpl->swapchainInfo.vsync = pimpl->graphicsSettings.vsync;
pimpl->swapchainInfo.waitForPresent = pimpl->graphicsSettings.waitForPresent;
pimpl->swapchainInfo.waitForPresent = pimpl->graphicsSettings.wait_for_present;
createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo);
/* make synchronisation primitives for rendering and allocate command buffers */
@ -541,7 +541,7 @@ namespace engine {
destroyVulkanInstance(pimpl->instance);
}
void GFXDevice::getViewportSize(uint32_t* w, uint32_t* h)
void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
{
int width, height;
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
@ -555,7 +555,7 @@ namespace engine {
}
}
gfx::DrawBuffer* GFXDevice::beginRender()
gfx::DrawBuffer* GFXDevice::BeginRender()
{
VkResult res;
@ -724,7 +724,7 @@ namespace engine {
}
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
{
assert(drawBuffer != nullptr);
@ -785,68 +785,68 @@ namespace engine {
delete drawBuffer;
}
void GFXDevice::cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
void GFXDevice::CmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
{
assert(drawBuffer != nullptr);
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
}
void GFXDevice::cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
void GFXDevice::CmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
{
assert(drawBuffer != nullptr);
assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::VERTEX);
assert(buffer->type == gfx::BufferType::kVertex);
const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset);
}
void GFXDevice::cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
void GFXDevice::CmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
{
assert(drawBuffer != nullptr);
assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::INDEX);
assert(buffer->type == gfx::BufferType::kIndex);
vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE);
}
void GFXDevice::cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
void GFXDevice::CmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance)
{
assert(drawBuffer != nullptr);
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
void GFXDevice::cmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data)
void GFXDevice::CmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data)
{
assert(drawBuffer != nullptr);
vkCmdPushConstants(drawBuffer->frameData.drawBuf, pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, offset, size, data);
}
void GFXDevice::cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
void GFXDevice::CmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
{
vkCmdBindDescriptorSets(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, setNumber, 1, &set->sets[drawBuffer->currentFrameIndex], 0, nullptr);
}
gfx::Pipeline* GFXDevice::createPipeline(const gfx::PipelineInfo& info)
gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
{
[[maybe_unused]] VkResult res;
gfx::Pipeline* pipeline = new gfx::Pipeline;
auto vertShaderCode = util::readTextFile(info.vertShaderPath);
auto fragShaderCode = util::readTextFile(info.fragShaderPath);
auto vertShaderCode = util::readTextFile(info.vert_shader_path);
auto fragShaderCode = util::readTextFile(info.frag_shader_path);
VkShaderModule vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vertShaderPath);
VkShaderModule fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.fragShaderPath);
VkShaderModule vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vert_shader_path);
VkShaderModule fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.frag_shader_path);
// get vertex attrib layout:
VkVertexInputBindingDescription bindingDescription{ };
bindingDescription.binding = 0;
bindingDescription.stride = info.vertexFormat.stride;
bindingDescription.stride = info.vertex_format.stride;
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
std::vector<VkVertexInputAttributeDescription> attribDescs{};
attribDescs.reserve(info.vertexFormat.attributeDescriptions.size());
for (const auto& desc : info.vertexFormat.attributeDescriptions) {
attribDescs.reserve(info.vertex_format.attribute_descriptions.size());
for (const auto& desc : info.vertex_format.attribute_descriptions) {
VkVertexInputAttributeDescription vulkanAttribDesc{};
vulkanAttribDesc.location = desc.location;
vulkanAttribDesc.binding = 0;
@ -920,7 +920,7 @@ namespace engine {
rasterizer.rasterizerDiscardEnable = VK_FALSE; // enabling this will not run the fragment shaders at all
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
if (info.backfaceCulling == true) {
if (info.backface_culling == true) {
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
}
else {
@ -947,7 +947,7 @@ namespace engine {
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT;
if (info.alphaBlending) {
if (info.alpha_blending) {
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
@ -988,9 +988,9 @@ namespace engine {
pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE;
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
std::vector<VkDescriptorSetLayout> descriptorSetLayouts(info.descriptorSetLayouts.size());
std::vector<VkDescriptorSetLayout> descriptorSetLayouts(info.descriptor_set_layouts.size());
for (size_t i = 0; i < descriptorSetLayouts.size(); i++) {
descriptorSetLayouts[i] = info.descriptorSetLayouts[i]->layout;
descriptorSetLayouts[i] = info.descriptor_set_layouts[i]->layout;
}
VkPipelineLayoutCreateInfo layoutInfo{};
@ -1031,7 +1031,7 @@ namespace engine {
}
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline)
{
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
vkDestroyPipelineLayout(pimpl->device.device, pipeline->layout, nullptr);
@ -1039,7 +1039,7 @@ namespace engine {
delete pipeline;
}
gfx::DescriptorSetLayout* GFXDevice::createDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings)
gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings)
{
gfx::DescriptorSetLayout* out = new gfx::DescriptorSetLayout{};
@ -1048,9 +1048,9 @@ namespace engine {
for (const auto& binding : bindings) {
auto& vulkanBinding = vulkanBindings.emplace_back();
vulkanBinding.binding = i; // This should be as low as possible to avoid wasting memory
vulkanBinding.descriptorType = converters::getDescriptorType(binding.descriptorType);
vulkanBinding.descriptorType = converters::getDescriptorType(binding.descriptor_type);
vulkanBinding.descriptorCount = 1; // if > 1, accessible as an array in the shader
vulkanBinding.stageFlags = converters::getShaderStageFlags(binding.stageFlags);
vulkanBinding.stageFlags = converters::getShaderStageFlags(binding.stage_flags);
++i;
}
@ -1066,13 +1066,13 @@ namespace engine {
return out;
}
void GFXDevice::destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
void GFXDevice::DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
{
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
delete layout;
}
gfx::DescriptorSet* GFXDevice::allocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
{
gfx::DescriptorSet* set = new gfx::DescriptorSet{};
@ -1094,7 +1094,7 @@ namespace engine {
return set;
}
void GFXDevice::updateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range)
void GFXDevice::UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range)
{
assert(pimpl->FRAMECOUNT == 0);
@ -1120,7 +1120,7 @@ namespace engine {
}
}
void GFXDevice::updateDescriptorCombinedImageSampler(const gfx::DescriptorSet *set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler)
void GFXDevice::UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet *set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler)
{
assert(pimpl->FRAMECOUNT == 0);
@ -1146,13 +1146,13 @@ namespace engine {
}
}
gfx::UniformBuffer* GFXDevice::createUniformBuffer(uint64_t size, const void* initialData)
gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* initialData)
{
gfx::UniformBuffer* out = new gfx::UniformBuffer{};
/* first make staging buffer */
out->stagingBuffer.size = size;
out->stagingBuffer.type = gfx::BufferType::UNIFORM;
out->stagingBuffer.type = gfx::BufferType::kUniform;
{
VkBufferCreateInfo stagingBufferInfo{};
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@ -1177,7 +1177,7 @@ namespace engine {
/* create the device-local set of buffers */
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
out->gpuBuffers[i].size = out->stagingBuffer.size;
out->gpuBuffers[i].type = gfx::BufferType::UNIFORM;
out->gpuBuffers[i].type = gfx::BufferType::kUniform;
VkBufferCreateInfo gpuBufferInfo{};
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@ -1200,7 +1200,7 @@ namespace engine {
}
void GFXDevice::destroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
{
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
vmaDestroyBuffer(pimpl->allocator, uniformBuffer->gpuBuffers[i].buffer, uniformBuffer->gpuBuffers[i].allocation);
@ -1211,7 +1211,7 @@ namespace engine {
delete uniformBuffer;
}
void GFXDevice::writeUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data)
void GFXDevice::WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data)
{
assert(offset + size <= buffer->stagingBuffer.size);
@ -1229,7 +1229,7 @@ namespace engine {
}
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
gfx::Buffer* GFXDevice::CreateBuffer(gfx::BufferType type, uint64_t size, const void* data)
{
[[maybe_unused]] VkResult res;
@ -1287,14 +1287,14 @@ namespace engine {
}
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
{
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
delete buffer;
}
// imageData must have pixel format R8G8B8A8_SRGB
gfx::Image* GFXDevice::createImage(uint32_t w, uint32_t h, const void* imageData)
gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, const void* imageData)
{
assert(imageData != nullptr);
assert(pimpl->FRAMECOUNT == 0);
@ -1541,14 +1541,14 @@ namespace engine {
return out;
}
void GFXDevice::destroyImage(const gfx::Image *image)
void GFXDevice::DestroyImage(const gfx::Image *image)
{
vkDestroyImageView(pimpl->device.device, image->view, nullptr);
vmaDestroyImage(pimpl->allocator, image->image, image->allocation);
delete image;
}
const gfx::Sampler *GFXDevice::createSampler(const gfx::SamplerInfo& info)
const gfx::Sampler *GFXDevice::CreateSampler(const gfx::SamplerInfo& info)
{
gfx::Sampler* out = new gfx::Sampler{};
@ -1561,7 +1561,7 @@ namespace engine {
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.anisotropyEnable = info.anisotropicFiltering ? VK_TRUE : VK_FALSE;
samplerInfo.anisotropyEnable = info.anisotropic_filtering ? VK_TRUE : VK_FALSE;
samplerInfo.maxAnisotropy = pimpl->device.properties.limits.maxSamplerAnisotropy;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
@ -1571,13 +1571,13 @@ namespace engine {
return out;
}
void GFXDevice::destroySampler(const gfx::Sampler *sampler)
void GFXDevice::DestroySampler(const gfx::Sampler *sampler)
{
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
delete sampler;
}
void GFXDevice::logPerformanceInfo()
void GFXDevice::LogPerformanceInfo()
{
VmaTotalStatistics pStats{};
vmaCalculateStatistics(pimpl->allocator, &pStats);
@ -1601,12 +1601,12 @@ namespace engine {
}
}
uint64_t GFXDevice::getFrameCount()
uint64_t GFXDevice::GetFrameCount()
{
return pimpl->FRAMECOUNT;
}
void GFXDevice::waitIdle()
void GFXDevice::WaitIdle()
{
vkDeviceWaitIdle(pimpl->device.device);
}

View File

@ -7,170 +7,16 @@
namespace engine {
InputManager::InputManager(const Window* win) : m_win(win)
float InputManager::GetAxis(const std::string& axis_name) const
{
m_enabledDevices.fill(true);
}
InputManager::~InputManager() {}
/* private methods */
float InputManager::getDeviceAxis(enum InputDevice device, int axis) const
{
switch (device) {
case InputDevice::MOUSE:
switch (static_cast<inputs::MouseAxis>(axis)) {
case inputs::MouseAxis::X:
return static_cast<float>(m_win->getMouseDX());
case inputs::MouseAxis::Y:
return static_cast<float>(m_win->getMouseDY());
case inputs::MouseAxis::X_SCR:
return m_win->getMouseScrollX();
case inputs::MouseAxis::Y_SCR:
return m_win->getMouseScrollY();
default: break;
}
break;
case InputDevice::KEYBOARD:
break;
case InputDevice::CONTROLLER:
break;
default: break;
}
throw std::runtime_error("Error getting device axis");
}
bool InputManager::getDeviceButton(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::MOUSE:
return m_win->getButton(static_cast<inputs::MouseButton>(button));
case InputDevice::KEYBOARD:
return m_win->getKey(static_cast<inputs::Key>(button));
case InputDevice::CONTROLLER:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
bool InputManager::getDeviceButtonDown(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::MOUSE:
return m_win->getButtonPress(static_cast<enum inputs::MouseButton>(button));
case InputDevice::KEYBOARD:
return m_win->getKeyPress(static_cast<enum inputs::Key>(button));
case InputDevice::CONTROLLER:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
bool InputManager::getDeviceButtonUp(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::MOUSE:
return m_win->getButtonRelease(static_cast<enum inputs::MouseButton>(button));
case InputDevice::KEYBOARD:
return m_win->getKeyRelease(static_cast<enum inputs::Key>(button));
case InputDevice::CONTROLLER:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
float InputManager::getButtonAxis(enum InputDevice device, int high, int low) const
{
float value = 0.0f;
if (getDeviceButton(device, high)) value += 1.0f;
if (low != 0) {
if (getDeviceButton(device, low)) value += -1.0f;
}
return value;
}
// public methods
void InputManager::addInputButton(const std::string& name, InputDevice device, int button)
{
m_buttonEntries.push_back({ name, device, button });
}
void InputManager::addInputAxis(const std::string& name, InputDevice device, int axis)
{
m_axisEntries.push_back({ name, device, axis, false, 0, 0 });
}
void InputManager::addInputButtonAsAxis(const std::string& name, InputDevice device, int high, int low)
{
m_axisEntries.push_back({ name, device, 0, true, high, low });
}
// OVERLOADS:
void InputManager::addInputButton(const std::string& name, inputs::MouseButton button)
{
addInputButton(name, InputDevice::MOUSE, static_cast<int>(button));
}
void InputManager::addInputAxis(const std::string& name, inputs::MouseAxis axis)
{
addInputAxis(name, InputDevice::MOUSE, static_cast<int>(axis));
}
void InputManager::addInputButtonAsAxis(const std::string& name, inputs::MouseButton high, inputs::MouseButton low)
{
addInputButtonAsAxis(name, InputDevice::MOUSE, static_cast<int>(high), static_cast<int>(low));
}
void InputManager::addInputButton(const std::string& name, inputs::Key button)
{
addInputButton(name, InputDevice::KEYBOARD, static_cast<int>(button));
}
void InputManager::addInputButtonAsAxis(const std::string& name, inputs::Key high, inputs::Key low)
{
addInputButtonAsAxis(name, InputDevice::KEYBOARD, static_cast<int>(high), static_cast<int>(low));
}
void InputManager::delInputButton(int index)
{
std::vector<struct ButtonEntry>::iterator it = m_buttonEntries.begin();
std::advance(it, index);
m_buttonEntries.erase(it);
}
void InputManager::delInputAxis(int index)
{
std::vector<struct AxisEntry>::iterator it = m_axisEntries.begin();
std::advance(it, index);
m_axisEntries.erase(it);
}
void InputManager::setDeviceActive(enum InputDevice device, bool active)
{
m_enabledDevices[static_cast<int>(device)] = active;
}
bool InputManager::getDeviceActive(enum InputDevice device) const
{
return m_enabledDevices[static_cast<int>(device)];
}
float InputManager::getAxis(const std::string& axisName) const
{
for (const AxisEntry& e : m_axisEntries) {
if (e.name == axisName) {
if (m_enabledDevices[static_cast<int>(e.device)]) {
if (e.isButtonAxis) {
return getButtonAxis(e.device, e.high, e.low);
for (const AxisEntry& e : axis_entries_) {
if (e.name == axis_name) {
if (enabled_devices_[static_cast<int>(e.device)]) {
if (e.is_button_axis) {
return GetButtonAxis(e.device, e.high, e.low);
}
else {
return getDeviceAxis(e.device, e.axis);
return GetDeviceAxis(e.device, e.axis);
}
}
}
@ -178,14 +24,14 @@ namespace engine {
return 0.0f; // instead of throwing an exception, just return nothing
}
bool InputManager::getButton(const std::string& buttonName) const
bool InputManager::GetButton(const std::string& buttonName) const
{
bool isDown = false;
for (const ButtonEntry& e : m_buttonEntries) {
for (const ButtonEntry& e : button_entries_) {
if (e.name == buttonName) {
if (m_enabledDevices[static_cast<int>(e.device)]) {
if (getDeviceButton(e.device, e.button) == true) {
if (enabled_devices_[static_cast<int>(e.device)]) {
if (GetDeviceButton(e.device, e.button) == true) {
isDown = true;
break;
}
@ -195,13 +41,13 @@ namespace engine {
return isDown;
}
bool InputManager::getButtonPress(const std::string& buttonName) const
bool InputManager::GetButtonPress(const std::string& buttonName) const
{
bool isPressed = false;
for (const ButtonEntry& e : m_buttonEntries) {
for (const ButtonEntry& e : button_entries_) {
if (e.name == buttonName) {
if (m_enabledDevices[static_cast<int>(e.device)]) {
if (enabled_devices_[static_cast<int>(e.device)]) {
if (getDeviceButtonDown(e.device, e.button) == true) {
isPressed = true;
break;
@ -212,14 +58,14 @@ namespace engine {
return isPressed;
}
bool InputManager::getButtonRelease(const std::string& buttonName) const
bool InputManager::GetButtonRelease(const std::string& buttonName) const
{
bool isReleased = false;
for (const ButtonEntry& e : m_buttonEntries) {
for (const ButtonEntry& e : button_entries_) {
if (e.name == buttonName) {
if (m_enabledDevices[static_cast<int>(e.device)]) {
if (getDeviceButtonUp(e.device, e.button) == true) {
if (enabled_devices_[static_cast<int>(e.device)]) {
if (GetDeviceButtonUp(e.device, e.button) == true) {
isReleased = true;
break;
}
@ -229,4 +75,72 @@ namespace engine {
return isReleased;
}
float InputManager::GetDeviceAxis(enum InputDevice device, int axis) const
{
switch (device) {
case InputDevice::kMouse:
switch (static_cast<inputs::MouseAxis>(axis)) {
case inputs::MouseAxis::X:
return static_cast<float>(win_->getMouseDX());
case inputs::MouseAxis::Y:
return static_cast<float>(win_->getMouseDY());
case inputs::MouseAxis::X_SCR:
return win_->getMouseScrollX();
case inputs::MouseAxis::Y_SCR:
return win_->getMouseScrollY();
default: break;
}
break;
case InputDevice::kKeyboard:
break;
case InputDevice::kController:
break;
default: break;
}
throw std::runtime_error("Error getting device axis");
}
bool InputManager::GetDeviceButton(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::kMouse:
return win_->getButton(static_cast<inputs::MouseButton>(button));
case InputDevice::kKeyboard:
return win_->getKey(static_cast<inputs::Key>(button));
case InputDevice::kController:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
bool InputManager::getDeviceButtonDown(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::kMouse:
return win_->getButtonPress(static_cast<enum inputs::MouseButton>(button));
case InputDevice::kKeyboard:
return win_->getKeyPress(static_cast<enum inputs::Key>(button));
case InputDevice::kController:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
bool InputManager::GetDeviceButtonUp(enum InputDevice device, int button) const
{
switch (device) {
case InputDevice::kMouse:
return win_->getButtonRelease(static_cast<enum inputs::MouseButton>(button));
case InputDevice::kKeyboard:
return win_->getKeyRelease(static_cast<enum inputs::Key>(button));
case InputDevice::kController:
break;
default: break;
}
throw std::runtime_error("Error getting device button");
}
}

View File

@ -17,8 +17,8 @@ namespace engine::resources {
Mesh::~Mesh()
{
m_gfx->destroyBuffer(m_ib);
m_gfx->destroyBuffer(m_vb);
m_gfx->DestroyBuffer(m_ib);
m_gfx->DestroyBuffer(m_vb);
}
const gfx::Buffer* Mesh::getVB()
@ -38,8 +38,8 @@ namespace engine::resources {
void Mesh::initMesh(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices)
{
m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data());
m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data());
m_vb = m_gfx->CreateBuffer(gfx::BufferType::kVertex, vertices.size() * sizeof(Vertex), vertices.data());
m_ib = m_gfx->CreateBuffer(gfx::BufferType::kIndex, indices.size() * sizeof(uint32_t), indices.data());
m_count = (uint32_t)indices.size();
LOG_INFO("Loaded mesh, vertices: {}, indices: {}", vertices.size(), indices.size());
}

View File

@ -17,46 +17,46 @@ namespace engine::resources {
uint32_t stride = 0;
gfx::VertexFormat vertFormat{};
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::FLOAT3, stride);
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat3, stride);
stride += 3 * sizeof(float);
if (vertexParams.hasNormal) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::FLOAT3, stride);
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat3, stride);
stride += 3 * sizeof(float);
}
if (vertexParams.hasTangent) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::FLOAT4, stride);
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
stride += 4 * sizeof(float);
}
if (vertexParams.hasColor) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::FLOAT4, stride);
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat4, stride);
stride += 4 * sizeof(float);
}
if (vertexParams.hasUV0) {
vertFormat.attributeDescriptions.emplace_back(index++, gfx::VertexAttribFormat::FLOAT2, stride);
vertFormat.attribute_descriptions.emplace_back(index++, gfx::VertexAttribFormat::kFloat2, stride);
stride += 2 * sizeof(float);
}
vertFormat.stride = stride;
gfx::PipelineInfo info{};
info.vertShaderPath = vertPath;
info.fragShaderPath = fragPath;
info.vertexFormat = vertFormat;
info.alphaBlending = alphaBlending;
info.backfaceCulling = cullBackFace;
info.descriptorSetLayouts.push_back(renderData->globalSetLayout);
info.descriptorSetLayouts.push_back(renderData->frameSetLayout);
info.descriptorSetLayouts.push_back(renderData->materialSetLayout);
info.vert_shader_path = vertPath;
info.frag_shader_path = fragPath;
info.vertex_format = vertFormat;
info.alpha_blending = alphaBlending;
info.backface_culling = cullBackFace;
info.descriptor_set_layouts.push_back(renderData->global_set_layout);
info.descriptor_set_layouts.push_back(renderData->frame_set_layout);
info.descriptor_set_layouts.push_back(renderData->material_set_layout);
m_pipeline = m_gfx->createPipeline(info);
m_pipeline = m_gfx->CreatePipeline(info);
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attributeDescriptions.size());
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attribute_descriptions.size());
}
Shader::~Shader()
{
m_gfx->destroyPipeline(m_pipeline);
m_gfx->DestroyPipeline(m_pipeline);
}
const gfx::Pipeline* Shader::getPipeline()

View File

@ -17,37 +17,37 @@ Texture::Texture(RenderData* renderData, const std::string& path, Filtering filt
gfx::SamplerInfo samplerInfo{};
samplerInfo.magnify = gfx::Filter::LINEAR;
samplerInfo.magnify = gfx::Filter::kLinear;
switch (filtering) {
case Filtering::OFF:
samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropicFiltering = false;
samplerInfo.minify = gfx::Filter::kNearest;
samplerInfo.mipmap = gfx::Filter::kNearest;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::BILINEAR:
samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropicFiltering = false;
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kNearest;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::TRILINEAR:
samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::LINEAR;
samplerInfo.anisotropicFiltering = false;
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kLinear;
samplerInfo.anisotropic_filtering = false;
break;
case Filtering::ANISOTROPIC:
samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::LINEAR;
samplerInfo.anisotropicFiltering = true;
samplerInfo.minify = gfx::Filter::kLinear;
samplerInfo.mipmap = gfx::Filter::kLinear;
samplerInfo.anisotropic_filtering = true;
}
if (renderData->samplers.contains(samplerInfo) == false) {
renderData->samplers.insert(std::make_pair(samplerInfo, m_gfxDevice->createSampler(samplerInfo)));
renderData->samplers.insert(std::make_pair(samplerInfo, m_gfxDevice->CreateSampler(samplerInfo)));
}
m_image = m_gfxDevice->createImage(width, height, texbuf->data());
m_descriptorSet = m_gfxDevice->allocateDescriptorSet(renderData->materialSetLayout);
m_gfxDevice->updateDescriptorCombinedImageSampler(m_descriptorSet, 0, m_image, renderData->samplers.at(samplerInfo));
m_image = m_gfxDevice->CreateImage(width, height, texbuf->data());
m_descriptorSet = m_gfxDevice->AllocateDescriptorSet(renderData->material_set_layout);
m_gfxDevice->UpdateDescriptorCombinedImageSampler(m_descriptorSet, 0, m_image, renderData->samplers.at(samplerInfo));
LOG_INFO("Loaded texture: {}, width: {} height: {}", path, width, height);
@ -55,7 +55,7 @@ Texture::Texture(RenderData* renderData, const std::string& path, Filtering filt
Texture::~Texture()
{
m_gfxDevice->destroyImage(m_image);
m_gfxDevice->DestroyImage(m_image);
}
}

View File

@ -10,10 +10,10 @@
namespace engine {
Scene::Scene(Application* app)
: m_app(app)
: app_(app)
{
// event system
m_eventSystem = std::make_unique<EventSystem>();
event_system_ = std::make_unique<EventSystem>();
// ecs configuration:
@ -22,22 +22,22 @@ namespace engine {
registerComponent<ColliderComponent>();
// Order here matters:
registerSystem<TransformSystem>();
registerSystem<PhysicsSystem>();
registerSystem<RenderSystem>();
RegisterSystem<TransformSystem>();
RegisterSystem<PhysicsSystem>();
RegisterSystem<RenderSystem>();
}
Scene::~Scene()
{
}
uint32_t Scene::createEntity(const std::string& tag, uint32_t parent)
uint32_t Scene::CreateEntity(const std::string& tag, uint32_t parent)
{
uint32_t id = m_nextEntityID++;
uint32_t id = next_entity_id_++;
m_signatures.emplace(id, std::bitset<MAX_COMPONENTS>{});
signatures_.emplace(id, std::bitset<kMaxComponents>{});
auto t = addComponent<TransformComponent>(id);
auto t = AddComponent<TransformComponent>(id);
t->position = {0.0f, 0.0f, 0.0f};
t->rotation = {};
@ -51,21 +51,21 @@ namespace engine {
uint32_t Scene::getEntity(const std::string& tag, uint32_t parent)
{
return getSystem<TransformSystem>()->getChildEntity(parent, tag);
return GetSystem<TransformSystem>()->getChildEntity(parent, tag);
}
size_t Scene::getComponentSignaturePosition(size_t hash)
size_t Scene::GetComponentSignaturePosition(size_t hash)
{
return m_componentSignaturePositions.at(hash);
return component_signature_positions_.at(hash);
}
void Scene::update(float ts)
void Scene::Update(float ts)
{
for (auto& [name, system] : m_systems) {
system->onUpdate(ts);
for (auto& [name, system] : systems_) {
system->OnUpdate(ts);
}
m_eventSystem->dispatchEvents(); // clears event queue
event_system_->DespatchEvents(); // clears event queue
}
}

View File

@ -8,25 +8,25 @@
namespace engine {
SceneManager::SceneManager(Application* app)
: m_app(app)
: app_(app)
{
}
SceneManager::~SceneManager() {}
Scene* SceneManager::createEmptyScene()
Scene* SceneManager::CreateEmptyScene()
{
auto scene = std::make_unique<Scene>(m_app);
m_scenes.emplace_back(std::move(scene));
m_activeSceneIndex = (int)m_scenes.size() - 1;
return m_scenes.back().get();
auto scene = std::make_unique<Scene>(app_);
scenes_.emplace_back(std::move(scene));
active_scene_index_ = (int)scenes_.size() - 1;
return scenes_.back().get();
}
void SceneManager::updateActiveScene(float ts)
void SceneManager::UpdateActiveScene(float ts)
{
if (m_activeSceneIndex >= 0) [[likely]] {
assert((size_t)m_activeSceneIndex < m_scenes.size());
m_scenes[m_activeSceneIndex]->update(ts);
if (active_scene_index_ >= 0) [[likely]] {
assert((size_t)active_scene_index_ < scenes_.size());
scenes_[active_scene_index_]->Update(ts);
}
}

View File

@ -68,13 +68,13 @@ namespace engine {
PhysicsSystem::PhysicsSystem(Scene* scene)
: System(scene, { typeid(TransformComponent).hash_code(), typeid(ColliderComponent).hash_code() })
{
m_scene->events()->registerEventType<CollisionEvent>();
scene_->event_system()->RegisterEventType<CollisionEvent>();
}
void PhysicsSystem::onComponentInsert(uint32_t entity)
void PhysicsSystem::OnComponentInsert(uint32_t entity)
{
(void)entity;
const size_t size = m_entities.size();
const size_t size = entities_.size();
m_staticAABBs.reserve(size);
m_dynamicAABBs.reserve(size);
m_possibleCollisions.reserve(size);
@ -82,7 +82,7 @@ namespace engine {
LOG_TRACE("added entity {} to collider system", entity);
}
void PhysicsSystem::onUpdate(float ts)
void PhysicsSystem::OnUpdate(float ts)
{
(void)ts;
@ -91,9 +91,9 @@ namespace engine {
m_possibleCollisions.clear();
m_collisionInfos.clear();
for (uint32_t entity : m_entities) {
const auto t = m_scene->getComponent<TransformComponent>(entity);
const auto c = m_scene->getComponent<ColliderComponent>(entity);
for (uint32_t entity : entities_) {
const auto t = scene_->GetComponent<TransformComponent>(entity);
const auto c = scene_->GetComponent<ColliderComponent>(entity);
const glm::vec3 globalPosition = t->worldMatrix[3];
const AABB localBoundingBox = c->aabb;
@ -157,7 +157,7 @@ namespace engine {
}
for (const auto& [entity, info] : m_collisionInfos) {
m_scene->events()->queueEvent<CollisionEvent>(EventSubscriberKind::ENTITY, entity, info);
scene_->event_system()->QueueEvent<CollisionEvent>(EventSubscriberKind::kEntity, entity, info);
}
}

View File

@ -16,7 +16,7 @@ namespace engine {
RenderSystem::RenderSystem(Scene* scene)
: System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() }),
m_gfx(m_scene->app()->gfx())
m_gfx(scene_->app()->gfxdev())
{
}
@ -24,23 +24,23 @@ namespace engine {
{
}
void RenderSystem::onUpdate(float ts)
void RenderSystem::OnUpdate(float ts)
{
(void)ts;
RenderData& renderData = m_scene->app()->renderData;
RenderData& renderData = scene_->app()->render_data_;
/* camera stuff */
const auto cameraTransform = m_scene->getComponent<TransformComponent>(m_camera.camEntity);
const auto cameraTransform = scene_->GetComponent<TransformComponent>(m_camera.camEntity);
// do not render if camera is not set
if (cameraTransform == nullptr) return;
glm::mat4 viewMatrix = glm::inverse(cameraTransform->worldMatrix);
if (m_scene->app()->window()->getWindowResized()) {
if (scene_->app()->window()->getWindowResized()) {
uint32_t w, h;
m_gfx->getViewportSize(&w, &h);
m_gfx->GetViewportSize(&w, &h);
m_viewportAspectRatio = (float)w / (float)h;
const float verticalFovRadians = glm::radians(m_camera.verticalFovDegrees);
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar);
@ -48,13 +48,13 @@ namespace engine {
RenderData::GlobalSetUniformBuffer globalSetUniformBuffer{
.proj = projMatrix
};
m_gfx->writeUniformBuffer(renderData.globalSetUniformBuffer, 0, sizeof(RenderData::GlobalSetUniformBuffer), &globalSetUniformBuffer);
m_gfx->WriteUniformBuffer(renderData.global_set_uniform_buffer, 0, sizeof(RenderData::GlobalSetUniformBuffer), &globalSetUniformBuffer);
}
RenderData::FrameSetUniformBuffer frameSetUniformBuffer{
.view = viewMatrix
};
m_gfx->writeUniformBuffer(renderData.frameSetUniformBuffer, 0, sizeof(RenderData::FrameSetUniformBuffer), &frameSetUniformBuffer);
m_gfx->WriteUniformBuffer(renderData.frame_set_uniform_buffer, 0, sizeof(RenderData::FrameSetUniformBuffer), &frameSetUniformBuffer);
/* render all renderable entities */
@ -71,16 +71,16 @@ namespace engine {
};
std::unordered_map <const gfx::Pipeline*, std::vector<DrawCallData>> pipelineDrawCalls{};
for (uint32_t entity : m_entities) {
for (uint32_t entity : entities_) {
auto r = m_scene->getComponent<RenderableComponent>(entity);
auto r = scene_->GetComponent<RenderableComponent>(entity);
assert(r != nullptr);
assert(r->material != nullptr);
assert(r->material->m_texture != nullptr);
assert(r->mesh != nullptr);
if (r->shown == false) continue;
auto t = m_scene->getComponent<TransformComponent>(entity);
auto t = scene_->GetComponent<TransformComponent>(entity);
assert(t != nullptr);
const gfx::Pipeline* pipeline = r->material->getShader()->getPipeline();
@ -96,26 +96,26 @@ namespace engine {
}
/* begin rendering */
renderData.drawBuffer = m_gfx->beginRender();
renderData.draw_buffer = m_gfx->BeginRender();
/* these descriptor set bindings should persist across pipeline changes */
const gfx::Pipeline* firstPipeline = pipelineDrawCalls.begin()->first;
m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, firstPipeline, renderData.globalSet, 0);
m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, firstPipeline, renderData.frameSet, 1);
m_gfx->CmdBindDescriptorSet(renderData.draw_buffer, firstPipeline, renderData.global_set, 0);
m_gfx->CmdBindDescriptorSet(renderData.draw_buffer, firstPipeline, renderData.frame_set, 1);
for (const auto& [pipeline, drawCalls] : pipelineDrawCalls) {
m_gfx->cmdBindPipeline(renderData.drawBuffer, pipeline);
m_gfx->CmdBindPipeline(renderData.draw_buffer, pipeline);
for (const auto& drawCall : drawCalls) {
m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, pipeline, drawCall.materialSet, 2);
m_gfx->cmdPushConstants(renderData.drawBuffer, pipeline, 0, sizeof(PushConstants), &drawCall.pushConsts);
m_gfx->cmdBindVertexBuffer(renderData.drawBuffer, 0, drawCall.vb);
m_gfx->cmdBindIndexBuffer(renderData.drawBuffer, drawCall.ib);
m_gfx->cmdDrawIndexed(renderData.drawBuffer, drawCall.indexCount, 1, 0, 0, 0);
m_gfx->CmdBindDescriptorSet(renderData.draw_buffer, pipeline, drawCall.materialSet, 2);
m_gfx->CmdPushConstants(renderData.draw_buffer, pipeline, 0, sizeof(PushConstants), &drawCall.pushConsts);
m_gfx->CmdBindVertexBuffer(renderData.draw_buffer, 0, drawCall.vb);
m_gfx->CmdBindIndexBuffer(renderData.draw_buffer, drawCall.ib);
m_gfx->CmdDrawIndexed(renderData.draw_buffer, drawCall.indexCount, 1, 0, 0, 0);
}
}
/* draw */
m_gfx->finishRender(renderData.drawBuffer);
m_gfx->FinishRender(renderData.draw_buffer);
}

View File

@ -1,5 +1,7 @@
#include "systems/render2d.hpp"
#include <typeinfo>
#include "components/transform.hpp"
namespace engine {
@ -13,7 +15,7 @@ namespace engine {
{
}
void Render2DSystem::onUpdate(float ts)
void Render2DSystem::OnUpdate(float ts)
{
(void)ts;
}

View File

@ -12,13 +12,13 @@ namespace engine {
{
}
void TransformSystem::onUpdate(float ts)
void TransformSystem::OnUpdate(float ts)
{
(void)ts;
for (uint32_t entity : m_entities) {
for (uint32_t entity : entities_) {
auto t = m_scene->getComponent<TransformComponent>(entity);
auto t = scene_->GetComponent<TransformComponent>(entity);
glm::mat4 transform;
@ -30,7 +30,7 @@ namespace engine {
transform = glm::scale(transform, t->scale);
if (t->parent != 0) {
transform = m_scene->getComponent<TransformComponent>(t->parent)->worldMatrix * transform;
transform = scene_->GetComponent<TransformComponent>(t->parent)->worldMatrix * transform;
}
t->worldMatrix = transform;
@ -39,8 +39,8 @@ namespace engine {
uint32_t TransformSystem::getChildEntity(uint32_t parent, const std::string& tag)
{
for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
for (uint32_t entity : entities_) {
auto t = scene_->GetComponent<TransformComponent>(entity);
if (t->parent == parent) {
if (t->tag == tag) {
return entity;

View File

@ -12,7 +12,7 @@ namespace engine {
}
void UISystem::onUpdate(float ts)
void UISystem::OnUpdate(float ts)
{
(void)ts;

View File

@ -67,21 +67,21 @@ namespace engine::util {
glm::quat rotation = glm::quat_cast(transform);
// update position, scale, rotation
auto parentTransform = scene->getComponent<TransformComponent>(parentObj);
auto parentTransform = scene->GetComponent<TransformComponent>(parentObj);
parentTransform->position = position;
parentTransform->scale = scale;
parentTransform->rotation = rotation;
for (uint32_t i = 0; i < parentNode->mNumMeshes; i++) {
// create child node for each mesh
auto child = scene->createEntity("_mesh" + std::to_string(i), parentObj);
auto childRenderer = scene->addComponent<RenderableComponent>(child);
auto child = scene->CreateEntity("_mesh" + std::to_string(i), parentObj);
auto childRenderer = scene->AddComponent<RenderableComponent>(child);
childRenderer->mesh = meshes[parentNode->mMeshes[i]];
childRenderer->material = std::make_shared<resources::Material>(scene->app()->getResource<resources::Shader>("builtin.standard"));
childRenderer->material = std::make_shared<resources::Material>(scene->app()->GetResource<resources::Shader>("builtin.standard"));
if (textures.contains(meshTextureIndices[parentNode->mMeshes[i]])) {
childRenderer->material->m_texture = textures.at(meshTextureIndices[parentNode->mMeshes[i]]);
} else {
childRenderer->material->m_texture = scene->app()->getResource<resources::Texture>("builtin.white");
childRenderer->material->m_texture = scene->app()->GetResource<resources::Texture>("builtin.white");
}
}
@ -92,7 +92,7 @@ namespace engine::util {
meshTextureIndices,
parentNode->mChildren[i],
scene,
scene->createEntity("child" + std::to_string(i), parentObj)
scene->CreateEntity("child" + std::to_string(i), parentObj)
);
}
}
@ -182,10 +182,10 @@ namespace engine::util {
absPath /= texPath.C_Str();
try {
textures[i] = std::make_shared<resources::Texture>(
&parent->app()->renderData, absPath.string(),
&parent->app()->render_data_, absPath.string(),
resources::Texture::Filtering::TRILINEAR);
} catch (const std::runtime_error&) {
textures[i] = parent->app()->getResource<resources::Texture>("builtin.white");
textures[i] = parent->app()->GetResource<resources::Texture>("builtin.white");
}
}
}
@ -223,10 +223,10 @@ namespace engine::util {
indices[(size_t)j * 3 + 1] = m->mFaces[j].mIndices[1];
indices[(size_t)j * 3 + 2] = m->mFaces[j].mIndices[2];
}
meshes.push_back(std::make_shared<resources::Mesh>(parent->app()->gfx(), vertices, indices));
meshes.push_back(std::make_shared<resources::Mesh>(parent->app()->gfxdev(), vertices, indices));
}
uint32_t obj = parent->createEntity(scene->GetShortFilename(path.c_str()));
uint32_t obj = parent->CreateEntity(scene->GetShortFilename(path.c_str()));
buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj);

View File

@ -21,14 +21,14 @@ CameraControllerSystem::CameraControllerSystem(engine::Scene* scene)
{
}
void CameraControllerSystem::onUpdate(float ts)
void CameraControllerSystem::OnUpdate(float ts)
{
if (t == nullptr || c == nullptr || col == nullptr) {
for (uint32_t entity : m_entities) {
t = m_scene->getComponent<engine::TransformComponent>(entity);
col = m_scene->getComponent<engine::ColliderComponent>(entity);
c = m_scene->getComponent<CameraControllerComponent>(entity);
for (uint32_t entity : entities_) {
t = scene_->GetComponent<engine::TransformComponent>(entity);
col = scene_->GetComponent<engine::ColliderComponent>(entity);
c = scene_->GetComponent<CameraControllerComponent>(entity);
break;
}
if (t == nullptr) return;
@ -78,32 +78,32 @@ void CameraControllerSystem::onUpdate(float ts)
// jumping
constexpr float JUMPVEL = (float)2.82231110971133017648; //std::sqrt(2 * G * JUMPHEIGHT);
if (m_scene->app()->inputManager()->getButton("jump") && c->isGrounded == true) {
if (scene_->app()->input_manager()->GetButton("jump") && c->isGrounded == true) {
c->dy = JUMPVEL;
}
if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) {
if (scene_->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) {
c->dy += dt * c->thrust;
}
// in metres per second
float SPEED = c->walk_speed;
if (m_scene->app()->inputManager()->getButton("sprint")) SPEED *= 10.0f;
if (scene_->app()->input_manager()->GetButton("sprint")) SPEED *= 10.0f;
float dx = m_scene->app()->inputManager()->getAxis("movex");
float dz = (-m_scene->app()->inputManager()->getAxis("movey"));
float dx = scene_->app()->input_manager()->GetAxis("movex");
float dz = (-scene_->app()->input_manager()->GetAxis("movey"));
// calculate new pitch and yaw
constexpr float MAX_PITCH = glm::half_pi<float>();
constexpr float MIN_PITCH = -MAX_PITCH;
float dPitch = m_scene->app()->inputManager()->getAxis("looky") * -1.0f * c->m_cameraSensitivity;
float dPitch = scene_->app()->input_manager()->GetAxis("looky") * -1.0f * c->m_cameraSensitivity;
c->m_pitch += dPitch;
if (c->m_pitch <= MIN_PITCH || c->m_pitch >= MAX_PITCH) {
c->m_pitch -= dPitch;
}
c->m_yaw += m_scene->app()->inputManager()->getAxis("lookx") * -1.0f * c->m_cameraSensitivity;
c->m_yaw += scene_->app()->input_manager()->GetAxis("lookx") * -1.0f * c->m_cameraSensitivity;
// update position relative to camera direction in xz plane
const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, c->m_yaw);
@ -148,27 +148,27 @@ void CameraControllerSystem::onUpdate(float ts)
/* user interface inputs */
if (m_scene->app()->window()->getKeyPress(engine::inputs::Key::K_P)) {
if (scene_->app()->window()->getKeyPress(engine::inputs::Key::K_P)) {
std::string pos_string{
"x: " + std::to_string(t->position.x) +
" y: " + std::to_string(t->position.y) +
" z: " + std::to_string(t->position.z)
};
//m_scene->app()->window()->infoBox("POSITION", pos_string);
//scene_->app()->window()->infoBox("POSITION", pos_string);
LOG_INFO("position: " + pos_string);
}
if (m_scene->app()->window()->getKeyPress(engine::inputs::Key::K_R)) {
if (scene_->app()->window()->getKeyPress(engine::inputs::Key::K_R)) {
t->position = { 0.0f, 5.0f, 0.0f };
c->dy = 0.0f;
}
if (m_scene->app()->inputManager()->getButtonPress("fullscreen")) {
m_scene->app()->window()->toggleFullscreen();
if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) {
scene_->app()->window()->toggleFullscreen();
}
if (m_scene->app()->inputManager()->getButtonPress("exit")) {
m_scene->app()->window()->setCloseFlag();
if (scene_->app()->input_manager()->GetButtonPress("exit")) {
scene_->app()->window()->setCloseFlag();
}
c->justCollided = false;
@ -176,7 +176,7 @@ void CameraControllerSystem::onUpdate(float ts)
}
// called once per frame
void CameraControllerSystem::onEvent(engine::PhysicsSystem::CollisionEvent info)
void CameraControllerSystem::OnEvent(engine::PhysicsSystem::CollisionEvent info)
{
c->justCollided = info.isCollisionEnter;
c->lastCollisionNormal = info.normal;

View File

@ -30,10 +30,10 @@ public:
CameraControllerSystem(engine::Scene* scene);
// engine::System overrides
void onUpdate(float ts) override;
void OnUpdate(float ts) override;
// engine::EventHandler overrides
void onEvent(engine::PhysicsSystem::CollisionEvent info) override;
void OnEvent(engine::PhysicsSystem::CollisionEvent info) override;
engine::TransformComponent* t = nullptr;
engine::ColliderComponent* col = nullptr;

View File

@ -26,19 +26,19 @@
static void configureInputs(engine::InputManager* inputManager)
{
// user interface mappings
inputManager->addInputButton("fullscreen", engine::inputs::Key::K_F11);
inputManager->addInputButton("exit", engine::inputs::Key::K_ESCAPE);
inputManager->AddInputButton("fullscreen", engine::inputs::Key::K_F11);
inputManager->AddInputButton("exit", engine::inputs::Key::K_ESCAPE);
// game buttons
inputManager->addInputButton("fire", engine::inputs::MouseButton::M_LEFT);
inputManager->addInputButton("aim", engine::inputs::MouseButton::M_RIGHT);
inputManager->addInputButton("jump", engine::inputs::Key::K_SPACE);
inputManager->addInputButton("sprint", engine::inputs::Key::K_LSHIFT);
inputManager->AddInputButton("fire", engine::inputs::MouseButton::M_LEFT);
inputManager->AddInputButton("aim", engine::inputs::MouseButton::M_RIGHT);
inputManager->AddInputButton("jump", engine::inputs::Key::K_SPACE);
inputManager->AddInputButton("sprint", engine::inputs::Key::K_LSHIFT);
// game movement
inputManager->addInputButtonAsAxis("movex", engine::inputs::Key::K_D, engine::inputs::Key::K_A);
inputManager->addInputButtonAsAxis("movey", engine::inputs::Key::K_W, engine::inputs::Key::K_S);
inputManager->AddInputButtonAsAxis("movex", engine::inputs::Key::K_D, engine::inputs::Key::K_A);
inputManager->AddInputButtonAsAxis("movey", engine::inputs::Key::K_W, engine::inputs::Key::K_S);
// looking around
inputManager->addInputAxis("lookx", engine::inputs::MouseAxis::X);
inputManager->addInputAxis("looky", engine::inputs::MouseAxis::Y);
inputManager->AddInputAxis("lookx", engine::inputs::MouseAxis::X);
inputManager->AddInputAxis("looky", engine::inputs::MouseAxis::Y);
}
void playGame(GameSettings settings)
@ -47,92 +47,92 @@ void playGame(GameSettings settings)
LOG_INFO("Graphics Validation: {}", settings.enableValidation ? "ON" : "OFF");
engine::gfx::GraphicsSettings graphicsSettings{};
graphicsSettings.enableValidation = settings.enableValidation;
graphicsSettings.enable_validation = settings.enableValidation;
graphicsSettings.vsync = true;
graphicsSettings.waitForPresent = false;
graphicsSettings.msaaLevel = engine::gfx::MSAALevel::MSAA_OFF;
graphicsSettings.wait_for_present = false;
graphicsSettings.msaa_level = engine::gfx::MSAALevel::kOff;
engine::Application app(PROJECT_NAME, PROJECT_VERSION, graphicsSettings);
app.setFrameLimiter(settings.enableFrameLimiter);
app.SetFrameLimiter(settings.enableFrameLimiter);
// configure window
app.window()->setRelativeMouseMode(true);
configureInputs(app.inputManager());
configureInputs(app.input_manager());
auto myScene = app.sceneManager()->createEmptyScene();
auto myScene = app.scene_manager()->CreateEmptyScene();
/* create camera */
{
myScene->registerComponent<CameraControllerComponent>();
myScene->registerSystem<CameraControllerSystem>();
myScene->RegisterSystem<CameraControllerSystem>();
auto camera = myScene->createEntity("camera");
myScene->getComponent<engine::TransformComponent>(camera)->position = { 0.0f, 10.0f, 0.0f };
auto cameraCollider = myScene->addComponent<engine::ColliderComponent>(camera);
auto camera = myScene->CreateEntity("camera");
myScene->GetComponent<engine::TransformComponent>(camera)->position = { 0.0f, 10.0f, 0.0f };
auto cameraCollider = myScene->AddComponent<engine::ColliderComponent>(camera);
cameraCollider->isStatic = false;
cameraCollider->isTrigger = true;
cameraCollider->aabb = { { -0.2f, -1.5f, -0.2f }, { 0.2f, 0.2f, 0.2f} }; // Origin is at eye level
myScene->addComponent<CameraControllerComponent>(camera);
myScene->events()->subscribeToEventType<engine::PhysicsSystem::CollisionEvent>(
engine::EventSubscriberKind::ENTITY, camera, myScene->getSystem<CameraControllerSystem>()
myScene->AddComponent<CameraControllerComponent>(camera);
myScene->event_system()->SubscribeToEventType<engine::PhysicsSystem::CollisionEvent>(
engine::EventSubscriberKind::kEntity, camera, myScene->GetSystem<CameraControllerSystem>()
);
auto renderSystem = myScene->getSystem<engine::RenderSystem>();
auto renderSystem = myScene->GetSystem<engine::RenderSystem>();
renderSystem->setCameraEntity(camera);
}
/* shared resources */
auto grassTexture = std::make_shared<engine::resources::Texture>(
&app.renderData,
app.getResourcePath("textures/grass.jpg"),
&app.render_data_,
app.GetResourcePath("textures/grass.jpg"),
engine::resources::Texture::Filtering::ANISOTROPIC
);
auto spaceTexture = std::make_shared<engine::resources::Texture>(
&app.renderData,
app.getResourcePath("textures/space2.png"),
&app.render_data_,
app.GetResourcePath("textures/space2.png"),
engine::resources::Texture::Filtering::ANISOTROPIC
);
/* cube */
{
uint32_t cube = myScene->createEntity("cube");
myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f + 5.0f, -0.5f + 5.0f, -0.5f + 5.0f };
auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube);
cubeRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
cubeRenderable->material->m_texture = app.getResource<engine::resources::Texture>("builtin.white");
cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1.0f, 1.0f, 1.0f, 1);
auto cubeCollider = myScene->addComponent<engine::ColliderComponent>(cube);
uint32_t cube = myScene->CreateEntity("cube");
myScene->GetComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f + 5.0f, -0.5f + 5.0f, -0.5f + 5.0f };
auto cubeRenderable = myScene->AddComponent<engine::RenderableComponent>(cube);
cubeRenderable->material = std::make_shared<engine::resources::Material>(app.GetResource<engine::resources::Shader>("builtin.standard"));
cubeRenderable->material->m_texture = app.GetResource<engine::resources::Texture>("builtin.white");
cubeRenderable->mesh = genCuboidMesh(app.gfxdev(), 1.0f, 1.0f, 1.0f, 1);
auto cubeCollider = myScene->AddComponent<engine::ColliderComponent>(cube);
cubeCollider->isStatic = true;
cubeCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f } };
}
/* floor */
{
uint32_t floor = myScene->createEntity("floor");
myScene->getComponent<engine::TransformComponent>(floor)->position = glm::vec3{-5000.0f, -1.0f, -5000.0f};
auto floorRenderable = myScene->addComponent<engine::RenderableComponent>(floor);
floorRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
uint32_t floor = myScene->CreateEntity("floor");
myScene->GetComponent<engine::TransformComponent>(floor)->position = glm::vec3{-5000.0f, -1.0f, -5000.0f};
auto floorRenderable = myScene->AddComponent<engine::RenderableComponent>(floor);
floorRenderable->material = std::make_shared<engine::resources::Material>(app.GetResource<engine::resources::Shader>("builtin.standard"));
floorRenderable->material->m_texture = grassTexture;
floorRenderable->mesh = genCuboidMesh(app.gfx(), 10000.0f, 1.0f, 10000.0f, 5000.0f);
floorRenderable->mesh = genCuboidMesh(app.gfxdev(), 10000.0f, 1.0f, 10000.0f, 5000.0f);
floorRenderable->shown = true;
auto floorCollider = myScene->addComponent<engine::ColliderComponent>(floor);
auto floorCollider = myScene->AddComponent<engine::ColliderComponent>(floor);
floorCollider->isStatic = true;
floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 10000.0f, 1.0f, 10000.0f } };
}
//engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/astronaut/astronaut.dae"));
//engine::util::loadMeshFromFile(myScene, app.GetResourcePath("models/astronaut/astronaut.dae"));
/* skybox */
{
uint32_t skybox = myScene->createEntity("skybox");
auto skyboxRenderable = myScene->addComponent<engine::RenderableComponent>(skybox);
skyboxRenderable->material = std::make_unique<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.skybox"));
uint32_t skybox = myScene->CreateEntity("skybox");
auto skyboxRenderable = myScene->AddComponent<engine::RenderableComponent>(skybox);
skyboxRenderable->material = std::make_unique<engine::resources::Material>(app.GetResource<engine::resources::Shader>("builtin.skybox"));
skyboxRenderable->material->m_texture = spaceTexture;
skyboxRenderable->mesh = genCuboidMesh(app.gfx(), 10.0f, 10.0f, 10.0f, 1.0f, true);
myScene->getComponent<engine::TransformComponent>(skybox)->position = { -5.0f, -5.0f, -5.0f };
skyboxRenderable->mesh = genCuboidMesh(app.gfxdev(), 10.0f, 10.0f, 10.0f, 1.0f, true);
myScene->GetComponent<engine::TransformComponent>(skybox)->position = { -5.0f, -5.0f, -5.0f };
}
app.gameLoop();
app.GameLoop();
}

View File

@ -25,7 +25,7 @@ int main(int argc, char* argv[])
if (args.contains("gpuvalidation")) settings.enableValidation = true;
}
engine::setupLog(PROJECT_NAME);
engine::SetupLog(PROJECT_NAME);
LOG_INFO("{} v{}", PROJECT_NAME, PROJECT_VERSION);