a little bit more reformatting

This commit is contained in:
bailehuni 2024-06-04 23:31:22 +01:00
parent 9b5fca62f5
commit 71e7f51195
27 changed files with 517 additions and 490 deletions

View File

@ -22,7 +22,7 @@ set(SRC_FILES
"src/file_dialog.cpp" "src/file_dialog.cpp"
"src/files.cpp" "src/files.cpp"
"src/gen_tangents.cpp" "src/gen_tangents.cpp"
"src/gfx_device_vulkan.cpp" "src/gfx_device.cpp"
"src/gltf_loader.cpp" "src/gltf_loader.cpp"
"src/input_manager.cpp" "src/input_manager.cpp"
"src/renderer.cpp" "src/renderer.cpp"

46
CMakePresets.json Normal file
View File

@ -0,0 +1,46 @@
{
"version": 3,
"configurePresets": [
{
"name": "windows-base",
"description": "Target Windows with the Visual Studio development environment.",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "x64-debug",
"displayName": "x64 Debug",
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
"inherits": "windows-base",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"ENGINETEST_BUILD_WIN32_APP": "OFF"
}
},
{
"name": "x64-release",
"displayName": "x64 Release",
"description": "Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
"inherits": "x64-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"ENGINETEST_BUILD_WIN32_APP": "ON"
}
}
]
}

View File

@ -9,21 +9,21 @@
namespace engine { namespace engine {
enum class EventSubscriberKind { enum class EventSubscriberKind {
kEntity, ENTITY,
}; };
// Event handler base-class // Event handler base-class
template <typename T> template <typename T>
class EventHandler { class EventHandler {
public: 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 // Event queue interface to allow for different type queues to be in the map
class IEventQueue { class IEventQueue {
public: public:
virtual ~IEventQueue() {} virtual ~IEventQueue() {}
virtual void DespatchEvents() = 0; virtual void despatchEvents() = 0;
}; };
template <typename T> template <typename T>
@ -31,42 +31,40 @@ class EventQueue : public IEventQueue {
// holds events of type T and subscribers to those events // holds events of type T and subscribers to those events
public: 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) // For the time being, ignore kind (TODO)
(void)kind; (void)kind;
assert(subscribers_.contains(id) == false && "subscribing to an event with ID that's already in use!"); assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
subscribers_.emplace(id, handler); m_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) // For the time being, ignore kind (TODO)
(void)kind; (void)kind;
assert(subscribers_.contains(id) && "Attempt to submit event to non-existing subscriber!"); assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
EventHandler<T>* handler = subscribers_.at(id); EventHandler<T>* handler = m_subscribers.at(id);
event_queue_.emplace(handler, event); m_event_queue.emplace(handler, event);
} }
void DespatchEvents() override void despatchEvents() override
{ {
while (event_queue_.empty() == false) { while (m_event_queue.empty() == false) {
auto [handler, event] = event_queue_.front(); auto [handler, event] = m_event_queue.front();
handler->OnEvent(event); handler->onEvent(event);
event_queue_.pop(); m_event_queue.pop();
} }
} }
private: private:
std::unordered_map<uint32_t, EventHandler<T>*> subscribers_; std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
struct QueuedEvent { struct QueuedEvent {
QueuedEvent(EventHandler<T>* handler, T event) : handler(handler), event(event) {}
EventHandler<T>* handler; EventHandler<T>* handler;
T event; T event;
}; };
std::queue<QueuedEvent> event_queue_{}; std::queue<QueuedEvent> m_event_queue{};
}; };
class EventSystem { class EventSystem {
@ -77,42 +75,42 @@ class EventSystem {
~EventSystem() {} ~EventSystem() {}
template <typename T> template <typename T>
void RegisterEventType() void registerEventType()
{ {
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
assert(event_queues_.contains(hash) == false && "Registering an event queue more than once!"); assert(m_event_queues.contains(hash) == false && "Registering an event queue more than once!");
event_queues_.emplace(hash, std::make_unique<EventQueue<T>>()); m_event_queues.emplace(hash, std::make_unique<EventQueue<T>>());
} }
template <typename 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(); size_t hash = typeid(T).hash_code();
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!"); assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get()); EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
assert(queue != nullptr && "This cast should work?!! wot"); assert(queue != nullptr && "This cast should work?!! wot");
queue->Subscribe(kind, id, handler); queue->subscribe(kind, id, handler);
} }
template <typename T> template <typename T>
void QueueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event) void queueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
{ {
size_t hash = typeid(T).hash_code(); size_t hash = typeid(T).hash_code();
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!"); assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get()); EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
assert(queue != nullptr && "This cast should work?!! wot"); assert(queue != nullptr && "This cast should work?!! wot");
queue->QueueEvent(kind, subscriber_id, event); queue->queueEvent(kind, subscriber_id, event);
} }
void DespatchEvents() void despatchEvents()
{ {
for (auto& [hash, queue] : event_queues_) { for (auto& [hash, queue] : m_event_queues) {
queue->DespatchEvents(); queue->despatchEvents();
} }
} }
private: private:
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> event_queues_{}; std::unordered_map<size_t, std::unique_ptr<IEventQueue>> m_event_queues{};
}; };
} // namespace engine } // namespace engine

View File

@ -4,8 +4,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace engine::util { namespace engine {
std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions); std::filesystem::path openFileDialog(const std::vector<std::string>& extensions);
} // namespace engine::util } // namespace engine

View File

@ -8,11 +8,11 @@
namespace engine { namespace engine {
std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path); std::unique_ptr<std::vector<char>> readTextFile(const std::string& path);
std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path); std::unique_ptr<std::vector<uint8_t>> readBinaryFile(const std::string& path);
// Read an image file into a vector byte buffer. PNG and JPG support at a // Read an image file into a vector byte buffer. PNG and JPG support at a
// minimum. Output format is R8G8B8A8_UINT // minimum. Output format is R8G8B8A8_UINT
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, int& width, int& height); std::unique_ptr<std::vector<uint8_t>> readImageFile(const std::string& path, int& width, int& height);
} // namespace engine } // namespace engine

View File

@ -1,14 +1,12 @@
#pragma once #pragma once
#include <cstdint> // uint32_t #include <cstdint>
#include <vector> #include <vector>
namespace engine { namespace engine {
struct Vertex; // resources/mesh.h
}
namespace engine::util { struct Vertex; // forward-dec
/* /*
* Generate tangents for a given list of vertices. * Generate tangents for a given list of vertices.
@ -18,6 +16,6 @@ namespace engine::util {
* Returns: * Returns:
* index list for the provided vertices * index list for the provided vertices
*/ */
std::vector<uint32_t> GenTangents(std::vector<engine::Vertex>& vertices); std::vector<uint32_t> genTangents(std::vector<engine::Vertex>& vertices);
} // namespace engine::util } // namespace engine

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
@ -22,17 +23,17 @@ struct Image;
struct Sampler; struct Sampler;
enum class MSAALevel { enum class MSAALevel {
kOff, MSAA_OFF,
k2X, MSAA_2X,
k4X, MSAA_4X,
k8X, MSAA_8X,
k16X, MSAA_16X,
}; };
enum class PresentMode { enum class PresentMode {
kDoubleBufferedNoVsync, DOUBLE_BUFFERED_NO_VSYNC,
kDoubleBufferedVsync, DOUBLE_BUFFERED_VSYNC,
kTripleBuffered, TRIPLE_BUFFERED,
}; };
struct GraphicsSettings { struct GraphicsSettings {
@ -40,8 +41,8 @@ struct GraphicsSettings {
{ {
// sane defaults // sane defaults
enable_validation = false; enable_validation = false;
present_mode = PresentMode::kDoubleBufferedVsync; present_mode = PresentMode::DOUBLE_BUFFERED_VSYNC;
msaa_level = MSAALevel::kOff; msaa_level = MSAALevel::MSAA_OFF;
enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs
} }
@ -52,60 +53,59 @@ struct GraphicsSettings {
}; };
enum class ImageFormat { enum class ImageFormat {
kLinear, LINEAR,
kSRGB, SRGB,
}; };
enum class ShaderType { enum class ShaderType {
kVertex, VERTEX,
kFragment, FRAGMENT,
}; };
enum class BufferType { enum class BufferType {
kVertex, VERTEX,
kIndex, INDEX,
kUniform, UNIFORM,
}; };
enum class Primitive { enum class Primitive {
kPoints, POINTS,
kLines, LINES,
kLineStrip, LINE_STRIP,
kTriangles, TRIANGLES,
kTriangleStrip, TRIANGLE_STRIP,
}; };
enum class CullMode { kCullNone, kCullFront, kCullBack, kCullFrontAndBack }; enum class CullMode { CULL_NONE, CULL_FRONT, CULL_BACK, CULL_FRONT_AND_BACK };
enum class VertexAttribFormat { kFloat2, kFloat3, kFloat4 }; enum class VertexAttribFormat { FLOAT2, FLOAT3, FLOAT4 };
enum class Filter : int { enum class Filter : int {
kLinear, LINEAR,
kNearest, NEAREST,
}; };
enum class WrapMode : int { enum class WrapMode : int {
kRepeat, REPEAT,
kMirroredRepeat, MIRRORED_REPEAT,
kClampToEdge, CLAMP_TO_EDGE,
kClampToBorder, CLAMP_TO_BORDER,
}; };
enum class DescriptorType { enum class DescriptorType {
kUniformBuffer, UNIFORM_BUFFER,
kCombinedImageSampler, COMBINED_IMAGE_SAMPLER,
}; };
namespace ShaderStageFlags { namespace ShaderStageFlags {
enum Bits : uint32_t { enum Bits : uint32_t {
kVertex = 1 << 0, VERTEX = 1 << 0,
kFragment = 1 << 1, FRAGMENT = 1 << 1,
}; };
typedef std::underlying_type<Bits>::type Flags; typedef std::underlying_type<Bits>::type Flags;
} // namespace ShaderStageFlags } // namespace ShaderStageFlags
struct VertexAttribDescription { struct VertexAttribDescription {
VertexAttribDescription(uint32_t location, VertexAttribFormat format, uint32_t offset) : location(location), format(format), offset(offset) {}
uint32_t location; // the index to use in the shader uint32_t location; // the index to use in the shader
VertexAttribFormat format; VertexAttribFormat format;
uint32_t offset; uint32_t offset;
@ -129,17 +129,17 @@ struct PipelineInfo {
}; };
struct DescriptorSetLayoutBinding { struct DescriptorSetLayoutBinding {
DescriptorType descriptor_type = DescriptorType::kUniformBuffer; DescriptorType descriptor_type = DescriptorType::UNIFORM_BUFFER;
ShaderStageFlags::Flags stage_flags = 0; ShaderStageFlags::Flags stage_flags = 0;
}; };
struct SamplerInfo { struct SamplerInfo {
Filter minify = gfx::Filter::kLinear; Filter minify = gfx::Filter::LINEAR;
Filter magnify = gfx::Filter::kLinear; Filter magnify = gfx::Filter::LINEAR;
Filter mipmap = gfx::Filter::kLinear; Filter mipmap = gfx::Filter::LINEAR;
WrapMode wrap_u = gfx::WrapMode::kRepeat; WrapMode wrap_u = gfx::WrapMode::REPEAT;
WrapMode wrap_v = gfx::WrapMode::kRepeat; WrapMode wrap_v = gfx::WrapMode::REPEAT;
WrapMode wrap_w = gfx::WrapMode::kRepeat; // only useful for cubemaps AFAIK WrapMode wrap_w = gfx::WrapMode::REPEAT; // only useful for cubemaps AFAIK
bool anisotropic_filtering = true; // this can be force disabled by a global setting bool anisotropic_filtering = true; // this can be force disabled by a global setting
bool operator==(const SamplerInfo&) const = default; bool operator==(const SamplerInfo&) const = default;
@ -148,6 +148,7 @@ struct SamplerInfo {
} // namespace gfx } // namespace gfx
} // namespace engine } // namespace engine
// there has to be another way...
namespace std { namespace std {
template <> template <>
struct hash<engine::gfx::SamplerInfo> { struct hash<engine::gfx::SamplerInfo> {

View File

@ -10,102 +10,71 @@ struct ImDrawData; // "imgui/imgui.h"
namespace engine { namespace engine {
class GFXDevice { class GFXDevice {
public: private:
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 ChangePresentMode(gfx::PresentMode mode);
gfx::PresentMode GetPresentMode();
void SetupImguiBackend();
void ShutdownImguiBackend();
void CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);
gfx::DrawBuffer* BeginRender(bool window_resized);
/* - draw_buffer MUST be a valid pointer returned by BeginRender().
- draw_buffer is invalid after this function has been called. */
void FinishRender(gfx::DrawBuffer* draw_buffer);
gfx::Image* CreateShadowmapImage();
gfx::DrawBuffer* BeginShadowmapRender(gfx::Image* image);
void FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image);
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
- pipeline MUST be a valid pointer returned by CreatePipeline() */
void CmdBindPipeline(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline);
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
- buffer MUST be a valid pointer returned by CreateBuffer */
void CmdBindVertexBuffer(gfx::DrawBuffer* draw_buffer, uint32_t binding, const gfx::Buffer* buffer);
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
- buffer MUST be a valid pointer returned by CreateBuffer */
void CmdBindIndexBuffer(gfx::DrawBuffer* draw_buffer, const gfx::Buffer* buffer);
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 CmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance);
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);
void FreeDescriptorSet(const gfx::DescriptorSet* set);
// 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::Image* CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* image_data);
gfx::Image* CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data);
void DestroyImage(const gfx::Image* image);
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();
private:
struct Impl; struct Impl;
std::unique_ptr<Impl> pimpl; std::unique_ptr<Impl> pimpl;
public:
GFXDevice(const char* app_name, const char* app_version, SDL_Window* window, gfx::GraphicsSettings settings);
GFXDevice(const GFXDevice&) = delete;
~GFXDevice();
GFXDevice& operator=(const GFXDevice&) = delete;
void getViewportSize(uint32_t* w, uint32_t* h);
void changePresentMode(gfx::PresentMode mode);
gfx::PresentMode getPresentMode();
void setupImguiBackend();
void shutdownImguiBackend();
void cmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);
gfx::DrawBuffer* beginRender(bool window_resized);
void finishRender(gfx::DrawBuffer* draw_buffer);
gfx::DrawBuffer* beginShadowmapRender(gfx::Image* image);
void finishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image);
void cmdBindPipeline(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline);
void cmdBindVertexBuffer(gfx::DrawBuffer* draw_buffer, uint32_t binding, const gfx::Buffer* buffer);
void cmdBindIndexBuffer(gfx::DrawBuffer* draw_buffer, const gfx::Buffer* buffer);
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 cmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance);
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);
void freeDescriptorSet(const gfx::DescriptorSet* set);
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);
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
void destroyBuffer(const gfx::Buffer* buffer);
gfx::Image* createImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* image_data);
gfx::Image* createImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data);
gfx::Image* createImageShadowmap();
void destroyImage(const gfx::Image* image);
const gfx::Sampler* createSampler(const gfx::SamplerInfo& info);
void destroySampler(const gfx::Sampler* sampler);
uint64_t getFrameCount();
void logPerformanceInfo();
void waitIdle();
}; };
} // namespace engine } // namespace engine

