mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
a little bit more reformatting
This commit is contained in:
parent
9b5fca62f5
commit
71e7f51195
@ -22,7 +22,7 @@ set(SRC_FILES
|
||||
"src/file_dialog.cpp"
|
||||
"src/files.cpp"
|
||||
"src/gen_tangents.cpp"
|
||||
"src/gfx_device_vulkan.cpp"
|
||||
"src/gfx_device.cpp"
|
||||
"src/gltf_loader.cpp"
|
||||
"src/input_manager.cpp"
|
||||
"src/renderer.cpp"
|
||||
|
46
CMakePresets.json
Normal file
46
CMakePresets.json
Normal 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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -9,21 +9,21 @@
|
||||
namespace engine {
|
||||
|
||||
enum class EventSubscriberKind {
|
||||
kEntity,
|
||||
ENTITY,
|
||||
};
|
||||
|
||||
// Event handler base-class
|
||||
template <typename T>
|
||||
class EventHandler {
|
||||
public:
|
||||
virtual void OnEvent(T data) = 0;
|
||||
virtual void onEvent(T data) = 0;
|
||||
};
|
||||
|
||||
// Event queue interface to allow for different type queues to be in the map
|
||||
class IEventQueue {
|
||||
public:
|
||||
virtual ~IEventQueue() {}
|
||||
virtual void DespatchEvents() = 0;
|
||||
virtual void despatchEvents() = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -31,42 +31,40 @@ class EventQueue : public IEventQueue {
|
||||
// holds events of type T and subscribers to those events
|
||||
|
||||
public:
|
||||
void Subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
void subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
{
|
||||
// For the time being, ignore kind (TODO)
|
||||
(void)kind;
|
||||
assert(subscribers_.contains(id) == false && "subscribing to an event with ID that's already in use!");
|
||||
subscribers_.emplace(id, handler);
|
||||
assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
|
||||
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)
|
||||
(void)kind;
|
||||
assert(subscribers_.contains(id) && "Attempt to submit event to non-existing subscriber!");
|
||||
EventHandler<T>* handler = subscribers_.at(id);
|
||||
event_queue_.emplace(handler, event);
|
||||
assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
|
||||
EventHandler<T>* handler = m_subscribers.at(id);
|
||||
m_event_queue.emplace(handler, event);
|
||||
}
|
||||
|
||||
void DespatchEvents() override
|
||||
void despatchEvents() override
|
||||
{
|
||||
while (event_queue_.empty() == false) {
|
||||
auto [handler, event] = event_queue_.front();
|
||||
handler->OnEvent(event);
|
||||
event_queue_.pop();
|
||||
while (m_event_queue.empty() == false) {
|
||||
auto [handler, event] = m_event_queue.front();
|
||||
handler->onEvent(event);
|
||||
m_event_queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, EventHandler<T>*> subscribers_;
|
||||
std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
|
||||
|
||||
struct QueuedEvent {
|
||||
QueuedEvent(EventHandler<T>* handler, T event) : handler(handler), event(event) {}
|
||||
|
||||
EventHandler<T>* handler;
|
||||
T event;
|
||||
};
|
||||
std::queue<QueuedEvent> event_queue_{};
|
||||
std::queue<QueuedEvent> m_event_queue{};
|
||||
};
|
||||
|
||||
class EventSystem {
|
||||
@ -77,42 +75,42 @@ class EventSystem {
|
||||
~EventSystem() {}
|
||||
|
||||
template <typename T>
|
||||
void RegisterEventType()
|
||||
void registerEventType()
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(event_queues_.contains(hash) == false && "Registering an event queue more than once!");
|
||||
event_queues_.emplace(hash, std::make_unique<EventQueue<T>>());
|
||||
assert(m_event_queues.contains(hash) == false && "Registering an event queue more than once!");
|
||||
m_event_queues.emplace(hash, std::make_unique<EventQueue<T>>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SubscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
void subscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get());
|
||||
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
|
||||
assert(queue != nullptr && "This cast should work?!! wot");
|
||||
queue->Subscribe(kind, id, handler);
|
||||
queue->subscribe(kind, id, handler);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void QueueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
|
||||
void queueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
|
||||
{
|
||||
size_t hash = typeid(T).hash_code();
|
||||
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get());
|
||||
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
|
||||
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_) {
|
||||
queue->DespatchEvents();
|
||||
for (auto& [hash, queue] : m_event_queues) {
|
||||
queue->despatchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
@ -4,8 +4,8 @@
|
||||
#include <string>
|
||||
#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
|
@ -8,11 +8,11 @@
|
||||
|
||||
namespace engine {
|
||||
|
||||
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<char>> readTextFile(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
|
||||
// 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
|
@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // uint32_t
|
||||
#include <cstdint>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace engine {
|
||||
struct Vertex; // resources/mesh.h
|
||||
}
|
||||
|
||||
namespace engine::util {
|
||||
struct Vertex; // forward-dec
|
||||
|
||||
/*
|
||||
* Generate tangents for a given list of vertices.
|
||||
@ -18,6 +16,6 @@ namespace engine::util {
|
||||
* Returns:
|
||||
* 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
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@ -22,17 +23,17 @@ struct Image;
|
||||
struct Sampler;
|
||||
|
||||
enum class MSAALevel {
|
||||
kOff,
|
||||
k2X,
|
||||
k4X,
|
||||
k8X,
|
||||
k16X,
|
||||
MSAA_OFF,
|
||||
MSAA_2X,
|
||||
MSAA_4X,
|
||||
MSAA_8X,
|
||||
MSAA_16X,
|
||||
};
|
||||
|
||||
enum class PresentMode {
|
||||
kDoubleBufferedNoVsync,
|
||||
kDoubleBufferedVsync,
|
||||
kTripleBuffered,
|
||||
DOUBLE_BUFFERED_NO_VSYNC,
|
||||
DOUBLE_BUFFERED_VSYNC,
|
||||
TRIPLE_BUFFERED,
|
||||
};
|
||||
|
||||
struct GraphicsSettings {
|
||||
@ -40,8 +41,8 @@ struct GraphicsSettings {
|
||||
{
|
||||
// sane defaults
|
||||
enable_validation = false;
|
||||
present_mode = PresentMode::kDoubleBufferedVsync;
|
||||
msaa_level = MSAALevel::kOff;
|
||||
present_mode = PresentMode::DOUBLE_BUFFERED_VSYNC;
|
||||
msaa_level = MSAALevel::MSAA_OFF;
|
||||
enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs
|
||||
}
|
||||
|
||||
@ -52,60 +53,59 @@ struct GraphicsSettings {
|
||||
};
|
||||
|
||||
enum class ImageFormat {
|
||||
kLinear,
|
||||
kSRGB,
|
||||
LINEAR,
|
||||
SRGB,
|
||||
};
|
||||
|
||||
enum class ShaderType {
|
||||
kVertex,
|
||||
kFragment,
|
||||
VERTEX,
|
||||
FRAGMENT,
|
||||
};
|
||||
|
||||
enum class BufferType {
|
||||
kVertex,
|
||||
kIndex,
|
||||
kUniform,
|
||||
VERTEX,
|
||||
INDEX,
|
||||
UNIFORM,
|
||||
};
|
||||
|
||||
enum class Primitive {
|
||||
kPoints,
|
||||
kLines,
|
||||
kLineStrip,
|
||||
kTriangles,
|
||||
kTriangleStrip,
|
||||
POINTS,
|
||||
LINES,
|
||||
LINE_STRIP,
|
||||
TRIANGLES,
|
||||
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 {
|
||||
kLinear,
|
||||
kNearest,
|
||||
LINEAR,
|
||||
NEAREST,
|
||||
};
|
||||
|
||||
enum class WrapMode : int {
|
||||
kRepeat,
|
||||
kMirroredRepeat,
|
||||
kClampToEdge,
|
||||
kClampToBorder,
|
||||
REPEAT,
|
||||
MIRRORED_REPEAT,
|
||||
CLAMP_TO_EDGE,
|
||||
CLAMP_TO_BORDER,
|
||||
};
|
||||
|
||||
enum class DescriptorType {
|
||||
kUniformBuffer,
|
||||
kCombinedImageSampler,
|
||||
UNIFORM_BUFFER,
|
||||
COMBINED_IMAGE_SAMPLER,
|
||||
};
|
||||
|
||||
namespace ShaderStageFlags {
|
||||
enum Bits : uint32_t {
|
||||
kVertex = 1 << 0,
|
||||
kFragment = 1 << 1,
|
||||
VERTEX = 1 << 0,
|
||||
FRAGMENT = 1 << 1,
|
||||
};
|
||||
typedef std::underlying_type<Bits>::type Flags;
|
||||
} // namespace ShaderStageFlags
|
||||
|
||||
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
|
||||
VertexAttribFormat format;
|
||||
uint32_t offset;
|
||||
@ -129,17 +129,17 @@ struct PipelineInfo {
|
||||
};
|
||||
|
||||
struct DescriptorSetLayoutBinding {
|
||||
DescriptorType descriptor_type = DescriptorType::kUniformBuffer;
|
||||
DescriptorType descriptor_type = DescriptorType::UNIFORM_BUFFER;
|
||||
ShaderStageFlags::Flags stage_flags = 0;
|
||||
};
|
||||
|
||||
struct SamplerInfo {
|
||||
Filter minify = gfx::Filter::kLinear;
|
||||
Filter magnify = gfx::Filter::kLinear;
|
||||
Filter mipmap = gfx::Filter::kLinear;
|
||||
WrapMode wrap_u = gfx::WrapMode::kRepeat;
|
||||
WrapMode wrap_v = gfx::WrapMode::kRepeat;
|
||||
WrapMode wrap_w = gfx::WrapMode::kRepeat; // only useful for cubemaps AFAIK
|
||||
Filter minify = gfx::Filter::LINEAR;
|
||||
Filter magnify = gfx::Filter::LINEAR;
|
||||
Filter mipmap = gfx::Filter::LINEAR;
|
||||
WrapMode wrap_u = gfx::WrapMode::REPEAT;
|
||||
WrapMode wrap_v = gfx::WrapMode::REPEAT;
|
||||
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 operator==(const SamplerInfo&) const = default;
|
||||
@ -148,6 +148,7 @@ struct SamplerInfo {
|
||||
} // namespace gfx
|
||||
} // namespace engine
|
||||
|
||||
// there has to be another way...
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<engine::gfx::SamplerInfo> {
|
||||
|
@ -10,102 +10,71 @@ struct ImDrawData; // "imgui/imgui.h"
|
||||
namespace engine {
|
||||
|
||||
class GFXDevice {
|
||||
public:
|
||||
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;
|
||||
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
|
||||
|
@ -4,17 +4,8 @@
|
||||
|
||||
#include "scene.h"
|
||||
|
||||
namespace engine::util {
|
||||
namespace engine {
|
||||
|
||||
/*
|
||||
* 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);
|
||||
engine::Entity loadGLTF(Scene& scene, const std::string& path, bool isStatic = false);
|
||||
|
||||
} // namespace engine::util
|
||||
} // namespace engine
|
@ -105,9 +105,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
||||
{
|
||||
const uint8_t pixel[4] = {255, 255, 255, 255};
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = false;
|
||||
auto whiteTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
||||
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};
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = false;
|
||||
auto blackTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
||||
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};
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = false;
|
||||
auto normalTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
||||
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
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = false;
|
||||
auto mrTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
||||
getResourceManager<Texture>()->AddPersistent("builtin.mr", std::move(mrTexture));
|
||||
@ -155,7 +155,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
m_renderer->GetDevice()->ShutdownImguiBackend();
|
||||
m_renderer->GetDevice()->shutdownImguiBackend();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext(im_gui_things.context);
|
||||
}
|
||||
@ -177,16 +177,16 @@ void Application::gameLoop()
|
||||
bool show_info_window = false;
|
||||
} debug_menu_state;
|
||||
debug_menu_state.enable_frame_limiter = m_configuration.enable_frame_limiter;
|
||||
switch (m_renderer->GetDevice()->GetPresentMode()) {
|
||||
case gfx::PresentMode::kDoubleBufferedNoVsync:
|
||||
switch (m_renderer->GetDevice()->getPresentMode()) {
|
||||
case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
|
||||
debug_menu_state.triple_buffering = false;
|
||||
debug_menu_state.vsync = false;
|
||||
break;
|
||||
case gfx::PresentMode::kDoubleBufferedVsync:
|
||||
case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
|
||||
debug_menu_state.triple_buffering = false;
|
||||
debug_menu_state.vsync = true;
|
||||
break;
|
||||
case gfx::PresentMode::kTripleBuffered:
|
||||
case gfx::PresentMode::TRIPLE_BUFFERED:
|
||||
debug_menu_state.triple_buffering = true;
|
||||
debug_menu_state.vsync = false;
|
||||
}
|
||||
@ -207,7 +207,7 @@ void Application::gameLoop()
|
||||
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
|
||||
lastTick = now;
|
||||
LOG_DEBUG("fps: {}", std::lroundf(avg_fps));
|
||||
getRenderer()->GetDevice()->LogPerformanceInfo();
|
||||
getRenderer()->GetDevice()->logPerformanceInfo();
|
||||
m_window->ResetAvgFPS();
|
||||
}
|
||||
|
||||
@ -246,10 +246,10 @@ void Application::gameLoop()
|
||||
}
|
||||
if (ImGui::Checkbox("Enable vsync", &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 {
|
||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync);
|
||||
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC);
|
||||
}
|
||||
}
|
||||
if (debug_menu_state.triple_buffering) {
|
||||
@ -258,14 +258,14 @@ void Application::gameLoop()
|
||||
if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) {
|
||||
if (debug_menu_state.triple_buffering) {
|
||||
debug_menu_state.vsync = false;
|
||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kTripleBuffered);
|
||||
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::TRIPLE_BUFFERED);
|
||||
}
|
||||
else {
|
||||
if (debug_menu_state.vsync) {
|
||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync);
|
||||
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_VSYNC);
|
||||
}
|
||||
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();
|
||||
// load gltf file dialog
|
||||
if (ImGui::Button("Load glTF")) {
|
||||
std::filesystem::path path = util::OpenFileDialog({"glb"});
|
||||
std::filesystem::path path = openFileDialog({"glb"});
|
||||
if (path.empty() == false) {
|
||||
util::LoadGLTF(*scene, path.string(), false);
|
||||
loadGLTF(*scene, path.string(), false);
|
||||
}
|
||||
}
|
||||
if (!scene) ImGui::EndDisabled();
|
||||
@ -534,7 +534,7 @@ void Application::gameLoop()
|
||||
delta_times[m_window->GetFrameCount() % delta_times.size()] = m_window->dt();
|
||||
}
|
||||
|
||||
m_renderer->GetDevice()->WaitIdle();
|
||||
m_renderer->GetDevice()->waitIdle();
|
||||
}
|
||||
|
||||
} // namespace engine
|
||||
|
@ -11,9 +11,9 @@
|
||||
|
||||
#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
|
||||
|
||||
@ -55,4 +55,4 @@ std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions)
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace engine::util
|
||||
} // namespace engine
|
@ -7,7 +7,7 @@
|
||||
|
||||
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);
|
||||
if (file.is_open() == false) {
|
||||
@ -39,7 +39,7 @@ std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path)
|
||||
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);
|
||||
if (file.is_open() == false) {
|
||||
@ -55,7 +55,7 @@ std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path)
|
||||
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;
|
||||
unsigned char* data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
#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>;
|
||||
@ -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<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()),
|
||||
static_cast<int>(vertices.size()), Vertex::floatsPerVertex());
|
||||
const int new_vertex_count = WeldMesh(reinterpret_cast<int*>(remap_table.data()), reinterpret_cast<float*>(vertex_data_out.data()),
|
||||
reinterpret_cast<float*>(vertices.data()), static_cast<int>(vertices.size()), Vertex::floatsPerVertex());
|
||||
assert(new_vertex_count >= 0);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
} // namespace engine::util
|
||||
} // namespace engine
|
@ -140,11 +140,11 @@ namespace converters {
|
||||
static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case gfx::VertexAttribFormat::kFloat2:
|
||||
case gfx::VertexAttribFormat::FLOAT2:
|
||||
return VK_FORMAT_R32G32_SFLOAT;
|
||||
case gfx::VertexAttribFormat::kFloat3:
|
||||
case gfx::VertexAttribFormat::FLOAT3:
|
||||
return VK_FORMAT_R32G32B32_SFLOAT;
|
||||
case gfx::VertexAttribFormat::kFloat4:
|
||||
case gfx::VertexAttribFormat::FLOAT4:
|
||||
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
}
|
||||
throw std::runtime_error("Unknown vertex attribute format");
|
||||
@ -153,11 +153,11 @@ static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
|
||||
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||
{
|
||||
switch (type) {
|
||||
case gfx::BufferType::kVertex:
|
||||
case gfx::BufferType::VERTEX:
|
||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
case gfx::BufferType::kIndex:
|
||||
case gfx::BufferType::INDEX:
|
||||
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||
case gfx::BufferType::kUniform:
|
||||
case gfx::BufferType::UNIFORM:
|
||||
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
switch (filter) {
|
||||
case gfx::Filter::kLinear:
|
||||
case gfx::Filter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case gfx::Filter::kNearest:
|
||||
case gfx::Filter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
}
|
||||
throw std::runtime_error("Unknown filter");
|
||||
@ -178,13 +178,13 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||
[[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case gfx::WrapMode::kRepeat:
|
||||
case gfx::WrapMode::REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case gfx::WrapMode::kMirroredRepeat:
|
||||
case gfx::WrapMode::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;
|
||||
case gfx::WrapMode::kClampToBorder:
|
||||
case gfx::WrapMode::CLAMP_TO_BORDER:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
}
|
||||
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)
|
||||
{
|
||||
switch (filter) {
|
||||
case gfx::Filter::kLinear:
|
||||
case gfx::Filter::LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case gfx::Filter::kNearest:
|
||||
case gfx::Filter::NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
}
|
||||
throw std::runtime_error("Unknown filter");
|
||||
@ -204,15 +204,15 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||
[[maybe_unused]] static VkSampleCountFlagBits getSampleCountFlags(gfx::MSAALevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case gfx::MSAALevel::kOff:
|
||||
case gfx::MSAALevel::MSAA_OFF:
|
||||
return VK_SAMPLE_COUNT_1_BIT;
|
||||
case gfx::MSAALevel::k2X:
|
||||
case gfx::MSAALevel::MSAA_2X:
|
||||
return VK_SAMPLE_COUNT_2_BIT;
|
||||
case gfx::MSAALevel::k4X:
|
||||
case gfx::MSAALevel::MSAA_4X:
|
||||
return VK_SAMPLE_COUNT_4_BIT;
|
||||
case gfx::MSAALevel::k8X:
|
||||
case gfx::MSAALevel::MSAA_8X:
|
||||
return VK_SAMPLE_COUNT_8_BIT;
|
||||
case gfx::MSAALevel::k16X:
|
||||
case gfx::MSAALevel::MSAA_16X:
|
||||
return VK_SAMPLE_COUNT_16_BIT;
|
||||
default:
|
||||
throw std::runtime_error("Unknown MSAA level");
|
||||
@ -222,9 +222,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||
static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
|
||||
{
|
||||
switch (type) {
|
||||
case gfx::DescriptorType::kUniformBuffer:
|
||||
case gfx::DescriptorType::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;
|
||||
default:
|
||||
throw std::runtime_error("Unknown descriptor type");
|
||||
@ -234,21 +234,21 @@ static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
|
||||
static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags)
|
||||
{
|
||||
VkShaderStageFlags out = 0;
|
||||
if (flags & gfx::ShaderStageFlags::kVertex) out |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||
if (flags & gfx::ShaderStageFlags::kFragment) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
if (flags & gfx::ShaderStageFlags::VERTEX) out |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||
if (flags & gfx::ShaderStageFlags::FRAGMENT) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
return out;
|
||||
}
|
||||
|
||||
static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case gfx::CullMode::kCullNone:
|
||||
case gfx::CullMode::CULL_NONE:
|
||||
return VK_CULL_MODE_NONE;
|
||||
case gfx::CullMode::kCullFront:
|
||||
case gfx::CullMode::CULL_FRONT:
|
||||
return VK_CULL_MODE_FRONT_BIT;
|
||||
case gfx::CullMode::kCullBack:
|
||||
case gfx::CullMode::CULL_BACK:
|
||||
return VK_CULL_MODE_BACK_BIT;
|
||||
case gfx::CullMode::kCullFrontAndBack:
|
||||
case gfx::CullMode::CULL_FRONT_AND_BACK:
|
||||
return VK_CULL_MODE_FRONT_AND_BACK;
|
||||
default:
|
||||
throw std::runtime_error("Unknown cull mode");
|
||||
@ -258,9 +258,9 @@ static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
|
||||
static VkFormat getImageFormat(gfx::ImageFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case gfx::ImageFormat::kLinear:
|
||||
case gfx::ImageFormat::LINEAR:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||
case gfx::ImageFormat::kSRGB:
|
||||
case gfx::ImageFormat::SRGB:
|
||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||
default:
|
||||
throw std::runtime_error("Unknown image format");
|
||||
@ -562,7 +562,7 @@ GFXDevice::~GFXDevice()
|
||||
destroyVulkanInstance(pimpl->instance);
|
||||
}
|
||||
|
||||
void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
|
||||
void GFXDevice::getViewportSize(uint32_t* w, uint32_t* h)
|
||||
{
|
||||
int width, height;
|
||||
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
|
||||
@ -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;
|
||||
// need to recreate swapchain to apply changes
|
||||
pimpl->swapchainIsOutOfDate = true;
|
||||
}
|
||||
|
||||
gfx::PresentMode GFXDevice::GetPresentMode()
|
||||
gfx::PresentMode GFXDevice::getPresentMode()
|
||||
{
|
||||
switch (pimpl->swapchain.presentMode) {
|
||||
case VK_PRESENT_MODE_FIFO_KHR:
|
||||
return gfx::PresentMode::kDoubleBufferedVsync;
|
||||
return gfx::PresentMode::DOUBLE_BUFFERED_VSYNC;
|
||||
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||
return gfx::PresentMode::kDoubleBufferedNoVsync;
|
||||
return gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC;
|
||||
case VK_PRESENT_MODE_MAILBOX_KHR:
|
||||
return gfx::PresentMode::kTripleBuffered;
|
||||
return gfx::PresentMode::TRIPLE_BUFFERED;
|
||||
default:
|
||||
throw std::runtime_error("Unknown present mode");
|
||||
}
|
||||
}
|
||||
|
||||
void GFXDevice::SetupImguiBackend()
|
||||
void GFXDevice::setupImguiBackend()
|
||||
{
|
||||
auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction {
|
||||
return vkGetInstanceProcAddr(*reinterpret_cast<VkInstance*>(user_data), function_name);
|
||||
@ -630,18 +630,18 @@ void GFXDevice::SetupImguiBackend()
|
||||
ImGui_ImplVulkan_CreateFontsTexture();
|
||||
}
|
||||
|
||||
void GFXDevice::ShutdownImguiBackend()
|
||||
void GFXDevice::shutdownImguiBackend()
|
||||
{
|
||||
ImGui_ImplVulkan_DestroyFontsTexture();
|
||||
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);
|
||||
}
|
||||
|
||||
gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
|
||||
gfx::DrawBuffer* GFXDevice::beginRender(bool window_resized)
|
||||
{
|
||||
VkResult res;
|
||||
|
||||
@ -899,7 +899,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
|
||||
return drawBuffer;
|
||||
}
|
||||
|
||||
void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
||||
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
|
||||
{
|
||||
assert(drawBuffer != nullptr);
|
||||
|
||||
@ -1009,7 +1009,7 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
||||
delete drawBuffer;
|
||||
}
|
||||
|
||||
gfx::Image* GFXDevice::CreateShadowmapImage()
|
||||
gfx::Image* GFXDevice::createImageShadowmap()
|
||||
{
|
||||
if (pimpl->FRAMECOUNT != 0) abort();
|
||||
|
||||
@ -1054,7 +1054,7 @@ gfx::Image* GFXDevice::CreateShadowmapImage()
|
||||
return out;
|
||||
}
|
||||
|
||||
gfx::DrawBuffer* GFXDevice::BeginShadowmapRender(gfx::Image* image)
|
||||
gfx::DrawBuffer* GFXDevice::beginShadowmapRender(gfx::Image* image)
|
||||
{
|
||||
assert(image != nullptr);
|
||||
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;
|
||||
}
|
||||
|
||||
void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image)
|
||||
void GFXDevice::finishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image)
|
||||
{
|
||||
assert(draw_buffer != nullptr);
|
||||
|
||||
@ -1211,44 +1211,44 @@ void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image*
|
||||
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(pipeline != nullptr);
|
||||
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||
}
|
||||
|
||||
void GFXDevice::CmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
|
||||
void GFXDevice::cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
|
||||
{
|
||||
assert(drawBuffer != nullptr);
|
||||
assert(buffer != nullptr);
|
||||
assert(buffer->type == gfx::BufferType::kVertex);
|
||||
assert(buffer->type == gfx::BufferType::VERTEX);
|
||||
const VkDeviceSize offset = 0;
|
||||
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset);
|
||||
}
|
||||
|
||||
void GFXDevice::CmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
|
||||
void GFXDevice::cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
|
||||
{
|
||||
assert(drawBuffer != nullptr);
|
||||
assert(buffer != nullptr);
|
||||
assert(buffer->type == gfx::BufferType::kIndex);
|
||||
assert(buffer->type == gfx::BufferType::INDEX);
|
||||
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)
|
||||
{
|
||||
assert(drawBuffer != nullptr);
|
||||
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);
|
||||
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(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);
|
||||
}
|
||||
|
||||
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(pipeline != nullptr);
|
||||
@ -1265,7 +1265,7 @@ void GFXDevice::CmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pip
|
||||
&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;
|
||||
|
||||
@ -1273,13 +1273,13 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
||||
|
||||
VkShaderModule vertShaderModule;
|
||||
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());
|
||||
}
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
@ -1497,7 +1497,7 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline)
|
||||
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||
{
|
||||
assert(pipeline != nullptr);
|
||||
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
|
||||
@ -1505,7 +1505,7 @@ void GFXDevice::DestroyPipeline(const gfx::Pipeline* 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{};
|
||||
|
||||
@ -1532,13 +1532,13 @@ gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector
|
||||
return out;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
|
||||
void GFXDevice::destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
|
||||
{
|
||||
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
|
||||
delete layout;
|
||||
}
|
||||
|
||||
gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
|
||||
gfx::DescriptorSet* GFXDevice::allocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
|
||||
{
|
||||
assert(layout != nullptr);
|
||||
|
||||
@ -1560,13 +1560,13 @@ gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLay
|
||||
return set;
|
||||
}
|
||||
|
||||
void GFXDevice::FreeDescriptorSet(const gfx::DescriptorSet* set)
|
||||
void GFXDevice::freeDescriptorSet(const gfx::DescriptorSet* set)
|
||||
{
|
||||
assert(set != nullptr);
|
||||
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(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(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);
|
||||
|
||||
@ -1627,7 +1627,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
|
||||
|
||||
/* first make staging buffer */
|
||||
out->stagingBuffer.size = size;
|
||||
out->stagingBuffer.type = gfx::BufferType::kUniform;
|
||||
out->stagingBuffer.type = gfx::BufferType::UNIFORM;
|
||||
{
|
||||
VkBufferCreateInfo stagingBufferInfo{};
|
||||
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 */
|
||||
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||
out->gpuBuffers[i].size = out->stagingBuffer.size;
|
||||
out->gpuBuffers[i].type = gfx::BufferType::kUniform;
|
||||
out->gpuBuffers[i].type = gfx::BufferType::UNIFORM;
|
||||
|
||||
VkBufferCreateInfo gpuBufferInfo{};
|
||||
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
@ -1677,7 +1677,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
|
||||
return out;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
|
||||
void GFXDevice::destroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
|
||||
{
|
||||
assert(uniformBuffer != nullptr);
|
||||
|
||||
@ -1690,7 +1690,7 @@ void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* 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(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);
|
||||
|
||||
@ -1769,7 +1769,7 @@ gfx::Buffer* GFXDevice::CreateBuffer(gfx::BufferType type, uint64_t size, const
|
||||
return out;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
|
||||
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
|
||||
{
|
||||
assert(buffer != nullptr);
|
||||
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
|
||||
@ -1777,7 +1777,7 @@ void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
@ -2032,7 +2032,7 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu
|
||||
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[1] != nullptr);
|
||||
@ -2291,7 +2291,7 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm
|
||||
return out;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroyImage(const gfx::Image* image)
|
||||
void GFXDevice::destroyImage(const gfx::Image* image)
|
||||
{
|
||||
assert(image != nullptr);
|
||||
vkDestroyImageView(pimpl->device.device, image->view, nullptr);
|
||||
@ -2299,7 +2299,7 @@ void GFXDevice::DestroyImage(const gfx::Image* 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{};
|
||||
|
||||
@ -2323,14 +2323,14 @@ const gfx::Sampler* GFXDevice::CreateSampler(const gfx::SamplerInfo& info)
|
||||
return out;
|
||||
}
|
||||
|
||||
void GFXDevice::DestroySampler(const gfx::Sampler* sampler)
|
||||
void GFXDevice::destroySampler(const gfx::Sampler* sampler)
|
||||
{
|
||||
assert(sampler != nullptr);
|
||||
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
|
||||
delete sampler;
|
||||
}
|
||||
|
||||
void GFXDevice::LogPerformanceInfo()
|
||||
void GFXDevice::logPerformanceInfo()
|
||||
{
|
||||
VmaTotalStatistics 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
|
@ -38,7 +38,7 @@ struct std::hash<Color> {
|
||||
|
||||
namespace tg = tinygltf;
|
||||
|
||||
namespace engine::util {
|
||||
namespace engine {
|
||||
|
||||
template <typename T>
|
||||
struct Attribute {
|
||||
@ -88,7 +88,17 @@ static glm::mat4 MatFromDoubleArray(const std::vector<double>& arr)
|
||||
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);
|
||||
@ -161,46 +171,46 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
// default to trilinear filtering even if mipmaps are not specified
|
||||
samplerInfo.minify = gfx::Filter::kLinear;
|
||||
samplerInfo.magnify = gfx::Filter::kLinear;
|
||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.magnify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||
if (texture.sampler != -1) {
|
||||
const tg::Sampler& sampler = model.samplers.at(texture.sampler);
|
||||
switch (sampler.minFilter) {
|
||||
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
||||
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR:
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||
break;
|
||||
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST:
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
break;
|
||||
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
||||
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR:
|
||||
samplerInfo.minify = gfx::Filter::kLinear;
|
||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||
break;
|
||||
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST:
|
||||
samplerInfo.minify = gfx::Filter::kLinear;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (sampler.magFilter) {
|
||||
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
break;
|
||||
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
||||
samplerInfo.magnify = gfx::Filter::kLinear;
|
||||
samplerInfo.magnify = gfx::Filter::LINEAR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
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) {
|
||||
const uint8_t pixel[4] = {c.r, c.g, c.b, c.a};
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = false;
|
||||
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) {
|
||||
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
||||
gfx::SamplerInfo samplerInfo{};
|
||||
samplerInfo.minify = gfx::Filter::kNearest;
|
||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
||||
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||
samplerInfo.anisotropic_filtering = 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;
|
||||
}
|
||||
|
||||
} // namespace engine::util
|
||||
} // namespace engine
|
214
src/renderer.cpp
214
src/renderer.cpp
@ -22,17 +22,17 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
||||
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
|
||||
{
|
||||
auto& binding0 = globalSetBindings.emplace_back();
|
||||
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
|
||||
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
|
||||
binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
|
||||
binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
|
||||
auto& binding1 = globalSetBindings.emplace_back();
|
||||
binding1.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
||||
binding1.stage_flags = gfx::ShaderStageFlags::kFragment;
|
||||
binding1.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||
binding1.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||
auto& binding2 = globalSetBindings.emplace_back();
|
||||
binding2.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
||||
binding2.stage_flags = gfx::ShaderStageFlags::kFragment;
|
||||
binding2.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||
binding2.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||
}
|
||||
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings);
|
||||
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout);
|
||||
global_uniform.layout = device_->createDescriptorSetLayout(globalSetBindings);
|
||||
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{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);
|
||||
@ -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});
|
||||
global_uniform.uniform_buffer_data.data.proj = light_proj;
|
||||
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);
|
||||
device_->UpdateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(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));
|
||||
// binding1 is updated towards the end of the constructor once the skybox texture is loaded
|
||||
// binding2 is updated just after that
|
||||
|
||||
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
|
||||
{
|
||||
auto& binding0 = frameSetBindings.emplace_back();
|
||||
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
|
||||
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
|
||||
binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
|
||||
binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
|
||||
}
|
||||
frame_uniform.layout = device_->CreateDescriptorSetLayout(frameSetBindings);
|
||||
frame_uniform.set = device_->AllocateDescriptorSet(frame_uniform.layout);
|
||||
frame_uniform.layout = device_->createDescriptorSetLayout(frameSetBindings);
|
||||
frame_uniform.set = device_->allocateDescriptorSet(frame_uniform.layout);
|
||||
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);
|
||||
device_->UpdateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(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));
|
||||
|
||||
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
|
||||
gfx::DescriptorSetLayoutBinding materialSetBinding{};
|
||||
materialSetBinding.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
||||
materialSetBinding.stage_flags = gfx::ShaderStageFlags::kFragment;
|
||||
materialSetBinding.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||
materialSetBinding.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||
materialSetBindings.push_back(materialSetBinding); // albedo
|
||||
materialSetBindings.push_back(materialSetBinding); // normal
|
||||
materialSetBindings.push_back(materialSetBinding); // occlusion
|
||||
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{};
|
||||
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.vertex_format = debug_vertex_format;
|
||||
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.descriptor_set_layouts = empty;
|
||||
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
|
||||
@ -97,29 +97,29 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
||||
|
||||
for (int face = 0; face < 6; ++face) {
|
||||
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!");
|
||||
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{};
|
||||
sampler_info.magnify = gfx::Filter::kLinear;
|
||||
sampler_info.minify = gfx::Filter::kLinear;
|
||||
sampler_info.mipmap = gfx::Filter::kLinear;
|
||||
sampler_info.wrap_u = gfx::WrapMode::kClampToEdge;
|
||||
sampler_info.wrap_v = gfx::WrapMode::kClampToEdge;
|
||||
sampler_info.wrap_w = gfx::WrapMode::kClampToEdge;
|
||||
sampler_info.magnify = gfx::Filter::LINEAR;
|
||||
sampler_info.minify = gfx::Filter::LINEAR;
|
||||
sampler_info.mipmap = gfx::Filter::LINEAR;
|
||||
sampler_info.wrap_u = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||
sampler_info.wrap_v = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||
sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
||||
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.vertex_format = vertex_format;
|
||||
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.line_primitives = false;
|
||||
pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout());
|
||||
pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout());
|
||||
|
||||
skybox_pipeline = device_->CreatePipeline(pipeline_info);
|
||||
skybox_pipeline = device_->createPipeline(pipeline_info);
|
||||
}
|
||||
|
||||
// create skybox vertex buffer
|
||||
@ -189,19 +189,19 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
||||
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
|
||||
gfx::VertexFormat shadowVertexFormat{};
|
||||
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(1u, gfx::VertexAttribFormat::kFloat2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv
|
||||
shadowVertexFormat.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::FLOAT3, 0u); // position
|
||||
shadowVertexFormat.attribute_descriptions.emplace_back(1u, gfx::VertexAttribFormat::FLOAT2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv
|
||||
gfx::PipelineInfo shadowPipelineInfo{};
|
||||
shadowPipelineInfo.vert_shader_path = getResourcePath("engine/shaders/shadow.vert");
|
||||
shadowPipelineInfo.frag_shader_path = getResourcePath("engine/shaders/shadow.frag");
|
||||
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.write_z = true;
|
||||
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(GetFrameSetLayout());
|
||||
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout());
|
||||
shadow_pipeline = device_->CreatePipeline(shadowPipelineInfo);
|
||||
shadow_pipeline = device_->createPipeline(shadowPipelineInfo);
|
||||
|
||||
// shadow map image and sampler
|
||||
shadow_map = device_->CreateShadowmapImage();
|
||||
shadow_map = device_->createImageShadowmap();
|
||||
gfx::SamplerInfo sampler_info{};
|
||||
sampler_info.magnify = gfx::Filter::kLinear;
|
||||
sampler_info.minify = gfx::Filter::kLinear;
|
||||
sampler_info.mipmap = gfx::Filter::kNearest; // 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_v = gfx::WrapMode::kClampToBorder;
|
||||
sampler_info.wrap_w = gfx::WrapMode::kClampToBorder;
|
||||
sampler_info.magnify = gfx::Filter::LINEAR;
|
||||
sampler_info.minify = gfx::Filter::LINEAR;
|
||||
sampler_info.mipmap = gfx::Filter::NEAREST; // bilinear is apparently good for shadow maps, mips aren't used anyway
|
||||
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::CLAMP_TO_BORDER;
|
||||
sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_BORDER;
|
||||
sampler_info.anisotropic_filtering = false; // no mip-maps so aniso won't do anything
|
||||
shadow_map_sampler = device_->CreateSampler(sampler_info);
|
||||
device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler);
|
||||
shadow_map_sampler = device_->createSampler(sampler_info);
|
||||
device_->updateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler);
|
||||
};
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
device_->DestroySampler(shadow_map_sampler);
|
||||
device_->DestroyImage(shadow_map);
|
||||
device_->DestroyPipeline(shadow_pipeline);
|
||||
device_->destroySampler(shadow_map_sampler);
|
||||
device_->destroyImage(shadow_map);
|
||||
device_->destroyPipeline(shadow_pipeline);
|
||||
|
||||
device_->DestroyBuffer(skybox_buffer);
|
||||
device_->DestroyPipeline(skybox_pipeline);
|
||||
device_->DestroySampler(skybox_sampler);
|
||||
device_->DestroyImage(skybox_cubemap);
|
||||
device_->destroyBuffer(skybox_buffer);
|
||||
device_->destroyPipeline(skybox_pipeline);
|
||||
device_->destroySampler(skybox_sampler);
|
||||
device_->destroyImage(skybox_cubemap);
|
||||
|
||||
device_->DestroyPipeline(debug_rendering_things_.pipeline);
|
||||
device_->destroyPipeline(debug_rendering_things_.pipeline);
|
||||
|
||||
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_->DestroyDescriptorSetLayout(frame_uniform.layout);
|
||||
device_->destroyUniformBuffer(frame_uniform.uniform_buffer);
|
||||
device_->destroyDescriptorSetLayout(frame_uniform.layout);
|
||||
|
||||
device_->DestroyUniformBuffer(global_uniform.uniform_buffer);
|
||||
device_->DestroyDescriptorSetLayout(global_uniform.layout);
|
||||
device_->destroyUniformBuffer(global_uniform.uniform_buffer);
|
||||
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) {
|
||||
uint32_t w, h;
|
||||
device_->GetViewportSize(&w, &h);
|
||||
device_->getViewportSize(&w, &h);
|
||||
viewport_aspect_ratio_ = (float)w / (float)h;
|
||||
const glm::mat4 proj_matrix =
|
||||
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)*/
|
||||
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);
|
||||
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) {
|
||||
// render to shadow map
|
||||
gfx::DrawBuffer* shadow_draw = device_->BeginShadowmapRender(shadow_map);
|
||||
device_->CmdBindPipeline(shadow_draw, shadow_pipeline);
|
||||
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
|
||||
gfx::DrawBuffer* shadow_draw = device_->beginShadowmapRender(shadow_map);
|
||||
device_->cmdBindPipeline(shadow_draw, shadow_pipeline);
|
||||
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->empty()) {
|
||||
for (const auto& entry : *static_list) {
|
||||
device_->CmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
||||
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2);
|
||||
device_->CmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
||||
device_->CmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
||||
device_->CmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
|
||||
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_->cmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
||||
device_->cmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
||||
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;
|
||||
|
||||
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->empty()) {
|
||||
DrawRenderList(draw_buffer, *static_list);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw moving objects
|
||||
if (dynamic_list) {
|
||||
if (!dynamic_list->empty()) {
|
||||
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 {
|
||||
glm::vec4 pos1;
|
||||
glm::vec4 pos2;
|
||||
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
|
||||
device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
||||
device_->cmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
||||
DebugPush push{};
|
||||
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.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
|
||||
push.color = l.color;
|
||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||
device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||
}
|
||||
|
||||
// also make a lil crosshair
|
||||
push.color = glm::vec3{1.0f, 1.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);
|
||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||
device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||
push.pos1 = 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_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||
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)
|
||||
@ -351,22 +353,22 @@ void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& re
|
||||
if (last_bound_pipeline_ == nullptr) {
|
||||
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
|
||||
// these bindings persist between all pipelines
|
||||
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
|
||||
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
|
||||
device_->CmdBindPipeline(draw_buffer, first_pipeline);
|
||||
device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
|
||||
device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
|
||||
device_->cmdBindPipeline(draw_buffer, first_pipeline);
|
||||
last_bound_pipeline_ = first_pipeline;
|
||||
}
|
||||
|
||||
for (const auto& entry : render_list) {
|
||||
if (entry.pipeline != last_bound_pipeline_) {
|
||||
device_->CmdBindPipeline(draw_buffer, entry.pipeline);
|
||||
device_->cmdBindPipeline(draw_buffer, entry.pipeline);
|
||||
last_bound_pipeline_ = entry.pipeline;
|
||||
}
|
||||
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_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
|
||||
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer);
|
||||
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
|
||||
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_->cmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
|
||||
device_->cmdBindIndexBuffer(draw_buffer, entry.index_buffer);
|
||||
device_->cmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace engine {
|
||||
|
||||
Font::Font(const std::string& path)
|
||||
{
|
||||
m_font_buffer = ReadBinaryFile(path);
|
||||
m_font_buffer = readBinaryFile(path);
|
||||
m_font_info = std::make_unique<stbtt_fontinfo>();
|
||||
|
||||
if (stbtt_InitFont(m_font_info.get(), m_font_buffer->data(), 0) == 0) {
|
||||
|
@ -7,27 +7,27 @@ namespace engine {
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ Mesh::Mesh(GFXDevice* gfx, const std::vector<Vertex>& vertices, const std::vecto
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
m_gfx->DestroyBuffer(m_ib);
|
||||
m_gfx->DestroyBuffer(m_vb);
|
||||
m_gfx->destroyBuffer(m_ib);
|
||||
m_gfx->destroyBuffer(m_vb);
|
||||
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)
|
||||
{
|
||||
m_vb = m_gfx->CreateBuffer(gfx::BufferType::kVertex, vertices.size() * sizeof(Vertex), vertices.data());
|
||||
m_ib = m_gfx->CreateBuffer(gfx::BufferType::kIndex, indices.size() * sizeof(uint32_t), indices.data());
|
||||
m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data());
|
||||
m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data());
|
||||
m_count = (uint32_t)indices.size();
|
||||
LOG_DEBUG("Created mesh, vertices: {}, indices: {}", vertices.size(), indices.size());
|
||||
}
|
||||
|
@ -19,27 +19,27 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
|
||||
gfx::VertexFormat vertFormat{};
|
||||
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||
index++, gfx::VertexAttribFormat::FLOAT3, stride);
|
||||
stride += 3 * sizeof(float);
|
||||
|
||||
if (settings.vertexParams.has_normal) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
||||
index++, gfx::VertexAttribFormat::FLOAT3, stride);
|
||||
stride += 3 * sizeof(float);
|
||||
}
|
||||
if (settings.vertexParams.has_tangent) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
index++, gfx::VertexAttribFormat::FLOAT4, stride);
|
||||
stride += 4 * sizeof(float);
|
||||
}
|
||||
if (settings.vertexParams.has_color) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
||||
index++, gfx::VertexAttribFormat::FLOAT4, stride);
|
||||
stride += 4 * sizeof(float);
|
||||
}
|
||||
if (settings.vertexParams.has_uv0) {
|
||||
vertFormat.attribute_descriptions.emplace_back(
|
||||
index++, gfx::VertexAttribFormat::kFloat2, stride);
|
||||
index++, gfx::VertexAttribFormat::FLOAT2, stride);
|
||||
stride += 2 * sizeof(float);
|
||||
}
|
||||
vertFormat.stride = stride;
|
||||
@ -49,21 +49,21 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
|
||||
info.frag_shader_path = fragPath;
|
||||
info.vertex_format = vertFormat;
|
||||
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.line_primitives = false;
|
||||
info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout());
|
||||
info.descriptor_set_layouts.push_back(renderer->GetFrameSetLayout());
|
||||
info.descriptor_set_layouts.push_back(renderer->GetMaterialSetLayout());
|
||||
|
||||
pipeline_ = gfx_->CreatePipeline(info);
|
||||
pipeline_ = gfx_->createPipeline(info);
|
||||
|
||||
LOG_DEBUG("Created shader: {}, pipeline: {}", vertPath,
|
||||
static_cast<const void*>(pipeline_));
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
gfx_->DestroyPipeline(pipeline_);
|
||||
gfx_->destroyPipeline(pipeline_);
|
||||
LOG_DEBUG("Destroyed shader, pipeline: {}", static_cast<const void*>(pipeline_));
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
{
|
||||
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);
|
||||
|
||||
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()
|
||||
{
|
||||
gfx_->DestroyImage(image_);
|
||||
gfx_->destroyImage(image_);
|
||||
LOG_DEBUG("Destroyed texture");
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, gfx::SamplerInfo samplerInfo, Renderer* renderer, bool srgb)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ void Scene::Update(float ts) {
|
||||
system->onUpdate(ts);
|
||||
}
|
||||
|
||||
event_system_->DespatchEvents(); // clears event queue
|
||||
event_system_->despatchEvents(); // clears event queue
|
||||
}
|
||||
|
||||
} // namespace engine
|
||||
|
@ -55,13 +55,13 @@ namespace engine {
|
||||
|
||||
VkPresentModeKHR present_mode_requested;
|
||||
switch (info.requested_present_mode) {
|
||||
case gfx::PresentMode::kDoubleBufferedNoVsync:
|
||||
case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
|
||||
present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
break;
|
||||
case gfx::PresentMode::kDoubleBufferedVsync:
|
||||
case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
|
||||
present_mode_requested = VK_PRESENT_MODE_FIFO_KHR;
|
||||
break;
|
||||
case gfx::PresentMode::kTripleBuffered:
|
||||
case gfx::PresentMode::TRIPLE_BUFFERED:
|
||||
present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available
|
||||
|
@ -62,7 +62,7 @@ void CameraControllerSystem::onUpdate(float ts)
|
||||
// keep vel.z as gravity can increase it every frame
|
||||
|
||||
// gravity stuff here:
|
||||
c->vel.z += CameraControllerComponent::kGravAccel * dt;
|
||||
c->vel.z += c->grav_accel * dt;
|
||||
|
||||
// jumping
|
||||
if (m_scene->app()->getInputManager()->GetButtonPress("jump") && (c->grounded || c->noclip)) {
|
||||
@ -208,6 +208,15 @@ void CameraControllerSystem::onUpdate(float ts)
|
||||
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)) {
|
||||
engine::Ray ray{};
|
||||
ray.origin = t->position;
|
||||
|
@ -25,8 +25,8 @@ struct CameraControllerComponent {
|
||||
static constexpr float kMaxStairHeight = 0.2f;
|
||||
static constexpr size_t kNumHorizontalRays = 20;
|
||||
|
||||
static constexpr float kGravAccel = -9.81f;
|
||||
// static constexpr float kGravAccel = -1.625f; // moon gravity
|
||||
float grav_accel = -9.81f;
|
||||
// grav_accel = -1.625f; // moon gravity
|
||||
static constexpr float kMaxDistanceFromOrigin = 200.0f;
|
||||
|
||||
bool noclip = false;
|
||||
|
@ -47,9 +47,9 @@ void PlayGame(GameSettings settings)
|
||||
|
||||
engine::gfx::GraphicsSettings graphics_settings{};
|
||||
graphics_settings.enable_validation = settings.enable_validation;
|
||||
graphics_settings.present_mode = engine::gfx::PresentMode::kTripleBuffered;
|
||||
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff;
|
||||
graphics_settings.enable_anisotropy = true;
|
||||
graphics_settings.present_mode = engine::gfx::PresentMode::TRIPLE_BUFFERED;
|
||||
graphics_settings.msaa_level = engine::gfx::MSAALevel::MSAA_OFF;
|
||||
graphics_settings.enable_anisotropy = false;
|
||||
|
||||
engine::AppConfiguration configuration{};
|
||||
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
|
||||
* 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->RegisterSystemAtIndex<CameraControllerSystem>(0);
|
||||
@ -98,36 +98,38 @@ void PlayGame(GameSettings settings)
|
||||
main_scene->AddComponent<CameraControllerComponent>(camera);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
// 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)->position.x += 25.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->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::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->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->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});
|
||||
|
||||
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};
|
||||
|
||||
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).z += 2.5f;
|
||||
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).x -= 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};
|
||||
|
||||
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->GetScale(box) *= 10.0f;
|
||||
main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f });
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user