View File

@ -4,17 +4,8 @@
#include "scene.h" #include "scene.h"
namespace engine::util { namespace engine {
/* engine::Entity loadGLTF(Scene& scene, const std::string& path, bool isStatic = false);
* Loads the default scene found in a glTF file into 'scene'.
* 'isStatic' will mark every transform as static to aid rendering optimisation.
* Returns the top-level glTF node as an engine entity.
*
* Loader limitations:
* - Can only load .glb files
* - glTF files must contain all textures
*/
engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic = false);
} // namespace engine::util } // namespace engine

View File

@ -105,9 +105,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
{ {
const uint8_t pixel[4] = {255, 255, 255, 255}; const uint8_t pixel[4] = {255, 255, 255, 255};
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
auto whiteTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true); auto whiteTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
getResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture)); getResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
@ -115,9 +115,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
{ {
const uint8_t pixel[4] = {0, 0, 0, 255}; const uint8_t pixel[4] = {0, 0, 0, 255};
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
auto blackTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true); auto blackTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
getResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture)); getResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture));
@ -125,9 +125,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
{ {
const uint8_t pixel[4] = {127, 127, 255, 255}; const uint8_t pixel[4] = {127, 127, 255, 255};
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
auto normalTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false); auto normalTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
getResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture)); getResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture));
@ -135,9 +135,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
{ {
const uint8_t pixel[4] = {255, 127, 0, 255}; // AO, roughness, metallic const uint8_t pixel[4] = {255, 127, 0, 255}; // AO, roughness, metallic
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
auto mrTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false); auto mrTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
getResourceManager<Texture>()->AddPersistent("builtin.mr", std::move(mrTexture)); getResourceManager<Texture>()->AddPersistent("builtin.mr", std::move(mrTexture));
@ -155,7 +155,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
Application::~Application() Application::~Application()
{ {
m_renderer->GetDevice()->ShutdownImguiBackend(); m_renderer->GetDevice()->shutdownImguiBackend();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(im_gui_things.context); ImGui::DestroyContext(im_gui_things.context);
} }
@ -177,16 +177,16 @@ void Application::gameLoop()
bool show_info_window = false; bool show_info_window = false;
} debug_menu_state; } debug_menu_state;
debug_menu_state.enable_frame_limiter = m_configuration.enable_frame_limiter; debug_menu_state.enable_frame_limiter = m_configuration.enable_frame_limiter;
switch (m_renderer->GetDevice()->GetPresentMode()) { switch (m_renderer->GetDevice()->getPresentMode()) {
case gfx::PresentMode::kDoubleBufferedNoVsync: case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
debug_menu_state.triple_buffering = false; debug_menu_state.triple_buffering = false;
debug_menu_state.vsync = false; debug_menu_state.vsync = false;
break; break;
case gfx::PresentMode::kDoubleBufferedVsync: case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
debug_menu_state.triple_buffering = false; debug_menu_state.triple_buffering = false;
debug_menu_state.vsync = true; debug_menu_state.vsync = true;
break; break;
case gfx::PresentMode::kTripleBuffered: case gfx::PresentMode::TRIPLE_BUFFERED:
debug_menu_state.triple_buffering = true; debug_menu_state.triple_buffering = true;
debug_menu_state.vsync = false; debug_menu_state.vsync = false;
} }
@ -207,7 +207,7 @@ void Application::gameLoop()
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] { if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
lastTick = now; lastTick = now;
LOG_DEBUG("fps: {}", std::lroundf(avg_fps)); LOG_DEBUG("fps: {}", std::lroundf(avg_fps));
getRenderer()->GetDevice()->LogPerformanceInfo(); getRenderer()->GetDevice()->logPerformanceInfo();
m_window->ResetAvgFPS(); m_window->ResetAvgFPS();
} }
@ -246,10 +246,10 @@ void Application::gameLoop()
} }
if (ImGui::Checkbox("Enable vsync", &debug_menu_state.vsync)) { if (ImGui::Checkbox("Enable vsync", &debug_menu_state.vsync)) {
if (debug_menu_state.vsync) { if (debug_menu_state.vsync) {
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync); m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_VSYNC);
} }
else { else {
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync); m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC);
} }
} }
if (debug_menu_state.triple_buffering) { if (debug_menu_state.triple_buffering) {
@ -258,14 +258,14 @@ void Application::gameLoop()
if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) { if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) {
if (debug_menu_state.triple_buffering) { if (debug_menu_state.triple_buffering) {
debug_menu_state.vsync = false; debug_menu_state.vsync = false;
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kTripleBuffered); m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::TRIPLE_BUFFERED);
} }
else { else {
if (debug_menu_state.vsync) { if (debug_menu_state.vsync) {
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync); m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_VSYNC);
} }
else { else {
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync); m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC);
} }
} }
} }
@ -276,9 +276,9 @@ void Application::gameLoop()
if (!scene) ImGui::BeginDisabled(); if (!scene) ImGui::BeginDisabled();
// load gltf file dialog // load gltf file dialog
if (ImGui::Button("Load glTF")) { if (ImGui::Button("Load glTF")) {
std::filesystem::path path = util::OpenFileDialog({"glb"}); std::filesystem::path path = openFileDialog({"glb"});
if (path.empty() == false) { if (path.empty() == false) {
util::LoadGLTF(*scene, path.string(), false); loadGLTF(*scene, path.string(), false);
} }
} }
if (!scene) ImGui::EndDisabled(); if (!scene) ImGui::EndDisabled();
@ -534,7 +534,7 @@ void Application::gameLoop()
delta_times[m_window->GetFrameCount() % delta_times.size()] = m_window->dt(); delta_times[m_window->GetFrameCount() % delta_times.size()] = m_window->dt();
} }
m_renderer->GetDevice()->WaitIdle(); m_renderer->GetDevice()->waitIdle();
} }
} // namespace engine } // namespace engine

View File

@ -11,9 +11,9 @@
#include "log.h" #include "log.h"
namespace engine::util { namespace engine {
std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions) std::filesystem::path openFileDialog(const std::vector<std::string>& extensions)
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -55,4 +55,4 @@ std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions)
#endif #endif
} }
} // namespace engine::util } // namespace engine

View File

@ -7,7 +7,7 @@
namespace engine { namespace engine {
std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path) std::unique_ptr<std::vector<char>> readTextFile(const std::string& path)
{ {
std::ifstream file(path, std::ios::ate); std::ifstream file(path, std::ios::ate);
if (file.is_open() == false) { if (file.is_open() == false) {
@ -39,7 +39,7 @@ std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path)
return buffer; return buffer;
} }
std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path) std::unique_ptr<std::vector<uint8_t>> readBinaryFile(const std::string& path)
{ {
std::ifstream file(path, std::ios::ate | std::ios::binary); std::ifstream file(path, std::ios::ate | std::ios::binary);
if (file.is_open() == false) { if (file.is_open() == false) {
@ -55,7 +55,7 @@ std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path)
return buffer; return buffer;
} }
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, int& width, int& height) std::unique_ptr<std::vector<uint8_t>> readImageFile(const std::string& path, int& width, int& height)
{ {
int x, y, n; int x, y, n;
unsigned char* data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp unsigned char* data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp

View File

@ -7,9 +7,9 @@
#include "resource_mesh.h" #include "resource_mesh.h"
namespace engine::util { namespace engine {
std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& vertices) std::vector<uint32_t> genTangents(std::vector<engine::Vertex>& vertices)
{ {
using VertList = std::vector<Vertex>; using VertList = std::vector<Vertex>;
@ -64,8 +64,8 @@ std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& ver
std::vector<uint32_t> remap_table(vertices.size()); // initialised to zeros std::vector<uint32_t> remap_table(vertices.size()); // initialised to zeros
std::vector<Vertex> vertex_data_out(vertices.size()); // initialised to zeros std::vector<Vertex> vertex_data_out(vertices.size()); // initialised to zeros
const int new_vertex_count = WeldMesh(reinterpret_cast<int*>(remap_table.data()), reinterpret_cast<float*>(vertex_data_out.data()), reinterpret_cast<float*>(vertices.data()), const int new_vertex_count = WeldMesh(reinterpret_cast<int*>(remap_table.data()), reinterpret_cast<float*>(vertex_data_out.data()),
static_cast<int>(vertices.size()), Vertex::floatsPerVertex()); reinterpret_cast<float*>(vertices.data()), static_cast<int>(vertices.size()), Vertex::floatsPerVertex());
assert(new_vertex_count >= 0); assert(new_vertex_count >= 0);
// get new vertices into the vector. // get new vertices into the vector.
@ -78,4 +78,4 @@ std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& ver
return remap_table; return remap_table;
} }
} // namespace engine::util } // namespace engine

View File

@ -140,11 +140,11 @@ namespace converters {
static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt) static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
{ {
switch (fmt) { switch (fmt) {
case gfx::VertexAttribFormat::kFloat2: case gfx::VertexAttribFormat::FLOAT2:
return VK_FORMAT_R32G32_SFLOAT; return VK_FORMAT_R32G32_SFLOAT;
case gfx::VertexAttribFormat::kFloat3: case gfx::VertexAttribFormat::FLOAT3:
return VK_FORMAT_R32G32B32_SFLOAT; return VK_FORMAT_R32G32B32_SFLOAT;
case gfx::VertexAttribFormat::kFloat4: case gfx::VertexAttribFormat::FLOAT4:
return VK_FORMAT_R32G32B32A32_SFLOAT; return VK_FORMAT_R32G32B32A32_SFLOAT;
} }
throw std::runtime_error("Unknown vertex attribute format"); throw std::runtime_error("Unknown vertex attribute format");
@ -153,11 +153,11 @@ static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type) static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
{ {
switch (type) { switch (type) {
case gfx::BufferType::kVertex: case gfx::BufferType::VERTEX:
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
case gfx::BufferType::kIndex: case gfx::BufferType::INDEX:
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT; return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
case gfx::BufferType::kUniform: case gfx::BufferType::UNIFORM:
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
default: default:
throw std::runtime_error("This buffer type does not have usage bits"); throw std::runtime_error("This buffer type does not have usage bits");
@ -167,9 +167,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
[[maybe_unused]] static VkFilter getFilter(gfx::Filter filter) [[maybe_unused]] static VkFilter getFilter(gfx::Filter filter)
{ {
switch (filter) { switch (filter) {
case gfx::Filter::kLinear: case gfx::Filter::LINEAR:
return VK_FILTER_LINEAR; return VK_FILTER_LINEAR;
case gfx::Filter::kNearest: case gfx::Filter::NEAREST:
return VK_FILTER_NEAREST; return VK_FILTER_NEAREST;
} }
throw std::runtime_error("Unknown filter"); throw std::runtime_error("Unknown filter");
@ -178,13 +178,13 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
[[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode) [[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode)
{ {
switch (mode) { switch (mode) {
case gfx::WrapMode::kRepeat: case gfx::WrapMode::REPEAT:
return VK_SAMPLER_ADDRESS_MODE_REPEAT; return VK_SAMPLER_ADDRESS_MODE_REPEAT;
case gfx::WrapMode::kMirroredRepeat: case gfx::WrapMode::MIRRORED_REPEAT:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
case gfx::WrapMode::kClampToEdge: case gfx::WrapMode::CLAMP_TO_EDGE:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
case gfx::WrapMode::kClampToBorder: case gfx::WrapMode::CLAMP_TO_BORDER:
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
} }
throw std::runtime_error("Unknown wrap mode"); throw std::runtime_error("Unknown wrap mode");
@ -193,9 +193,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
[[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter) [[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter)
{ {
switch (filter) { switch (filter) {
case gfx::Filter::kLinear: case gfx::Filter::LINEAR:
return VK_SAMPLER_MIPMAP_MODE_LINEAR; return VK_SAMPLER_MIPMAP_MODE_LINEAR;
case gfx::Filter::kNearest: case gfx::Filter::NEAREST:
return VK_SAMPLER_MIPMAP_MODE_NEAREST; return VK_SAMPLER_MIPMAP_MODE_NEAREST;
} }
throw std::runtime_error("Unknown filter"); throw std::runtime_error("Unknown filter");
@ -204,15 +204,15 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
[[maybe_unused]] static VkSampleCountFlagBits getSampleCountFlags(gfx::MSAALevel level) [[maybe_unused]] static VkSampleCountFlagBits getSampleCountFlags(gfx::MSAALevel level)
{ {
switch (level) { switch (level) {
case gfx::MSAALevel::kOff: case gfx::MSAALevel::MSAA_OFF:
return VK_SAMPLE_COUNT_1_BIT; return VK_SAMPLE_COUNT_1_BIT;
case gfx::MSAALevel::k2X: case gfx::MSAALevel::MSAA_2X:
return VK_SAMPLE_COUNT_2_BIT; return VK_SAMPLE_COUNT_2_BIT;
case gfx::MSAALevel::k4X: case gfx::MSAALevel::MSAA_4X:
return VK_SAMPLE_COUNT_4_BIT; return VK_SAMPLE_COUNT_4_BIT;
case gfx::MSAALevel::k8X: case gfx::MSAALevel::MSAA_8X:
return VK_SAMPLE_COUNT_8_BIT; return VK_SAMPLE_COUNT_8_BIT;
case gfx::MSAALevel::k16X: case gfx::MSAALevel::MSAA_16X:
return VK_SAMPLE_COUNT_16_BIT; return VK_SAMPLE_COUNT_16_BIT;
default: default:
throw std::runtime_error("Unknown MSAA level"); throw std::runtime_error("Unknown MSAA level");
@ -222,9 +222,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
static VkDescriptorType getDescriptorType(gfx::DescriptorType type) static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
{ {
switch (type) { switch (type) {
case gfx::DescriptorType::kUniformBuffer: case gfx::DescriptorType::UNIFORM_BUFFER:
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case gfx::DescriptorType::kCombinedImageSampler: case gfx::DescriptorType::COMBINED_IMAGE_SAMPLER:
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
default: default:
throw std::runtime_error("Unknown descriptor type"); throw std::runtime_error("Unknown descriptor type");
@ -234,21 +234,21 @@ static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags) static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags)
{ {
VkShaderStageFlags out = 0; VkShaderStageFlags out = 0;
if (flags & gfx::ShaderStageFlags::kVertex) out |= VK_SHADER_STAGE_VERTEX_BIT; if (flags & gfx::ShaderStageFlags::VERTEX) out |= VK_SHADER_STAGE_VERTEX_BIT;
if (flags & gfx::ShaderStageFlags::kFragment) out |= VK_SHADER_STAGE_FRAGMENT_BIT; if (flags & gfx::ShaderStageFlags::FRAGMENT) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
return out; return out;
} }
static VkCullModeFlags getCullModeFlags(gfx::CullMode mode) static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
{ {
switch (mode) { switch (mode) {
case gfx::CullMode::kCullNone: case gfx::CullMode::CULL_NONE:
return VK_CULL_MODE_NONE; return VK_CULL_MODE_NONE;
case gfx::CullMode::kCullFront: case gfx::CullMode::CULL_FRONT:
return VK_CULL_MODE_FRONT_BIT; return VK_CULL_MODE_FRONT_BIT;
case gfx::CullMode::kCullBack: case gfx::CullMode::CULL_BACK:
return VK_CULL_MODE_BACK_BIT; return VK_CULL_MODE_BACK_BIT;
case gfx::CullMode::kCullFrontAndBack: case gfx::CullMode::CULL_FRONT_AND_BACK:
return VK_CULL_MODE_FRONT_AND_BACK; return VK_CULL_MODE_FRONT_AND_BACK;
default: default:
throw std::runtime_error("Unknown cull mode"); throw std::runtime_error("Unknown cull mode");
@ -258,9 +258,9 @@ static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
static VkFormat getImageFormat(gfx::ImageFormat format) static VkFormat getImageFormat(gfx::ImageFormat format)
{ {
switch (format) { switch (format) {
case gfx::ImageFormat::kLinear: case gfx::ImageFormat::LINEAR:
return VK_FORMAT_R8G8B8A8_UNORM; return VK_FORMAT_R8G8B8A8_UNORM;
case gfx::ImageFormat::kSRGB: case gfx::ImageFormat::SRGB:
return VK_FORMAT_R8G8B8A8_SRGB; return VK_FORMAT_R8G8B8A8_SRGB;
default: default:
throw std::runtime_error("Unknown image format"); throw std::runtime_error("Unknown image format");
@ -562,7 +562,7 @@ GFXDevice::~GFXDevice()
destroyVulkanInstance(pimpl->instance); destroyVulkanInstance(pimpl->instance);
} }
void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h) void GFXDevice::getViewportSize(uint32_t* w, uint32_t* h)
{ {
int width, height; int width, height;
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height); SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
@ -576,28 +576,28 @@ void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
} }
} }
void GFXDevice::ChangePresentMode(gfx::PresentMode mode) void GFXDevice::changePresentMode(gfx::PresentMode mode)
{ {
pimpl->swapchainInfo.requested_present_mode = mode; pimpl->swapchainInfo.requested_present_mode = mode;
// need to recreate swapchain to apply changes // need to recreate swapchain to apply changes
pimpl->swapchainIsOutOfDate = true; pimpl->swapchainIsOutOfDate = true;
} }
gfx::PresentMode GFXDevice::GetPresentMode() gfx::PresentMode GFXDevice::getPresentMode()
{ {
switch (pimpl->swapchain.presentMode) { switch (pimpl->swapchain.presentMode) {
case VK_PRESENT_MODE_FIFO_KHR: case VK_PRESENT_MODE_FIFO_KHR:
return gfx::PresentMode::kDoubleBufferedVsync; return gfx::PresentMode::DOUBLE_BUFFERED_VSYNC;
case VK_PRESENT_MODE_IMMEDIATE_KHR: case VK_PRESENT_MODE_IMMEDIATE_KHR:
return gfx::PresentMode::kDoubleBufferedNoVsync; return gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC;
case VK_PRESENT_MODE_MAILBOX_KHR: case VK_PRESENT_MODE_MAILBOX_KHR:
return gfx::PresentMode::kTripleBuffered; return gfx::PresentMode::TRIPLE_BUFFERED;
default: default:
throw std::runtime_error("Unknown present mode"); throw std::runtime_error("Unknown present mode");
} }
} }
void GFXDevice::SetupImguiBackend() void GFXDevice::setupImguiBackend()
{ {
auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction { auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction {
return vkGetInstanceProcAddr(*reinterpret_cast<VkInstance*>(user_data), function_name); return vkGetInstanceProcAddr(*reinterpret_cast<VkInstance*>(user_data), function_name);
@ -630,18 +630,18 @@ void GFXDevice::SetupImguiBackend()
ImGui_ImplVulkan_CreateFontsTexture(); ImGui_ImplVulkan_CreateFontsTexture();
} }
void GFXDevice::ShutdownImguiBackend() void GFXDevice::shutdownImguiBackend()
{ {
ImGui_ImplVulkan_DestroyFontsTexture(); ImGui_ImplVulkan_DestroyFontsTexture();
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
} }
void GFXDevice::CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data) void GFXDevice::cmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data)
{ {
ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf); ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf);
} }
gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized) gfx::DrawBuffer* GFXDevice::beginRender(bool window_resized)
{ {
VkResult res; VkResult res;
@ -899,7 +899,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
return drawBuffer; return drawBuffer;
} }
void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
{ {
assert(drawBuffer != nullptr); assert(drawBuffer != nullptr);
@ -1009,7 +1009,7 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
delete drawBuffer; delete drawBuffer;
} }
gfx::Image* GFXDevice::CreateShadowmapImage() gfx::Image* GFXDevice::createImageShadowmap()
{ {
if (pimpl->FRAMECOUNT != 0) abort(); if (pimpl->FRAMECOUNT != 0) abort();
@ -1054,7 +1054,7 @@ gfx::Image* GFXDevice::CreateShadowmapImage()
return out; return out;
} }
gfx::DrawBuffer* GFXDevice::BeginShadowmapRender(gfx::Image* image) gfx::DrawBuffer* GFXDevice::beginShadowmapRender(gfx::Image* image)
{ {
assert(image != nullptr); assert(image != nullptr);
if (pimpl->FRAMECOUNT != 0) throw std::runtime_error("Can only create shadowmap before proper rendering begins."); if (pimpl->FRAMECOUNT != 0) throw std::runtime_error("Can only create shadowmap before proper rendering begins.");
@ -1152,7 +1152,7 @@ gfx::DrawBuffer* GFXDevice::BeginShadowmapRender(gfx::Image* image)
return drawBuffer; return drawBuffer;
} }
void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image) void GFXDevice::finishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image)
{ {
assert(draw_buffer != nullptr); assert(draw_buffer != nullptr);
@ -1211,44 +1211,44 @@ void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image*
delete draw_buffer; delete draw_buffer;
} }
void GFXDevice::CmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline) void GFXDevice::cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
{ {
assert(drawBuffer != nullptr); assert(drawBuffer != nullptr);
assert(pipeline != nullptr); assert(pipeline != nullptr);
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); 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(drawBuffer != nullptr);
assert(buffer != nullptr); assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::kVertex); assert(buffer->type == gfx::BufferType::VERTEX);
const VkDeviceSize offset = 0; const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset); 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(drawBuffer != nullptr);
assert(buffer != nullptr); assert(buffer != nullptr);
assert(buffer->type == gfx::BufferType::kIndex); assert(buffer->type == gfx::BufferType::INDEX);
vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE); 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, void GFXDevice::cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
uint32_t firstInstance) uint32_t firstInstance)
{ {
assert(drawBuffer != nullptr); assert(drawBuffer != nullptr);
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
} }
void GFXDevice::CmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance) void GFXDevice::cmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)
{ {
assert(drawBuffer != nullptr); assert(drawBuffer != nullptr);
vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count, first_vertex, first_instance); vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count, first_vertex, first_instance);
} }
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); assert(drawBuffer != nullptr);
assert(pipeline != nullptr); assert(pipeline != nullptr);
@ -1256,7 +1256,7 @@ void GFXDevice::CmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipelin
vkCmdPushConstants(drawBuffer->frameData.drawBuf, pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, offset, size, data); 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)
{ {
assert(drawBuffer != nullptr); assert(drawBuffer != nullptr);
assert(pipeline != nullptr); assert(pipeline != nullptr);
@ -1265,7 +1265,7 @@ void GFXDevice::CmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pip
&set->sets[drawBuffer->currentFrameIndex], 0, nullptr); &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; [[maybe_unused]] VkResult res;
@ -1273,13 +1273,13 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
VkShaderModule vertShaderModule; VkShaderModule vertShaderModule;
VkShaderModule fragShaderModule; VkShaderModule fragShaderModule;
// be careful with these .c_str() calls. It is OK here because 'info' exists for the duration of CreatePipeline() // be careful with these .c_str() calls. It is OK here because 'info' exists for the duration of createPipeline()
{ {
auto vertShaderCode = ReadTextFile(info.vert_shader_path.c_str()); auto vertShaderCode = readTextFile(info.vert_shader_path.c_str());
vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vert_shader_path.c_str()); vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vert_shader_path.c_str());
} }
{ {
auto fragShaderCode = ReadTextFile(info.frag_shader_path.c_str()); auto fragShaderCode = readTextFile(info.frag_shader_path.c_str());
fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.frag_shader_path.c_str()); fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.frag_shader_path.c_str());
} }
@ -1497,7 +1497,7 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
return pipeline; return pipeline;
} }
void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline) void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
{ {
assert(pipeline != nullptr); assert(pipeline != nullptr);
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr); vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
@ -1505,7 +1505,7 @@ void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline)
delete pipeline; 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{}; gfx::DescriptorSetLayout* out = new gfx::DescriptorSetLayout{};
@ -1532,13 +1532,13 @@ gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector
return out; return out;
} }
void GFXDevice::DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout) void GFXDevice::destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
{ {
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr); vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
delete layout; delete layout;
} }
gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLayout* layout) gfx::DescriptorSet* GFXDevice::allocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
{ {
assert(layout != nullptr); assert(layout != nullptr);
@ -1560,13 +1560,13 @@ gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLay
return set; return set;
} }
void GFXDevice::FreeDescriptorSet(const gfx::DescriptorSet* set) void GFXDevice::freeDescriptorSet(const gfx::DescriptorSet* set)
{ {
assert(set != nullptr); assert(set != nullptr);
VKCHECK(vkFreeDescriptorSets(pimpl->device.device, pimpl->descriptorPool, static_cast<uint32_t>(set->sets.size()), set->sets.data())); VKCHECK(vkFreeDescriptorSets(pimpl->device.device, pimpl->descriptorPool, static_cast<uint32_t>(set->sets.size()), set->sets.data()));
} }
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(set != nullptr); assert(set != nullptr);
assert(buffer != nullptr); assert(buffer != nullptr);
@ -1589,7 +1589,7 @@ void GFXDevice::UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uin
} }
} }
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(set != nullptr); assert(set != nullptr);
assert(image != nullptr); assert(image != nullptr);
@ -1617,7 +1617,7 @@ void GFXDevice::UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* s
} }
} }
gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* initialData) gfx::UniformBuffer* GFXDevice::createUniformBuffer(uint64_t size, const void* initialData)
{ {
assert(initialData != nullptr); assert(initialData != nullptr);
@ -1627,7 +1627,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
/* first make staging buffer */ /* first make staging buffer */
out->stagingBuffer.size = size; out->stagingBuffer.size = size;
out->stagingBuffer.type = gfx::BufferType::kUniform; out->stagingBuffer.type = gfx::BufferType::UNIFORM;
{ {
VkBufferCreateInfo stagingBufferInfo{}; VkBufferCreateInfo stagingBufferInfo{};
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@ -1653,7 +1653,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
/* create the device-local set of buffers */ /* create the device-local set of buffers */
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
out->gpuBuffers[i].size = out->stagingBuffer.size; out->gpuBuffers[i].size = out->stagingBuffer.size;
out->gpuBuffers[i].type = gfx::BufferType::kUniform; out->gpuBuffers[i].type = gfx::BufferType::UNIFORM;
VkBufferCreateInfo gpuBufferInfo{}; VkBufferCreateInfo gpuBufferInfo{};
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@ -1677,7 +1677,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
return out; return out;
} }
void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer) void GFXDevice::destroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
{ {
assert(uniformBuffer != nullptr); assert(uniformBuffer != nullptr);
@ -1690,7 +1690,7 @@ void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
delete uniformBuffer; 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(buffer != nullptr); assert(buffer != nullptr);
assert(data != nullptr); assert(data != nullptr);
@ -1710,7 +1710,7 @@ void GFXDevice::WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset,
} }
} }
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)
{ {
assert(data != nullptr); assert(data != nullptr);
@ -1769,7 +1769,7 @@ gfx::Buffer* GFXDevice::CreateBuffer(gfx::BufferType type, uint64_t size, const
return out; return out;
} }
void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer) void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
{ {
assert(buffer != nullptr); assert(buffer != nullptr);
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation); vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
@ -1777,7 +1777,7 @@ void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
} }
// imageData must have pixel format R8G8B8A8 // imageData must have pixel format R8G8B8A8
gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* imageData) gfx::Image* GFXDevice::createImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* imageData)
{ {
assert(imageData != nullptr); assert(imageData != nullptr);
@ -2032,7 +2032,7 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu
return out; return out;
} }
gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data) gfx::Image* GFXDevice::createImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data)
{ {
assert(image_data[0] != nullptr); assert(image_data[0] != nullptr);
assert(image_data[1] != nullptr); assert(image_data[1] != nullptr);
@ -2291,7 +2291,7 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm
return out; return out;
} }
void GFXDevice::DestroyImage(const gfx::Image* image) void GFXDevice::destroyImage(const gfx::Image* image)
{ {
assert(image != nullptr); assert(image != nullptr);
vkDestroyImageView(pimpl->device.device, image->view, nullptr); vkDestroyImageView(pimpl->device.device, image->view, nullptr);
@ -2299,7 +2299,7 @@ void GFXDevice::DestroyImage(const gfx::Image* image)
delete image; 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{}; gfx::Sampler* out = new gfx::Sampler{};
@ -2323,14 +2323,14 @@ const gfx::Sampler* GFXDevice::CreateSampler(const gfx::SamplerInfo& info)
return out; return out;
} }
void GFXDevice::DestroySampler(const gfx::Sampler* sampler) void GFXDevice::destroySampler(const gfx::Sampler* sampler)
{ {
assert(sampler != nullptr); assert(sampler != nullptr);
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr); vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
delete sampler; delete sampler;
} }
void GFXDevice::LogPerformanceInfo() void GFXDevice::logPerformanceInfo()
{ {
VmaTotalStatistics pStats{}; VmaTotalStatistics pStats{};
vmaCalculateStatistics(pimpl->allocator, &pStats); vmaCalculateStatistics(pimpl->allocator, &pStats);
@ -2354,8 +2354,9 @@ void GFXDevice::LogPerformanceInfo()
} }
} }
uint64_t GFXDevice::GetFrameCount() { return pimpl->FRAMECOUNT; } uint64_t GFXDevice::getFrameCount() { return pimpl->FRAMECOUNT; }
void GFXDevice::WaitIdle() { vkDeviceWaitIdle(pimpl->device.device); } /* Waits until all the active GPU queues have finished working */
void GFXDevice::waitIdle() { vkDeviceWaitIdle(pimpl->device.device); }
} // namespace engine } // namespace engine

View File

@ -38,7 +38,7 @@ struct std::hash<Color> {
namespace tg = tinygltf; namespace tg = tinygltf;
namespace engine::util { namespace engine {
template <typename T> template <typename T>
struct Attribute { struct Attribute {
@ -88,7 +88,17 @@ static glm::mat4 MatFromDoubleArray(const std::vector<double>& arr)
return mat; return mat;
} }
engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) /*
* Loads the default scene found in a glTF file into 'scene'.
* 'isStatic' will mark every transform as static to aid rendering optimisation.
* Returns the top-level glTF node as an engine entity.
*
* Loader limitations:
* - Can only load .glb files
* - glTF files must contain all textures
* - No extension support
*/
engine::Entity loadGLTF(Scene& scene, const std::string& path, bool isStatic)
{ {
LOG_INFO("Loading gltf file: {}", path); LOG_INFO("Loading gltf file: {}", path);
@ -161,46 +171,46 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
// default to trilinear filtering even if mipmaps are not specified // default to trilinear filtering even if mipmaps are not specified
samplerInfo.minify = gfx::Filter::kLinear; samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.magnify = gfx::Filter::kLinear; samplerInfo.magnify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::kLinear; samplerInfo.mipmap = gfx::Filter::LINEAR;
if (texture.sampler != -1) { if (texture.sampler != -1) {
const tg::Sampler& sampler = model.samplers.at(texture.sampler); const tg::Sampler& sampler = model.samplers.at(texture.sampler);
switch (sampler.minFilter) { switch (sampler.minFilter) {
case TINYGLTF_TEXTURE_FILTER_NEAREST: case TINYGLTF_TEXTURE_FILTER_NEAREST:
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR: case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR:
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kLinear; samplerInfo.mipmap = gfx::Filter::LINEAR;
break; break;
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST: case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST:
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
break; break;
case TINYGLTF_TEXTURE_FILTER_LINEAR: case TINYGLTF_TEXTURE_FILTER_LINEAR:
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR: case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR:
samplerInfo.minify = gfx::Filter::kLinear; samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::kLinear; samplerInfo.mipmap = gfx::Filter::LINEAR;
break; break;
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST: case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST:
samplerInfo.minify = gfx::Filter::kLinear; samplerInfo.minify = gfx::Filter::LINEAR;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
break; break;
default: default:
break; break;
} }
switch (sampler.magFilter) { switch (sampler.magFilter) {
case TINYGLTF_TEXTURE_FILTER_NEAREST: case TINYGLTF_TEXTURE_FILTER_NEAREST:
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
break; break;
case TINYGLTF_TEXTURE_FILTER_LINEAR: case TINYGLTF_TEXTURE_FILTER_LINEAR:
samplerInfo.magnify = gfx::Filter::kLinear; samplerInfo.magnify = gfx::Filter::LINEAR;
break; break;
default: default:
break; break;
} }
} }
// use aniso if min filter is LINEAR_MIPMAP_LINEAR // use aniso if min filter is LINEAR_MIPMAP_LINEAR
samplerInfo.anisotropic_filtering = (samplerInfo.minify == gfx::Filter::kLinear && samplerInfo.mipmap == gfx::Filter::kLinear); samplerInfo.anisotropic_filtering = (samplerInfo.minify == gfx::Filter::LINEAR && samplerInfo.mipmap == gfx::Filter::LINEAR);
const tg::Image& image = model.images.at(texture.source); const tg::Image& image = model.images.at(texture.source);
if (image.as_is == false && image.bits == 8 && image.component == 4 && image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) { if (image.as_is == false && image.bits == 8 && image.component == 4 && image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
@ -265,9 +275,9 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
if (colour_textures.contains(c) == false) { if (colour_textures.contains(c) == false) {
const uint8_t pixel[4] = {c.r, c.g, c.b, c.a}; const uint8_t pixel[4] = {c.r, c.g, c.b, c.a};
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
colour_textures.emplace(std::make_pair(c, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, true))); colour_textures.emplace(std::make_pair(c, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, true)));
} }
@ -294,9 +304,9 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
if (metal_rough_textures.contains(mr) == false) { if (metal_rough_textures.contains(mr) == false) {
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a}; const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
gfx::SamplerInfo samplerInfo{}; gfx::SamplerInfo samplerInfo{};
samplerInfo.minify = gfx::Filter::kNearest; samplerInfo.minify = gfx::Filter::NEAREST;
samplerInfo.magnify = gfx::Filter::kNearest; samplerInfo.magnify = gfx::Filter::NEAREST;
samplerInfo.mipmap = gfx::Filter::kNearest; samplerInfo.mipmap = gfx::Filter::NEAREST;
samplerInfo.anisotropic_filtering = false; samplerInfo.anisotropic_filtering = false;
metal_rough_textures.emplace(std::make_pair(mr, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, false))); metal_rough_textures.emplace(std::make_pair(mr, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, false)));
} }
@ -672,4 +682,4 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
return parent; return parent;
} }
} // namespace engine::util } // namespace engine

View File

@ -22,17 +22,17 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
{ {
auto& binding0 = globalSetBindings.emplace_back(); auto& binding0 = globalSetBindings.emplace_back();
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer; binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stage_flags = gfx::ShaderStageFlags::kVertex; binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
auto& binding1 = globalSetBindings.emplace_back(); auto& binding1 = globalSetBindings.emplace_back();
binding1.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; binding1.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
binding1.stage_flags = gfx::ShaderStageFlags::kFragment; binding1.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
auto& binding2 = globalSetBindings.emplace_back(); auto& binding2 = globalSetBindings.emplace_back();
binding2.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; binding2.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
binding2.stage_flags = gfx::ShaderStageFlags::kFragment; binding2.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
} }
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings); global_uniform.layout = device_->createDescriptorSetLayout(globalSetBindings);
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout); global_uniform.set = device_->allocateDescriptorSet(global_uniform.layout);
const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f; const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f;
// const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f}; // const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f};
const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f); const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f);
@ -40,34 +40,34 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f}); const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f});
global_uniform.uniform_buffer_data.data.proj = light_proj; global_uniform.uniform_buffer_data.data.proj = light_proj;
global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view; global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view;
global_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); global_uniform.uniform_buffer = device_->createUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
device_->UpdateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data)); device_->updateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data));
// binding1 is updated towards the end of the constructor once the skybox texture is loaded // binding1 is updated towards the end of the constructor once the skybox texture is loaded
// binding2 is updated just after that // binding2 is updated just after that
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
{ {
auto& binding0 = frameSetBindings.emplace_back(); auto& binding0 = frameSetBindings.emplace_back();
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer; binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
binding0.stage_flags = gfx::ShaderStageFlags::kVertex; binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
} }
frame_uniform.layout = device_->CreateDescriptorSetLayout(frameSetBindings); frame_uniform.layout = device_->createDescriptorSetLayout(frameSetBindings);
frame_uniform.set = device_->AllocateDescriptorSet(frame_uniform.layout); frame_uniform.set = device_->allocateDescriptorSet(frame_uniform.layout);
frame_uniform.uniform_buffer_data.data = light_view; frame_uniform.uniform_buffer_data.data = light_view;
frame_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); frame_uniform.uniform_buffer = device_->createUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
device_->UpdateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data)); device_->updateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data));
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings; std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
gfx::DescriptorSetLayoutBinding materialSetBinding{}; gfx::DescriptorSetLayoutBinding materialSetBinding{};
materialSetBinding.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; materialSetBinding.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
materialSetBinding.stage_flags = gfx::ShaderStageFlags::kFragment; materialSetBinding.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
materialSetBindings.push_back(materialSetBinding); // albedo materialSetBindings.push_back(materialSetBinding); // albedo
materialSetBindings.push_back(materialSetBinding); // normal materialSetBindings.push_back(materialSetBinding); // normal
materialSetBindings.push_back(materialSetBinding); // occlusion materialSetBindings.push_back(materialSetBinding); // occlusion
materialSetBindings.push_back(materialSetBinding); // metallic-roughness materialSetBindings.push_back(materialSetBinding); // metallic-roughness
material_set_layout = device_->CreateDescriptorSetLayout(materialSetBindings); material_set_layout = device_->createDescriptorSetLayout(materialSetBindings);
device_->SetupImguiBackend(); device_->setupImguiBackend();
gfx::VertexFormat debug_vertex_format{}; gfx::VertexFormat debug_vertex_format{};
debug_vertex_format.stride = 0; debug_vertex_format.stride = 0;
@ -79,12 +79,12 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
debug_pipeline_info.frag_shader_path = getResourcePath("engine/shaders/debug.frag"); debug_pipeline_info.frag_shader_path = getResourcePath("engine/shaders/debug.frag");
debug_pipeline_info.vertex_format = debug_vertex_format; debug_pipeline_info.vertex_format = debug_vertex_format;
debug_pipeline_info.alpha_blending = false; debug_pipeline_info.alpha_blending = false;
debug_pipeline_info.face_cull_mode = gfx::CullMode::kCullNone; // probably ignored for line rendering debug_pipeline_info.face_cull_mode = gfx::CullMode::CULL_NONE; // probably ignored for line rendering
debug_pipeline_info.write_z = false; // lines don't need the depth buffer debug_pipeline_info.write_z = false; // lines don't need the depth buffer
// debug_pipeline_info.descriptor_set_layouts = empty; // debug_pipeline_info.descriptor_set_layouts = empty;
debug_pipeline_info.line_primitives = true; debug_pipeline_info.line_primitives = true;
debug_rendering_things_.pipeline = device_->CreatePipeline(debug_pipeline_info); debug_rendering_things_.pipeline = device_->createPipeline(debug_pipeline_info);
} }
// create the skybox cubemap and update global skybox combined-image-sampler // create the skybox cubemap and update global skybox combined-image-sampler
@ -97,29 +97,29 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
for (int face = 0; face < 6; ++face) { for (int face = 0; face < 6; ++face) {
std::string path = std::string("engine/textures/skybox") + std::to_string(face) + std::string(".jpg"); std::string path = std::string("engine/textures/skybox") + std::to_string(face) + std::string(".jpg");
face_unq_ptrs[face] = ReadImageFile(getResourcePath(path), w, h); face_unq_ptrs[face] = readImageFile(getResourcePath(path), w, h);
if (cubemap_w != w || cubemap_h != h) throw std::runtime_error("Skybox textures must be 512x512!"); if (cubemap_w != w || cubemap_h != h) throw std::runtime_error("Skybox textures must be 512x512!");
face_unsafe_ptrs[face] = face_unq_ptrs[face]->data(); face_unsafe_ptrs[face] = face_unq_ptrs[face]->data();
} }
skybox_cubemap = device_->CreateImageCubemap(cubemap_w, cubemap_h, gfx::ImageFormat::kSRGB, face_unsafe_ptrs); skybox_cubemap = device_->createImageCubemap(cubemap_w, cubemap_h, gfx::ImageFormat::SRGB, face_unsafe_ptrs);
gfx::SamplerInfo sampler_info{}; gfx::SamplerInfo sampler_info{};
sampler_info.magnify = gfx::Filter::kLinear; sampler_info.magnify = gfx::Filter::LINEAR;
sampler_info.minify = gfx::Filter::kLinear; sampler_info.minify = gfx::Filter::LINEAR;
sampler_info.mipmap = gfx::Filter::kLinear; sampler_info.mipmap = gfx::Filter::LINEAR;
sampler_info.wrap_u = gfx::WrapMode::kClampToEdge; sampler_info.wrap_u = gfx::WrapMode::CLAMP_TO_EDGE;
sampler_info.wrap_v = gfx::WrapMode::kClampToEdge; sampler_info.wrap_v = gfx::WrapMode::CLAMP_TO_EDGE;
sampler_info.wrap_w = gfx::WrapMode::kClampToEdge; sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_EDGE;
sampler_info.anisotropic_filtering = true; sampler_info.anisotropic_filtering = true;
skybox_sampler = device_->CreateSampler(sampler_info); skybox_sampler = device_->createSampler(sampler_info);
device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler); device_->updateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler);
} }
// create skybox shader // create skybox shader
{ {
gfx::VertexFormat vertex_format{}; gfx::VertexFormat vertex_format{};
vertex_format.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::kFloat3, 0u); vertex_format.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::FLOAT3, 0u);
vertex_format.stride = 3 * sizeof(float); vertex_format.stride = 3 * sizeof(float);
gfx::PipelineInfo pipeline_info{}; gfx::PipelineInfo pipeline_info{};
@ -127,13 +127,13 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
pipeline_info.frag_shader_path = getResourcePath("engine/shaders/skybox.frag"); pipeline_info.frag_shader_path = getResourcePath("engine/shaders/skybox.frag");
pipeline_info.vertex_format = vertex_format; pipeline_info.vertex_format = vertex_format;
pipeline_info.alpha_blending = false; pipeline_info.alpha_blending = false;
pipeline_info.face_cull_mode = gfx::CullMode::kCullBack; pipeline_info.face_cull_mode = gfx::CullMode::CULL_BACK;
pipeline_info.write_z = false; pipeline_info.write_z = false;
pipeline_info.line_primitives = false; pipeline_info.line_primitives = false;
pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout()); pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout());
pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout()); pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout());
skybox_pipeline = device_->CreatePipeline(pipeline_info); skybox_pipeline = device_->createPipeline(pipeline_info);
} }
// create skybox vertex buffer // create skybox vertex buffer
@ -189,19 +189,19 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
std::swap(v[i], v[i + 2]); std::swap(v[i], v[i + 2]);
} }
skybox_buffer = device_->CreateBuffer(gfx::BufferType::kVertex, v.size() * sizeof(glm::vec3), v.data()); skybox_buffer = device_->createBuffer(gfx::BufferType::VERTEX, v.size() * sizeof(glm::vec3), v.data());
} }
// shadow map pipeline // shadow map pipeline
gfx::VertexFormat shadowVertexFormat{}; gfx::VertexFormat shadowVertexFormat{};
shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped
shadowVertexFormat.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::kFloat3, 0u); // position shadowVertexFormat.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::FLOAT3, 0u); // position
shadowVertexFormat.attribute_descriptions.emplace_back(1u, gfx::VertexAttribFormat::kFloat2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv shadowVertexFormat.attribute_descriptions.emplace_back(1u, gfx::VertexAttribFormat::FLOAT2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv
gfx::PipelineInfo shadowPipelineInfo{}; gfx::PipelineInfo shadowPipelineInfo{};
shadowPipelineInfo.vert_shader_path = getResourcePath("engine/shaders/shadow.vert"); shadowPipelineInfo.vert_shader_path = getResourcePath("engine/shaders/shadow.vert");
shadowPipelineInfo.frag_shader_path = getResourcePath("engine/shaders/shadow.frag"); shadowPipelineInfo.frag_shader_path = getResourcePath("engine/shaders/shadow.frag");
shadowPipelineInfo.vertex_format = shadowVertexFormat; shadowPipelineInfo.vertex_format = shadowVertexFormat;
shadowPipelineInfo.face_cull_mode = gfx::CullMode::kCullFront; // shadows care about back faces shadowPipelineInfo.face_cull_mode = gfx::CullMode::CULL_FRONT; // shadows care about back faces
shadowPipelineInfo.alpha_blending = false; shadowPipelineInfo.alpha_blending = false;
shadowPipelineInfo.write_z = true; shadowPipelineInfo.write_z = true;
shadowPipelineInfo.line_primitives = false; shadowPipelineInfo.line_primitives = false;
@ -209,140 +209,142 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout()); shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout());
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetFrameSetLayout()); shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetFrameSetLayout());
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout()); shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout());
shadow_pipeline = device_->CreatePipeline(shadowPipelineInfo); shadow_pipeline = device_->createPipeline(shadowPipelineInfo);
// shadow map image and sampler // shadow map image and sampler
shadow_map = device_->CreateShadowmapImage(); shadow_map = device_->createImageShadowmap();
gfx::SamplerInfo sampler_info{}; gfx::SamplerInfo sampler_info{};
sampler_info.magnify = gfx::Filter::kLinear; sampler_info.magnify = gfx::Filter::LINEAR;
sampler_info.minify = gfx::Filter::kLinear; sampler_info.minify = gfx::Filter::LINEAR;
sampler_info.mipmap = gfx::Filter::kNearest; // bilinear is apparently good for shadow maps, mips aren't used anyway sampler_info.mipmap = gfx::Filter::NEAREST; // bilinear is apparently good for shadow maps, mips aren't used anyway
sampler_info.wrap_u = gfx::WrapMode::kClampToBorder; // sampler reads 1.0 out of bounds which ensures no shadowing there sampler_info.wrap_u = gfx::WrapMode::CLAMP_TO_BORDER; // sampler reads 1.0 out of bounds which ensures no shadowing there
sampler_info.wrap_v = gfx::WrapMode::kClampToBorder; sampler_info.wrap_v = gfx::WrapMode::CLAMP_TO_BORDER;
sampler_info.wrap_w = gfx::WrapMode::kClampToBorder; sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_BORDER;
sampler_info.anisotropic_filtering = false; // no mip-maps so aniso won't do anything sampler_info.anisotropic_filtering = false; // no mip-maps so aniso won't do anything
shadow_map_sampler = device_->CreateSampler(sampler_info); shadow_map_sampler = device_->createSampler(sampler_info);
device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler); device_->updateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler);
}; };
Renderer::~Renderer() Renderer::~Renderer()
{ {
device_->DestroySampler(shadow_map_sampler); device_->destroySampler(shadow_map_sampler);
device_->DestroyImage(shadow_map); device_->destroyImage(shadow_map);
device_->DestroyPipeline(shadow_pipeline); device_->destroyPipeline(shadow_pipeline);
device_->DestroyBuffer(skybox_buffer); device_->destroyBuffer(skybox_buffer);
device_->DestroyPipeline(skybox_pipeline); device_->destroyPipeline(skybox_pipeline);
device_->DestroySampler(skybox_sampler); device_->destroySampler(skybox_sampler);
device_->DestroyImage(skybox_cubemap); device_->destroyImage(skybox_cubemap);
device_->DestroyPipeline(debug_rendering_things_.pipeline); device_->destroyPipeline(debug_rendering_things_.pipeline);
for (const auto& [info, sampler] : samplers) { for (const auto& [info, sampler] : samplers) {
device_->DestroySampler(sampler); device_->destroySampler(sampler);
} }
device_->DestroyDescriptorSetLayout(material_set_layout); device_->destroyDescriptorSetLayout(material_set_layout);
device_->DestroyUniformBuffer(frame_uniform.uniform_buffer); device_->destroyUniformBuffer(frame_uniform.uniform_buffer);
device_->DestroyDescriptorSetLayout(frame_uniform.layout); device_->destroyDescriptorSetLayout(frame_uniform.layout);
device_->DestroyUniformBuffer(global_uniform.uniform_buffer); device_->destroyUniformBuffer(global_uniform.uniform_buffer);
device_->DestroyDescriptorSetLayout(global_uniform.layout); device_->destroyDescriptorSetLayout(global_uniform.layout);
} }
void Renderer::Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list, const std::vector<DebugLine>& debug_lines) void Renderer::Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list,
const std::vector<DebugLine>& debug_lines)
{ {
if (window_is_resized) { if (window_is_resized) {
uint32_t w, h; uint32_t w, h;
device_->GetViewportSize(&w, &h); device_->getViewportSize(&w, &h);
viewport_aspect_ratio_ = (float)w / (float)h; viewport_aspect_ratio_ = (float)w / (float)h;
const glm::mat4 proj_matrix = const glm::mat4 proj_matrix =
glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far); glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far);
/* update SET 0 (rarely changing uniforms)*/ /* update SET 0 (rarely changing uniforms)*/
global_uniform.uniform_buffer_data.data.proj = proj_matrix; global_uniform.uniform_buffer_data.data.proj = proj_matrix;
device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); device_->writeUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
} }
const glm::mat4 view_matrix = glm::inverse(camera_transform); const glm::mat4 view_matrix = glm::inverse(camera_transform);
frame_uniform.uniform_buffer_data.data = view_matrix; frame_uniform.uniform_buffer_data.data = view_matrix;
device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); device_->writeUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
if (rendering_started == false) { if (rendering_started == false) {
// render to shadow map // render to shadow map
gfx::DrawBuffer* shadow_draw = device_->BeginShadowmapRender(shadow_map); gfx::DrawBuffer* shadow_draw = device_->beginShadowmapRender(shadow_map);
device_->CmdBindPipeline(shadow_draw, shadow_pipeline); device_->cmdBindPipeline(shadow_draw, shadow_pipeline);
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix device_->cmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
if (static_list) { // only create shadow map with static meshes if (static_list) { // only create shadow map with static meshes
if (!static_list->empty()) { for (const auto& entry : *static_list) {
for (const auto& entry : *static_list) { device_->cmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
device_->CmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix); device_->cmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2); // need to sample base color texture for alpha clipping
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2); device_->cmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
device_->CmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer); device_->cmdBindIndexBuffer(shadow_draw, entry.index_buffer);
device_->CmdBindIndexBuffer(shadow_draw, entry.index_buffer); device_->cmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
device_->CmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
}
} }
} }
device_->FinishShadowmapRender(shadow_draw, shadow_map); device_->finishShadowmapRender(shadow_draw, shadow_map);
} }
rendering_started = true; rendering_started = true;
last_bound_pipeline_ = nullptr; last_bound_pipeline_ = nullptr;
gfx::DrawBuffer* draw_buffer = device_->BeginRender(window_is_resized); gfx::DrawBuffer* draw_buffer = device_->beginRender(window_is_resized);
// Draw static objects
if (static_list) { if (static_list) {
if (!static_list->empty()) { if (!static_list->empty()) {
DrawRenderList(draw_buffer, *static_list); DrawRenderList(draw_buffer, *static_list);
} }
} }
// Draw moving objects
if (dynamic_list) { if (dynamic_list) {
if (!dynamic_list->empty()) { if (!dynamic_list->empty()) {
DrawRenderList(draw_buffer, *dynamic_list); DrawRenderList(draw_buffer, *dynamic_list);
} }
} }
// draw skybox
{
device_->cmdBindPipeline(draw_buffer, skybox_pipeline);
device_->cmdBindDescriptorSet(draw_buffer, skybox_pipeline, global_uniform.set, 0);
device_->cmdBindDescriptorSet(draw_buffer, skybox_pipeline, frame_uniform.set, 1);
device_->cmdBindVertexBuffer(draw_buffer, 0, skybox_buffer);
device_->cmdDraw(draw_buffer, 36, 1, 0, 0);
}
struct DebugPush { struct DebugPush {
glm::vec4 pos1; glm::vec4 pos1;
glm::vec4 pos2; glm::vec4 pos2;
glm::vec3 color; glm::vec3 color;
}; };
// draw skybox
{
device_->CmdBindPipeline(draw_buffer, skybox_pipeline);
device_->CmdBindDescriptorSet(draw_buffer, skybox_pipeline, global_uniform.set, 0);
device_->CmdBindDescriptorSet(draw_buffer, skybox_pipeline, frame_uniform.set, 1);
device_->CmdBindVertexBuffer(draw_buffer, 0, skybox_buffer);
device_->CmdDraw(draw_buffer, 36, 1, 0, 0);
}
// draw debug shit here // draw debug shit here
device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline); device_->cmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
DebugPush push{}; DebugPush push{};
for (const DebugLine& l : debug_lines) { for (const DebugLine& l : debug_lines) {
push.pos1 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f); push.pos1 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f);
push.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f); push.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
push.color = l.color; push.color = l.color;
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push); device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0); device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
} }
// also make a lil crosshair // also make a lil crosshair
push.color = glm::vec3{1.0f, 1.0f, 1.0f}; push.color = glm::vec3{1.0f, 1.0f, 1.0f};
push.pos1 = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f); push.pos1 = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
push.pos2 = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f); push.pos2 = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f);
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push); device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0); device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
push.pos1 = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f); push.pos1 = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
push.pos2 = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f); push.pos2 = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f);
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push); device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
device_->CmdDraw(draw_buffer, 2, 1, 0, 0); device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData()); device_->cmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
device_->FinishRender(draw_buffer); device_->finishRender(draw_buffer);
} }
void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list) void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list)
@ -351,22 +353,22 @@ void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& re
if (last_bound_pipeline_ == nullptr) { if (last_bound_pipeline_ == nullptr) {
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline; const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
// these bindings persist between all pipelines // these bindings persist between all pipelines
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0); device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1); device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
device_->CmdBindPipeline(draw_buffer, first_pipeline); device_->cmdBindPipeline(draw_buffer, first_pipeline);
last_bound_pipeline_ = first_pipeline; last_bound_pipeline_ = first_pipeline;
} }
for (const auto& entry : render_list) { for (const auto& entry : render_list) {
if (entry.pipeline != last_bound_pipeline_) { if (entry.pipeline != last_bound_pipeline_) {
device_->CmdBindPipeline(draw_buffer, entry.pipeline); device_->cmdBindPipeline(draw_buffer, entry.pipeline);
last_bound_pipeline_ = entry.pipeline; last_bound_pipeline_ = entry.pipeline;
} }
device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, entry.material_set, 2); device_->cmdBindDescriptorSet(draw_buffer, entry.pipeline, entry.material_set, 2);
device_->CmdPushConstants(draw_buffer, entry.pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix); device_->cmdPushConstants(draw_buffer, entry.pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer); device_->cmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer); device_->cmdBindIndexBuffer(draw_buffer, entry.index_buffer);
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0); device_->cmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
} }
} }

View File

@ -12,7 +12,7 @@ namespace engine {
Font::Font(const std::string& path) Font::Font(const std::string& path)
{ {
m_font_buffer = ReadBinaryFile(path); m_font_buffer = readBinaryFile(path);
m_font_info = std::make_unique<stbtt_fontinfo>(); m_font_info = std::make_unique<stbtt_fontinfo>();
if (stbtt_InitFont(m_font_info.get(), m_font_buffer->data(), 0) == 0) { if (stbtt_InitFont(m_font_info.get(), m_font_buffer->data(), 0) == 0) {

View File

@ -7,27 +7,27 @@ namespace engine {
Material::Material(Renderer* renderer, std::shared_ptr<Shader> shader) : m_shader(shader), m_renderer(renderer) Material::Material(Renderer* renderer, std::shared_ptr<Shader> shader) : m_shader(shader), m_renderer(renderer)
{ {
m_material_set = renderer->GetDevice()->AllocateDescriptorSet(renderer->GetMaterialSetLayout()); m_material_set = renderer->GetDevice()->allocateDescriptorSet(renderer->GetMaterialSetLayout());
LOG_DEBUG("Created material"); LOG_DEBUG("Created material");
} }
Material::~Material() { m_renderer->GetDevice()->FreeDescriptorSet(m_material_set); LOG_DEBUG("Destroyed material"); } Material::~Material() { m_renderer->GetDevice()->freeDescriptorSet(m_material_set); LOG_DEBUG("Destroyed material"); }
void Material::setAlbedoTexture(std::shared_ptr<Texture> texture) void Material::setAlbedoTexture(std::shared_ptr<Texture> texture)
{ {
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 0, texture->GetImage(), texture->GetSampler()); m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 0, texture->GetImage(), texture->GetSampler());
m_texture_albedo = texture; m_texture_albedo = texture;
} }
void Material::setNormalTexture(std::shared_ptr<Texture> texture) void Material::setNormalTexture(std::shared_ptr<Texture> texture)
{ {
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 1, texture->GetImage(), texture->GetSampler()); m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 1, texture->GetImage(), texture->GetSampler());
m_texture_normal = texture; m_texture_normal = texture;
} }
void Material::setOcclusionRoughnessMetallicTexture(std::shared_ptr<Texture> texture) void Material::setOcclusionRoughnessMetallicTexture(std::shared_ptr<Texture> texture)
{ {
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 2, texture->GetImage(), texture->GetSampler()); m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 2, texture->GetImage(), texture->GetSampler());
m_texture_occlusion_roughness_metallic = texture; m_texture_occlusion_roughness_metallic = texture;
} }

View File

@ -18,8 +18,8 @@ Mesh::Mesh(GFXDevice* gfx, const std::vector<Vertex>& vertices, const std::vecto
Mesh::~Mesh() Mesh::~Mesh()
{ {
m_gfx->DestroyBuffer(m_ib); m_gfx->destroyBuffer(m_ib);
m_gfx->DestroyBuffer(m_vb); m_gfx->destroyBuffer(m_vb);
LOG_DEBUG("Destroyed mesh"); LOG_DEBUG("Destroyed mesh");
} }
@ -31,8 +31,8 @@ uint32_t Mesh::getCount() { return m_count; }
void Mesh::initMesh(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices) void Mesh::initMesh(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices)
{ {
m_vb = m_gfx->CreateBuffer(gfx::BufferType::kVertex, vertices.size() * sizeof(Vertex), vertices.data()); m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data());
m_ib = m_gfx->CreateBuffer(gfx::BufferType::kIndex, indices.size() * sizeof(uint32_t), indices.data()); m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data());
m_count = (uint32_t)indices.size(); m_count = (uint32_t)indices.size();
LOG_DEBUG("Created mesh, vertices: {}, indices: {}", vertices.size(), indices.size()); LOG_DEBUG("Created mesh, vertices: {}, indices: {}", vertices.size(), indices.size());
} }

View File

@ -19,27 +19,27 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
gfx::VertexFormat vertFormat{}; gfx::VertexFormat vertFormat{};
vertFormat.attribute_descriptions.emplace_back( vertFormat.attribute_descriptions.emplace_back(
index++, gfx::VertexAttribFormat::kFloat3, stride); index++, gfx::VertexAttribFormat::FLOAT3, stride);
stride += 3 * sizeof(float); stride += 3 * sizeof(float);
if (settings.vertexParams.has_normal) { if (settings.vertexParams.has_normal) {
vertFormat.attribute_descriptions.emplace_back( vertFormat.attribute_descriptions.emplace_back(
index++, gfx::VertexAttribFormat::kFloat3, stride); index++, gfx::VertexAttribFormat::FLOAT3, stride);
stride += 3 * sizeof(float); stride += 3 * sizeof(float);
} }
if (settings.vertexParams.has_tangent) { if (settings.vertexParams.has_tangent) {
vertFormat.attribute_descriptions.emplace_back( vertFormat.attribute_descriptions.emplace_back(
index++, gfx::VertexAttribFormat::kFloat4, stride); index++, gfx::VertexAttribFormat::FLOAT4, stride);
stride += 4 * sizeof(float); stride += 4 * sizeof(float);
} }
if (settings.vertexParams.has_color) { if (settings.vertexParams.has_color) {
vertFormat.attribute_descriptions.emplace_back( vertFormat.attribute_descriptions.emplace_back(
index++, gfx::VertexAttribFormat::kFloat4, stride); index++, gfx::VertexAttribFormat::FLOAT4, stride);
stride += 4 * sizeof(float); stride += 4 * sizeof(float);
} }
if (settings.vertexParams.has_uv0) { if (settings.vertexParams.has_uv0) {
vertFormat.attribute_descriptions.emplace_back( vertFormat.attribute_descriptions.emplace_back(
index++, gfx::VertexAttribFormat::kFloat2, stride); index++, gfx::VertexAttribFormat::FLOAT2, stride);
stride += 2 * sizeof(float); stride += 2 * sizeof(float);
} }
vertFormat.stride = stride; vertFormat.stride = stride;
@ -49,21 +49,21 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
info.frag_shader_path = fragPath; info.frag_shader_path = fragPath;
info.vertex_format = vertFormat; info.vertex_format = vertFormat;
info.alpha_blending = settings.alpha_blending; info.alpha_blending = settings.alpha_blending;
info.face_cull_mode = settings.cull_backface ? gfx::CullMode::kCullBack : gfx::CullMode::kCullNone; info.face_cull_mode = settings.cull_backface ? gfx::CullMode::CULL_BACK : gfx::CullMode::CULL_NONE;
info.write_z = settings.write_z; info.write_z = settings.write_z;
info.line_primitives = false; info.line_primitives = false;
info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout()); info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout());
info.descriptor_set_layouts.push_back(renderer->GetFrameSetLayout()); info.descriptor_set_layouts.push_back(renderer->GetFrameSetLayout());
info.descriptor_set_layouts.push_back(renderer->GetMaterialSetLayout()); info.descriptor_set_layouts.push_back(renderer->GetMaterialSetLayout());
pipeline_ = gfx_->CreatePipeline(info); pipeline_ = gfx_->createPipeline(info);
LOG_DEBUG("Created shader: {}, pipeline: {}", vertPath, LOG_DEBUG("Created shader: {}, pipeline: {}", vertPath,
static_cast<const void*>(pipeline_)); static_cast<const void*>(pipeline_));
} }
Shader::~Shader() { Shader::~Shader() {
gfx_->DestroyPipeline(pipeline_); gfx_->destroyPipeline(pipeline_);
LOG_DEBUG("Destroyed shader, pipeline: {}", static_cast<const void*>(pipeline_)); LOG_DEBUG("Destroyed shader, pipeline: {}", static_cast<const void*>(pipeline_));
} }

View File

@ -12,12 +12,12 @@ namespace engine {
Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, gfx::SamplerInfo samplerInfo, bool srgb) : gfx_(renderer->GetDevice()) Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, gfx::SamplerInfo samplerInfo, bool srgb) : gfx_(renderer->GetDevice())
{ {
if (renderer->samplers.contains(samplerInfo) == false) { if (renderer->samplers.contains(samplerInfo) == false) {
renderer->samplers.insert(std::make_pair(samplerInfo, gfx_->CreateSampler(samplerInfo))); renderer->samplers.insert(std::make_pair(samplerInfo, gfx_->createSampler(samplerInfo)));
} }
gfx::ImageFormat format = srgb ? gfx::ImageFormat::kSRGB : gfx::ImageFormat::kLinear; gfx::ImageFormat format = srgb ? gfx::ImageFormat::SRGB : gfx::ImageFormat::LINEAR;
image_ = gfx_->CreateImage(width, height, format, bitmap); image_ = gfx_->createImage(width, height, format, bitmap);
sampler_ = renderer->samplers.at(samplerInfo); sampler_ = renderer->samplers.at(samplerInfo);
LOG_DEBUG("Created texture: width: {}, height: {}", width, height); LOG_DEBUG("Created texture: width: {}, height: {}", width, height);
@ -25,14 +25,14 @@ Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int heigh
Texture::~Texture() Texture::~Texture()
{ {
gfx_->DestroyImage(image_); gfx_->destroyImage(image_);
LOG_DEBUG("Destroyed texture"); LOG_DEBUG("Destroyed texture");
} }
std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, gfx::SamplerInfo samplerInfo, Renderer* renderer, bool srgb) std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, gfx::SamplerInfo samplerInfo, Renderer* renderer, bool srgb)
{ {
int width, height; int width, height;
auto bitmap = ReadImageFile(path, width, height); auto bitmap = readImageFile(path, width, height);
return std::make_unique<Texture>(renderer, bitmap->data(), width, height, samplerInfo, srgb); return std::make_unique<Texture>(renderer, bitmap->data(), width, height, samplerInfo, srgb);
} }

View File

@ -64,7 +64,7 @@ void Scene::Update(float ts) {
system->onUpdate(ts); system->onUpdate(ts);
} }
event_system_->DespatchEvents(); // clears event queue event_system_->despatchEvents(); // clears event queue
} }
} // namespace engine } // namespace engine

View File

@ -55,13 +55,13 @@ namespace engine {
VkPresentModeKHR present_mode_requested; VkPresentModeKHR present_mode_requested;
switch (info.requested_present_mode) { switch (info.requested_present_mode) {
case gfx::PresentMode::kDoubleBufferedNoVsync: case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR; present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR;
break; break;
case gfx::PresentMode::kDoubleBufferedVsync: case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
present_mode_requested = VK_PRESENT_MODE_FIFO_KHR; present_mode_requested = VK_PRESENT_MODE_FIFO_KHR;
break; break;
case gfx::PresentMode::kTripleBuffered: case gfx::PresentMode::TRIPLE_BUFFERED:
present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR; present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR;
} }
sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available

View File

@ -62,7 +62,7 @@ void CameraControllerSystem::onUpdate(float ts)
// keep vel.z as gravity can increase it every frame // keep vel.z as gravity can increase it every frame
// gravity stuff here: // gravity stuff here:
c->vel.z += CameraControllerComponent::kGravAccel * dt; c->vel.z += c->grav_accel * dt;
// jumping // jumping
if (m_scene->app()->getInputManager()->GetButtonPress("jump") && (c->grounded || c->noclip)) { if (m_scene->app()->getInputManager()->GetButtonPress("jump") && (c->grounded || c->noclip)) {
@ -208,6 +208,15 @@ void CameraControllerSystem::onUpdate(float ts)
c->noclip ^= true; c->noclip ^= true;
} }
if (m_scene->app()->getWindow()->GetKeyPress(engine::inputs::Key::K_T)) {
if (c->grav_accel != 0.0f) {
c->grav_accel = 0.0f;
}
else {
c->grav_accel = -9.81f;
}
}
if (m_scene->app()->getWindow()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) { if (m_scene->app()->getWindow()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
engine::Ray ray{}; engine::Ray ray{};
ray.origin = t->position; ray.origin = t->position;

View File

@ -25,14 +25,14 @@ struct CameraControllerComponent {
static constexpr float kMaxStairHeight = 0.2f; static constexpr float kMaxStairHeight = 0.2f;
static constexpr size_t kNumHorizontalRays = 20; static constexpr size_t kNumHorizontalRays = 20;
static constexpr float kGravAccel = -9.81f; float grav_accel = -9.81f;
// static constexpr float kGravAccel = -1.625f; // moon gravity // grav_accel = -1.625f; // moon gravity
static constexpr float kMaxDistanceFromOrigin = 200.0f; static constexpr float kMaxDistanceFromOrigin = 200.0f;
bool noclip = false; bool noclip = false;
float yaw = 0.0f; float yaw = 0.0f;
//float pitch = glm::half_pi<float>(); // float pitch = glm::half_pi<float>();
float pitch = 0.0f; float pitch = 0.0f;
glm::vec3 vel{0.0f, 0.0f, 0.0f}; glm::vec3 vel{0.0f, 0.0f, 0.0f};
bool grounded = false; bool grounded = false;
@ -41,7 +41,7 @@ struct CameraControllerComponent {
}; };
class CameraControllerSystem : public engine::System { class CameraControllerSystem : public engine::System {
public: public:
CameraControllerSystem(engine::Scene* scene); CameraControllerSystem(engine::Scene* scene);
// engine::System overrides // engine::System overrides

View File

@ -47,9 +47,9 @@ void PlayGame(GameSettings settings)
engine::gfx::GraphicsSettings graphics_settings{}; engine::gfx::GraphicsSettings graphics_settings{};
graphics_settings.enable_validation = settings.enable_validation; graphics_settings.enable_validation = settings.enable_validation;
graphics_settings.present_mode = engine::gfx::PresentMode::kTripleBuffered; graphics_settings.present_mode = engine::gfx::PresentMode::TRIPLE_BUFFERED;
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff; graphics_settings.msaa_level = engine::gfx::MSAALevel::MSAA_OFF;
graphics_settings.enable_anisotropy = true; graphics_settings.enable_anisotropy = false;
engine::AppConfiguration configuration{}; engine::AppConfiguration configuration{};
configuration.enable_frame_limiter = settings.enable_frame_limiter; configuration.enable_frame_limiter = settings.enable_frame_limiter;
@ -66,7 +66,7 @@ void PlayGame(GameSettings settings)
/* as of right now, the entity with tag 'camera' is used to build the view /* as of right now, the entity with tag 'camera' is used to build the view
* matrix */ * matrix */
//engine::Entity temple = engine::util::LoadGLTF(*start_scene, "C:/games/temple.glb", true); //engine::Entity temple = engine::loadGLTF(*start_scene, "C:/games/temple.glb", true);
start_scene->RegisterComponent<CameraControllerComponent>(); start_scene->RegisterComponent<CameraControllerComponent>();
start_scene->RegisterSystemAtIndex<CameraControllerSystem>(0); start_scene->RegisterSystemAtIndex<CameraControllerSystem>(0);
@ -98,36 +98,38 @@ void PlayGame(GameSettings settings)
main_scene->AddComponent<CameraControllerComponent>(camera); main_scene->AddComponent<CameraControllerComponent>(camera);
/* floor */ /* floor */
engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/floor2.glb"), true); engine::Entity floor = engine::loadGLTF(*main_scene, app.getResourcePath("models/floor2.glb"), true);
main_scene->GetScale(floor).x *= 100.0f;
main_scene->GetScale(floor).z *= 100.0f;
//main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false; //main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/monke.glb"), true); engine::Entity monke = engine::loadGLTF(*main_scene, app.getResourcePath("models/monke.glb"), true);
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f; main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
// engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/bottle.glb")); // engine::Entity bottle = engine::loadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"));
// main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 10.0f; // main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 10.0f;
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.x += 25.0f; // main_scene->GetComponent<engine::TransformComponent>(bottle)->position.x += 25.0f;
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f; // main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f;
engine::Entity helmet = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/DamagedHelmet.glb"), true); engine::Entity helmet = engine::loadGLTF(*main_scene, app.getResourcePath("models/DamagedHelmet.glb"), true);
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 5.0f}; main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 5.0f};
main_scene->GetScale(helmet) *= 3.0f; main_scene->GetScale(helmet) *= 3.0f;
main_scene->GetRotation(helmet) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f }); main_scene->GetRotation(helmet) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f });
main_scene->GetRotation(helmet) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f }); main_scene->GetRotation(helmet) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });
engine::Entity toycar = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/ToyCar.glb"), true); engine::Entity toycar = engine::loadGLTF(*main_scene, app.getResourcePath("models/ToyCar.glb"), true);
main_scene->GetScale(toycar) *= 150.0f; main_scene->GetScale(toycar) *= 150.0f;
main_scene->GetPosition(toycar).z -= 0.07f; main_scene->GetPosition(toycar).z -= 0.07f;
engine::Entity stairs = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/stairs.glb"), true); engine::Entity stairs = engine::loadGLTF(*main_scene, app.getResourcePath("models/stairs.glb"), true);
main_scene->GetPosition(stairs) += glm::vec3{-8.0f, -5.0f, 0.1f}; main_scene->GetPosition(stairs) += glm::vec3{-8.0f, -5.0f, 0.1f};
main_scene->GetRotation(stairs) = glm::angleAxis(glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f}); main_scene->GetRotation(stairs) = glm::angleAxis(glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f});
main_scene->GetRotation(stairs) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{1.0f, 0.0f, 0.0f}); main_scene->GetRotation(stairs) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{1.0f, 0.0f, 0.0f});
engine::Entity axes = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/MY_AXES.glb"), true); engine::Entity axes = engine::loadGLTF(*main_scene, app.getResourcePath("models/MY_AXES.glb"), true);
main_scene->GetPosition(axes) += glm::vec3{-40.0f, -40.0f, 1.0f}; main_scene->GetPosition(axes) += glm::vec3{-40.0f, -40.0f, 1.0f};
engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"), true); engine::Entity bottle = engine::loadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"), true);
main_scene->GetPosition(bottle).y -= 10.0f; main_scene->GetPosition(bottle).y -= 10.0f;
main_scene->GetPosition(bottle).z += 2.5f; main_scene->GetPosition(bottle).z += 2.5f;
main_scene->GetScale(bottle) *= 25.0f; main_scene->GetScale(bottle) *= 25.0f;
@ -149,15 +151,15 @@ void PlayGame(GameSettings settings)
}; };
engine::Entity teapot = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/teapot.glb"), true); engine::Entity teapot = engine::loadGLTF(*main_scene, app.getResourcePath("models/teapot.glb"), true);
main_scene->GetPosition(teapot).y += 5.0f; main_scene->GetPosition(teapot).y += 5.0f;
main_scene->GetPosition(teapot).x -= 5.0f; main_scene->GetPosition(teapot).x -= 5.0f;
main_scene->GetScale(teapot) *= 5.0f; main_scene->GetScale(teapot) *= 5.0f;
engine::Entity tree = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/tree.glb"), true); engine::Entity tree = engine::loadGLTF(*main_scene, app.getResourcePath("models/tree.glb"), true);
main_scene->GetPosition(tree) = glm::vec3{-5.0f, -5.0f, 0.0f}; main_scene->GetPosition(tree) = glm::vec3{-5.0f, -5.0f, 0.0f};
engine::Entity box = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/box.glb"), true); engine::Entity box = engine::loadGLTF(*main_scene, app.getResourcePath("models/box.glb"), true);
main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f }; main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f };
main_scene->GetScale(box) *= 10.0f; main_scene->GetScale(box) *= 10.0f;
main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f }); main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f });

View File

@ -73,7 +73,7 @@ std::unique_ptr<engine::Mesh> GenSphereMesh(engine::GFXDevice* gfx, float r, int
} }
} }
std::vector<uint32_t> indices = engine::util::GenTangents(vertices); std::vector<uint32_t> indices = engine::genTangents(vertices);
return std::make_unique<engine::Mesh>(gfx, vertices, indices); return std::make_unique<engine::Mesh>(gfx, vertices, indices);
} }
@ -137,7 +137,7 @@ std::unique_ptr<engine::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, float x, flo
} }
} }
std::vector<uint32_t> indices = engine::util::GenTangents(vertices); std::vector<uint32_t> indices = engine::genTangents(vertices);
return std::make_unique<engine::Mesh>(gfx, vertices, indices); return std::make_unique<engine::Mesh>(gfx, vertices, indices);
} }