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/file_dialog.cpp"
|
||||||
"src/files.cpp"
|
"src/files.cpp"
|
||||||
"src/gen_tangents.cpp"
|
"src/gen_tangents.cpp"
|
||||||
"src/gfx_device_vulkan.cpp"
|
"src/gfx_device.cpp"
|
||||||
"src/gltf_loader.cpp"
|
"src/gltf_loader.cpp"
|
||||||
"src/input_manager.cpp"
|
"src/input_manager.cpp"
|
||||||
"src/renderer.cpp"
|
"src/renderer.cpp"
|
||||||
|
46
CMakePresets.json
Normal file
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 {
|
namespace engine {
|
||||||
|
|
||||||
enum class EventSubscriberKind {
|
enum class EventSubscriberKind {
|
||||||
kEntity,
|
ENTITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event handler base-class
|
// Event handler base-class
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EventHandler {
|
class EventHandler {
|
||||||
public:
|
public:
|
||||||
virtual void OnEvent(T data) = 0;
|
virtual void onEvent(T data) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event queue interface to allow for different type queues to be in the map
|
// Event queue interface to allow for different type queues to be in the map
|
||||||
class IEventQueue {
|
class IEventQueue {
|
||||||
public:
|
public:
|
||||||
virtual ~IEventQueue() {}
|
virtual ~IEventQueue() {}
|
||||||
virtual void DespatchEvents() = 0;
|
virtual void despatchEvents() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -31,42 +31,40 @@ class EventQueue : public IEventQueue {
|
|||||||
// holds events of type T and subscribers to those events
|
// holds events of type T and subscribers to those events
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
void subscribe(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||||
{
|
{
|
||||||
// For the time being, ignore kind (TODO)
|
// For the time being, ignore kind (TODO)
|
||||||
(void)kind;
|
(void)kind;
|
||||||
assert(subscribers_.contains(id) == false && "subscribing to an event with ID that's already in use!");
|
assert(m_subscribers.contains(id) == false && "subscribing to an event with ID that's already in use!");
|
||||||
subscribers_.emplace(id, handler);
|
m_subscribers.emplace(id, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueueEvent(EventSubscriberKind kind, uint32_t id, T event)
|
void queueEvent(EventSubscriberKind kind, uint32_t id, T event)
|
||||||
{
|
{
|
||||||
// For the time being, ignore kind (TODO)
|
// For the time being, ignore kind (TODO)
|
||||||
(void)kind;
|
(void)kind;
|
||||||
assert(subscribers_.contains(id) && "Attempt to submit event to non-existing subscriber!");
|
assert(m_subscribers.contains(id) && "Attempt to submit event to non-existing subscriber!");
|
||||||
EventHandler<T>* handler = subscribers_.at(id);
|
EventHandler<T>* handler = m_subscribers.at(id);
|
||||||
event_queue_.emplace(handler, event);
|
m_event_queue.emplace(handler, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DespatchEvents() override
|
void despatchEvents() override
|
||||||
{
|
{
|
||||||
while (event_queue_.empty() == false) {
|
while (m_event_queue.empty() == false) {
|
||||||
auto [handler, event] = event_queue_.front();
|
auto [handler, event] = m_event_queue.front();
|
||||||
handler->OnEvent(event);
|
handler->onEvent(event);
|
||||||
event_queue_.pop();
|
m_event_queue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, EventHandler<T>*> subscribers_;
|
std::unordered_map<uint32_t, EventHandler<T>*> m_subscribers;
|
||||||
|
|
||||||
struct QueuedEvent {
|
struct QueuedEvent {
|
||||||
QueuedEvent(EventHandler<T>* handler, T event) : handler(handler), event(event) {}
|
|
||||||
|
|
||||||
EventHandler<T>* handler;
|
EventHandler<T>* handler;
|
||||||
T event;
|
T event;
|
||||||
};
|
};
|
||||||
std::queue<QueuedEvent> event_queue_{};
|
std::queue<QueuedEvent> m_event_queue{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventSystem {
|
class EventSystem {
|
||||||
@ -77,42 +75,42 @@ class EventSystem {
|
|||||||
~EventSystem() {}
|
~EventSystem() {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void RegisterEventType()
|
void registerEventType()
|
||||||
{
|
{
|
||||||
size_t hash = typeid(T).hash_code();
|
size_t hash = typeid(T).hash_code();
|
||||||
assert(event_queues_.contains(hash) == false && "Registering an event queue more than once!");
|
assert(m_event_queues.contains(hash) == false && "Registering an event queue more than once!");
|
||||||
event_queues_.emplace(hash, std::make_unique<EventQueue<T>>());
|
m_event_queues.emplace(hash, std::make_unique<EventQueue<T>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SubscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
void subscribeToEventType(EventSubscriberKind kind, uint32_t id, EventHandler<T>* handler)
|
||||||
{
|
{
|
||||||
size_t hash = typeid(T).hash_code();
|
size_t hash = typeid(T).hash_code();
|
||||||
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!");
|
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get());
|
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
|
||||||
assert(queue != nullptr && "This cast should work?!! wot");
|
assert(queue != nullptr && "This cast should work?!! wot");
|
||||||
queue->Subscribe(kind, id, handler);
|
queue->subscribe(kind, id, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void QueueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
|
void queueEvent(EventSubscriberKind kind, uint32_t subscriber_id, T event)
|
||||||
{
|
{
|
||||||
size_t hash = typeid(T).hash_code();
|
size_t hash = typeid(T).hash_code();
|
||||||
assert(event_queues_.contains(hash) && "Subscribing to event type that isn't registered!");
|
assert(m_event_queues.contains(hash) && "Subscribing to event type that isn't registered!");
|
||||||
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(event_queues_.at(hash).get());
|
EventQueue<T>* queue = dynamic_cast<EventQueue<T>*>(m_event_queues.at(hash).get());
|
||||||
assert(queue != nullptr && "This cast should work?!! wot");
|
assert(queue != nullptr && "This cast should work?!! wot");
|
||||||
queue->QueueEvent(kind, subscriber_id, event);
|
queue->queueEvent(kind, subscriber_id, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DespatchEvents()
|
void despatchEvents()
|
||||||
{
|
{
|
||||||
for (auto& [hash, queue] : event_queues_) {
|
for (auto& [hash, queue] : m_event_queues) {
|
||||||
queue->DespatchEvents();
|
queue->despatchEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> event_queues_{};
|
std::unordered_map<size_t, std::unique_ptr<IEventQueue>> m_event_queues{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
@ -4,8 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace engine::util {
|
namespace engine {
|
||||||
|
|
||||||
std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions);
|
std::filesystem::path openFileDialog(const std::vector<std::string>& extensions);
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path);
|
std::unique_ptr<std::vector<char>> readTextFile(const std::string& path);
|
||||||
std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path);
|
std::unique_ptr<std::vector<uint8_t>> readBinaryFile(const std::string& path);
|
||||||
|
|
||||||
// Read an image file into a vector byte buffer. PNG and JPG support at a
|
// Read an image file into a vector byte buffer. PNG and JPG support at a
|
||||||
// minimum. Output format is R8G8B8A8_UINT
|
// minimum. Output format is R8G8B8A8_UINT
|
||||||
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, int& width, int& height);
|
std::unique_ptr<std::vector<uint8_t>> readImageFile(const std::string& path, int& width, int& height);
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint32_t
|
#include <cstdint>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
struct Vertex; // resources/mesh.h
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace engine::util {
|
struct Vertex; // forward-dec
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate tangents for a given list of vertices.
|
* Generate tangents for a given list of vertices.
|
||||||
@ -18,6 +16,6 @@ namespace engine::util {
|
|||||||
* Returns:
|
* Returns:
|
||||||
* index list for the provided vertices
|
* index list for the provided vertices
|
||||||
*/
|
*/
|
||||||
std::vector<uint32_t> GenTangents(std::vector<engine::Vertex>& vertices);
|
std::vector<uint32_t> genTangents(std::vector<engine::Vertex>& vertices);
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -22,17 +23,17 @@ struct Image;
|
|||||||
struct Sampler;
|
struct Sampler;
|
||||||
|
|
||||||
enum class MSAALevel {
|
enum class MSAALevel {
|
||||||
kOff,
|
MSAA_OFF,
|
||||||
k2X,
|
MSAA_2X,
|
||||||
k4X,
|
MSAA_4X,
|
||||||
k8X,
|
MSAA_8X,
|
||||||
k16X,
|
MSAA_16X,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PresentMode {
|
enum class PresentMode {
|
||||||
kDoubleBufferedNoVsync,
|
DOUBLE_BUFFERED_NO_VSYNC,
|
||||||
kDoubleBufferedVsync,
|
DOUBLE_BUFFERED_VSYNC,
|
||||||
kTripleBuffered,
|
TRIPLE_BUFFERED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsSettings {
|
struct GraphicsSettings {
|
||||||
@ -40,8 +41,8 @@ struct GraphicsSettings {
|
|||||||
{
|
{
|
||||||
// sane defaults
|
// sane defaults
|
||||||
enable_validation = false;
|
enable_validation = false;
|
||||||
present_mode = PresentMode::kDoubleBufferedVsync;
|
present_mode = PresentMode::DOUBLE_BUFFERED_VSYNC;
|
||||||
msaa_level = MSAALevel::kOff;
|
msaa_level = MSAALevel::MSAA_OFF;
|
||||||
enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs
|
enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,60 +53,59 @@ struct GraphicsSettings {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class ImageFormat {
|
enum class ImageFormat {
|
||||||
kLinear,
|
LINEAR,
|
||||||
kSRGB,
|
SRGB,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ShaderType {
|
enum class ShaderType {
|
||||||
kVertex,
|
VERTEX,
|
||||||
kFragment,
|
FRAGMENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BufferType {
|
enum class BufferType {
|
||||||
kVertex,
|
VERTEX,
|
||||||
kIndex,
|
INDEX,
|
||||||
kUniform,
|
UNIFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Primitive {
|
enum class Primitive {
|
||||||
kPoints,
|
POINTS,
|
||||||
kLines,
|
LINES,
|
||||||
kLineStrip,
|
LINE_STRIP,
|
||||||
kTriangles,
|
TRIANGLES,
|
||||||
kTriangleStrip,
|
TRIANGLE_STRIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CullMode { kCullNone, kCullFront, kCullBack, kCullFrontAndBack };
|
enum class CullMode { CULL_NONE, CULL_FRONT, CULL_BACK, CULL_FRONT_AND_BACK };
|
||||||
|
|
||||||
enum class VertexAttribFormat { kFloat2, kFloat3, kFloat4 };
|
enum class VertexAttribFormat { FLOAT2, FLOAT3, FLOAT4 };
|
||||||
|
|
||||||
enum class Filter : int {
|
enum class Filter : int {
|
||||||
kLinear,
|
LINEAR,
|
||||||
kNearest,
|
NEAREST,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class WrapMode : int {
|
enum class WrapMode : int {
|
||||||
kRepeat,
|
REPEAT,
|
||||||
kMirroredRepeat,
|
MIRRORED_REPEAT,
|
||||||
kClampToEdge,
|
CLAMP_TO_EDGE,
|
||||||
kClampToBorder,
|
CLAMP_TO_BORDER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DescriptorType {
|
enum class DescriptorType {
|
||||||
kUniformBuffer,
|
UNIFORM_BUFFER,
|
||||||
kCombinedImageSampler,
|
COMBINED_IMAGE_SAMPLER,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ShaderStageFlags {
|
namespace ShaderStageFlags {
|
||||||
enum Bits : uint32_t {
|
enum Bits : uint32_t {
|
||||||
kVertex = 1 << 0,
|
VERTEX = 1 << 0,
|
||||||
kFragment = 1 << 1,
|
FRAGMENT = 1 << 1,
|
||||||
};
|
};
|
||||||
typedef std::underlying_type<Bits>::type Flags;
|
typedef std::underlying_type<Bits>::type Flags;
|
||||||
} // namespace ShaderStageFlags
|
} // namespace ShaderStageFlags
|
||||||
|
|
||||||
struct VertexAttribDescription {
|
struct VertexAttribDescription {
|
||||||
VertexAttribDescription(uint32_t location, VertexAttribFormat format, uint32_t offset) : location(location), format(format), offset(offset) {}
|
|
||||||
uint32_t location; // the index to use in the shader
|
uint32_t location; // the index to use in the shader
|
||||||
VertexAttribFormat format;
|
VertexAttribFormat format;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
@ -129,17 +129,17 @@ struct PipelineInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct DescriptorSetLayoutBinding {
|
struct DescriptorSetLayoutBinding {
|
||||||
DescriptorType descriptor_type = DescriptorType::kUniformBuffer;
|
DescriptorType descriptor_type = DescriptorType::UNIFORM_BUFFER;
|
||||||
ShaderStageFlags::Flags stage_flags = 0;
|
ShaderStageFlags::Flags stage_flags = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SamplerInfo {
|
struct SamplerInfo {
|
||||||
Filter minify = gfx::Filter::kLinear;
|
Filter minify = gfx::Filter::LINEAR;
|
||||||
Filter magnify = gfx::Filter::kLinear;
|
Filter magnify = gfx::Filter::LINEAR;
|
||||||
Filter mipmap = gfx::Filter::kLinear;
|
Filter mipmap = gfx::Filter::LINEAR;
|
||||||
WrapMode wrap_u = gfx::WrapMode::kRepeat;
|
WrapMode wrap_u = gfx::WrapMode::REPEAT;
|
||||||
WrapMode wrap_v = gfx::WrapMode::kRepeat;
|
WrapMode wrap_v = gfx::WrapMode::REPEAT;
|
||||||
WrapMode wrap_w = gfx::WrapMode::kRepeat; // only useful for cubemaps AFAIK
|
WrapMode wrap_w = gfx::WrapMode::REPEAT; // only useful for cubemaps AFAIK
|
||||||
bool anisotropic_filtering = true; // this can be force disabled by a global setting
|
bool anisotropic_filtering = true; // this can be force disabled by a global setting
|
||||||
|
|
||||||
bool operator==(const SamplerInfo&) const = default;
|
bool operator==(const SamplerInfo&) const = default;
|
||||||
@ -148,6 +148,7 @@ struct SamplerInfo {
|
|||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|
||||||
|
// there has to be another way...
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash<engine::gfx::SamplerInfo> {
|
struct hash<engine::gfx::SamplerInfo> {
|
||||||
|
@ -10,102 +10,71 @@ struct ImDrawData; // "imgui/imgui.h"
|
|||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
class GFXDevice {
|
class GFXDevice {
|
||||||
public:
|
private:
|
||||||
GFXDevice(const char* app_name, const char* app_version, SDL_Window* window, gfx::GraphicsSettings settings);
|
|
||||||
|
|
||||||
GFXDevice(const GFXDevice&) = delete;
|
|
||||||
GFXDevice& operator=(const GFXDevice&) = delete;
|
|
||||||
~GFXDevice();
|
|
||||||
|
|
||||||
void GetViewportSize(uint32_t* w, uint32_t* h);
|
|
||||||
|
|
||||||
void ChangePresentMode(gfx::PresentMode mode);
|
|
||||||
gfx::PresentMode GetPresentMode();
|
|
||||||
|
|
||||||
void SetupImguiBackend();
|
|
||||||
void ShutdownImguiBackend();
|
|
||||||
void CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);
|
|
||||||
|
|
||||||
gfx::DrawBuffer* BeginRender(bool window_resized);
|
|
||||||
|
|
||||||
/* - draw_buffer MUST be a valid pointer returned by BeginRender().
|
|
||||||
- draw_buffer is invalid after this function has been called. */
|
|
||||||
void FinishRender(gfx::DrawBuffer* draw_buffer);
|
|
||||||
|
|
||||||
gfx::Image* CreateShadowmapImage();
|
|
||||||
gfx::DrawBuffer* BeginShadowmapRender(gfx::Image* image);
|
|
||||||
void FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image);
|
|
||||||
|
|
||||||
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
|
|
||||||
- pipeline MUST be a valid pointer returned by CreatePipeline() */
|
|
||||||
void CmdBindPipeline(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline);
|
|
||||||
|
|
||||||
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
|
|
||||||
- buffer MUST be a valid pointer returned by CreateBuffer */
|
|
||||||
void CmdBindVertexBuffer(gfx::DrawBuffer* draw_buffer, uint32_t binding, const gfx::Buffer* buffer);
|
|
||||||
|
|
||||||
/* - draw_buffer MUST be a valid pointer returned by BeginRender()
|
|
||||||
- buffer MUST be a valid pointer returned by CreateBuffer */
|
|
||||||
void CmdBindIndexBuffer(gfx::DrawBuffer* draw_buffer, const gfx::Buffer* buffer);
|
|
||||||
|
|
||||||
void CmdDrawIndexed(gfx::DrawBuffer* draw_buffer, uint32_t index_count, uint32_t instance_count, uint32_t first_index, int32_t vertex_offset,
|
|
||||||
uint32_t first_instance);
|
|
||||||
|
|
||||||
void CmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance);
|
|
||||||
|
|
||||||
void CmdPushConstants(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data);
|
|
||||||
|
|
||||||
void CmdBindDescriptorSet(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t set_number);
|
|
||||||
|
|
||||||
gfx::Pipeline* CreatePipeline(const gfx::PipelineInfo& info);
|
|
||||||
|
|
||||||
void DestroyPipeline(const gfx::Pipeline* pipeline);
|
|
||||||
|
|
||||||
gfx::DescriptorSetLayout* CreateDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings);
|
|
||||||
|
|
||||||
void DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
|
|
||||||
|
|
||||||
gfx::DescriptorSet* AllocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
|
|
||||||
|
|
||||||
void FreeDescriptorSet(const gfx::DescriptorSet* set);
|
|
||||||
|
|
||||||
// This updates all copies of the descriptor.
|
|
||||||
// This cannot be used after any frames have been renderered
|
|
||||||
void UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range);
|
|
||||||
|
|
||||||
void UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler);
|
|
||||||
|
|
||||||
gfx::UniformBuffer* CreateUniformBuffer(uint64_t size, const void* initial_data);
|
|
||||||
|
|
||||||
void DestroyUniformBuffer(const gfx::UniformBuffer* descriptor_buffer);
|
|
||||||
|
|
||||||
void WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data);
|
|
||||||
|
|
||||||
// Loads data into staging buffer and copies that into a single GPU buffer.
|
|
||||||
gfx::Buffer* CreateBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
|
||||||
|
|
||||||
void DestroyBuffer(const gfx::Buffer* buffer);
|
|
||||||
|
|
||||||
gfx::Image* CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* image_data);
|
|
||||||
|
|
||||||
gfx::Image* CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data);
|
|
||||||
|
|
||||||
void DestroyImage(const gfx::Image* image);
|
|
||||||
|
|
||||||
const gfx::Sampler* CreateSampler(const gfx::SamplerInfo& info);
|
|
||||||
|
|
||||||
void DestroySampler(const gfx::Sampler* sampler);
|
|
||||||
|
|
||||||
uint64_t GetFrameCount();
|
|
||||||
|
|
||||||
void LogPerformanceInfo();
|
|
||||||
|
|
||||||
// wait until all the active GPU queues have finished working
|
|
||||||
void WaitIdle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> pimpl;
|
std::unique_ptr<Impl> pimpl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GFXDevice(const char* app_name, const char* app_version, SDL_Window* window, gfx::GraphicsSettings settings);
|
||||||
|
GFXDevice(const GFXDevice&) = delete;
|
||||||
|
|
||||||
|
~GFXDevice();
|
||||||
|
|
||||||
|
GFXDevice& operator=(const GFXDevice&) = delete;
|
||||||
|
|
||||||
|
void getViewportSize(uint32_t* w, uint32_t* h);
|
||||||
|
|
||||||
|
void changePresentMode(gfx::PresentMode mode);
|
||||||
|
gfx::PresentMode getPresentMode();
|
||||||
|
|
||||||
|
void setupImguiBackend();
|
||||||
|
void shutdownImguiBackend();
|
||||||
|
void cmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);
|
||||||
|
|
||||||
|
gfx::DrawBuffer* beginRender(bool window_resized);
|
||||||
|
void finishRender(gfx::DrawBuffer* draw_buffer);
|
||||||
|
|
||||||
|
gfx::DrawBuffer* beginShadowmapRender(gfx::Image* image);
|
||||||
|
void finishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image);
|
||||||
|
|
||||||
|
void cmdBindPipeline(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline);
|
||||||
|
void cmdBindVertexBuffer(gfx::DrawBuffer* draw_buffer, uint32_t binding, const gfx::Buffer* buffer);
|
||||||
|
void cmdBindIndexBuffer(gfx::DrawBuffer* draw_buffer, const gfx::Buffer* buffer);
|
||||||
|
void cmdDrawIndexed(gfx::DrawBuffer* draw_buffer, uint32_t index_count, uint32_t instance_count, uint32_t first_index, int32_t vertex_offset,
|
||||||
|
uint32_t first_instance);
|
||||||
|
void cmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance);
|
||||||
|
void cmdPushConstants(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data);
|
||||||
|
void cmdBindDescriptorSet(gfx::DrawBuffer* draw_buffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t set_number);
|
||||||
|
|
||||||
|
gfx::Pipeline* createPipeline(const gfx::PipelineInfo& info);
|
||||||
|
void destroyPipeline(const gfx::Pipeline* pipeline);
|
||||||
|
|
||||||
|
gfx::DescriptorSetLayout* createDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings);
|
||||||
|
void destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
|
||||||
|
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
|
||||||
|
void freeDescriptorSet(const gfx::DescriptorSet* set);
|
||||||
|
void updateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range);
|
||||||
|
void updateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler);
|
||||||
|
|
||||||
|
gfx::UniformBuffer* createUniformBuffer(uint64_t size, const void* initial_data);
|
||||||
|
void destroyUniformBuffer(const gfx::UniformBuffer* descriptor_buffer);
|
||||||
|
void writeUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data);
|
||||||
|
|
||||||
|
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
||||||
|
void destroyBuffer(const gfx::Buffer* buffer);
|
||||||
|
|
||||||
|
gfx::Image* createImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* image_data);
|
||||||
|
gfx::Image* createImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data);
|
||||||
|
gfx::Image* createImageShadowmap();
|
||||||
|
void destroyImage(const gfx::Image* image);
|
||||||
|
|
||||||
|
const gfx::Sampler* createSampler(const gfx::SamplerInfo& info);
|
||||||
|
void destroySampler(const gfx::Sampler* sampler);
|
||||||
|
|
||||||
|
uint64_t getFrameCount();
|
||||||
|
void logPerformanceInfo();
|
||||||
|
|
||||||
|
void waitIdle();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -4,17 +4,8 @@
|
|||||||
|
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
|
|
||||||
namespace engine::util {
|
namespace engine {
|
||||||
|
|
||||||
/*
|
engine::Entity loadGLTF(Scene& scene, const std::string& path, bool isStatic = false);
|
||||||
* Loads the default scene found in a glTF file into 'scene'.
|
|
||||||
* 'isStatic' will mark every transform as static to aid rendering optimisation.
|
|
||||||
* Returns the top-level glTF node as an engine entity.
|
|
||||||
*
|
|
||||||
* Loader limitations:
|
|
||||||
* - Can only load .glb files
|
|
||||||
* - glTF files must contain all textures
|
|
||||||
*/
|
|
||||||
engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic = false);
|
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
@ -105,9 +105,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
{
|
{
|
||||||
const uint8_t pixel[4] = {255, 255, 255, 255};
|
const uint8_t pixel[4] = {255, 255, 255, 255};
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
auto whiteTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
auto whiteTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
||||||
getResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
|
getResourceManager<Texture>()->AddPersistent("builtin.white", std::move(whiteTexture));
|
||||||
@ -115,9 +115,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
{
|
{
|
||||||
const uint8_t pixel[4] = {0, 0, 0, 255};
|
const uint8_t pixel[4] = {0, 0, 0, 255};
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
auto blackTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
auto blackTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, true);
|
||||||
getResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture));
|
getResourceManager<Texture>()->AddPersistent("builtin.black", std::move(blackTexture));
|
||||||
@ -125,9 +125,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
{
|
{
|
||||||
const uint8_t pixel[4] = {127, 127, 255, 255};
|
const uint8_t pixel[4] = {127, 127, 255, 255};
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
auto normalTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
auto normalTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
||||||
getResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture));
|
getResourceManager<Texture>()->AddPersistent("builtin.normal", std::move(normalTexture));
|
||||||
@ -135,9 +135,9 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
{
|
{
|
||||||
const uint8_t pixel[4] = {255, 127, 0, 255}; // AO, roughness, metallic
|
const uint8_t pixel[4] = {255, 127, 0, 255}; // AO, roughness, metallic
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
auto mrTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
auto mrTexture = std::make_unique<Texture>(getRenderer(), pixel, 1, 1, samplerInfo, false);
|
||||||
getResourceManager<Texture>()->AddPersistent("builtin.mr", std::move(mrTexture));
|
getResourceManager<Texture>()->AddPersistent("builtin.mr", std::move(mrTexture));
|
||||||
@ -155,7 +155,7 @@ Application::Application(const char* appName, const char* appVersion, gfx::Graph
|
|||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
{
|
{
|
||||||
m_renderer->GetDevice()->ShutdownImguiBackend();
|
m_renderer->GetDevice()->shutdownImguiBackend();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
ImGui::DestroyContext(im_gui_things.context);
|
ImGui::DestroyContext(im_gui_things.context);
|
||||||
}
|
}
|
||||||
@ -177,16 +177,16 @@ void Application::gameLoop()
|
|||||||
bool show_info_window = false;
|
bool show_info_window = false;
|
||||||
} debug_menu_state;
|
} debug_menu_state;
|
||||||
debug_menu_state.enable_frame_limiter = m_configuration.enable_frame_limiter;
|
debug_menu_state.enable_frame_limiter = m_configuration.enable_frame_limiter;
|
||||||
switch (m_renderer->GetDevice()->GetPresentMode()) {
|
switch (m_renderer->GetDevice()->getPresentMode()) {
|
||||||
case gfx::PresentMode::kDoubleBufferedNoVsync:
|
case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
|
||||||
debug_menu_state.triple_buffering = false;
|
debug_menu_state.triple_buffering = false;
|
||||||
debug_menu_state.vsync = false;
|
debug_menu_state.vsync = false;
|
||||||
break;
|
break;
|
||||||
case gfx::PresentMode::kDoubleBufferedVsync:
|
case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
|
||||||
debug_menu_state.triple_buffering = false;
|
debug_menu_state.triple_buffering = false;
|
||||||
debug_menu_state.vsync = true;
|
debug_menu_state.vsync = true;
|
||||||
break;
|
break;
|
||||||
case gfx::PresentMode::kTripleBuffered:
|
case gfx::PresentMode::TRIPLE_BUFFERED:
|
||||||
debug_menu_state.triple_buffering = true;
|
debug_menu_state.triple_buffering = true;
|
||||||
debug_menu_state.vsync = false;
|
debug_menu_state.vsync = false;
|
||||||
}
|
}
|
||||||
@ -207,7 +207,7 @@ void Application::gameLoop()
|
|||||||
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
|
if (now - lastTick >= 1000000000LL * 5LL) [[unlikely]] {
|
||||||
lastTick = now;
|
lastTick = now;
|
||||||
LOG_DEBUG("fps: {}", std::lroundf(avg_fps));
|
LOG_DEBUG("fps: {}", std::lroundf(avg_fps));
|
||||||
getRenderer()->GetDevice()->LogPerformanceInfo();
|
getRenderer()->GetDevice()->logPerformanceInfo();
|
||||||
m_window->ResetAvgFPS();
|
m_window->ResetAvgFPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,10 +246,10 @@ void Application::gameLoop()
|
|||||||
}
|
}
|
||||||
if (ImGui::Checkbox("Enable vsync", &debug_menu_state.vsync)) {
|
if (ImGui::Checkbox("Enable vsync", &debug_menu_state.vsync)) {
|
||||||
if (debug_menu_state.vsync) {
|
if (debug_menu_state.vsync) {
|
||||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync);
|
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_VSYNC);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync);
|
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug_menu_state.triple_buffering) {
|
if (debug_menu_state.triple_buffering) {
|
||||||
@ -258,14 +258,14 @@ void Application::gameLoop()
|
|||||||
if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) {
|
if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) {
|
||||||
if (debug_menu_state.triple_buffering) {
|
if (debug_menu_state.triple_buffering) {
|
||||||
debug_menu_state.vsync = false;
|
debug_menu_state.vsync = false;
|
||||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kTripleBuffered);
|
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::TRIPLE_BUFFERED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (debug_menu_state.vsync) {
|
if (debug_menu_state.vsync) {
|
||||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync);
|
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_VSYNC);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_renderer->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync);
|
m_renderer->GetDevice()->changePresentMode(gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,9 +276,9 @@ void Application::gameLoop()
|
|||||||
if (!scene) ImGui::BeginDisabled();
|
if (!scene) ImGui::BeginDisabled();
|
||||||
// load gltf file dialog
|
// load gltf file dialog
|
||||||
if (ImGui::Button("Load glTF")) {
|
if (ImGui::Button("Load glTF")) {
|
||||||
std::filesystem::path path = util::OpenFileDialog({"glb"});
|
std::filesystem::path path = openFileDialog({"glb"});
|
||||||
if (path.empty() == false) {
|
if (path.empty() == false) {
|
||||||
util::LoadGLTF(*scene, path.string(), false);
|
loadGLTF(*scene, path.string(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!scene) ImGui::EndDisabled();
|
if (!scene) ImGui::EndDisabled();
|
||||||
@ -534,7 +534,7 @@ void Application::gameLoop()
|
|||||||
delta_times[m_window->GetFrameCount() % delta_times.size()] = m_window->dt();
|
delta_times[m_window->GetFrameCount() % delta_times.size()] = m_window->dt();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderer->GetDevice()->WaitIdle();
|
m_renderer->GetDevice()->waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
namespace engine::util {
|
namespace engine {
|
||||||
|
|
||||||
std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions)
|
std::filesystem::path openFileDialog(const std::vector<std::string>& extensions)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
@ -55,4 +55,4 @@ std::filesystem::path OpenFileDialog(const std::vector<std::string>& extensions)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path)
|
std::unique_ptr<std::vector<char>> readTextFile(const std::string& path)
|
||||||
{
|
{
|
||||||
std::ifstream file(path, std::ios::ate);
|
std::ifstream file(path, std::ios::ate);
|
||||||
if (file.is_open() == false) {
|
if (file.is_open() == false) {
|
||||||
@ -39,7 +39,7 @@ std::unique_ptr<std::vector<char>> ReadTextFile(const std::string& path)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path)
|
std::unique_ptr<std::vector<uint8_t>> readBinaryFile(const std::string& path)
|
||||||
{
|
{
|
||||||
std::ifstream file(path, std::ios::ate | std::ios::binary);
|
std::ifstream file(path, std::ios::ate | std::ios::binary);
|
||||||
if (file.is_open() == false) {
|
if (file.is_open() == false) {
|
||||||
@ -55,7 +55,7 @@ std::unique_ptr<std::vector<uint8_t>> ReadBinaryFile(const std::string& path)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<std::vector<uint8_t>> ReadImageFile(const std::string& path, int& width, int& height)
|
std::unique_ptr<std::vector<uint8_t>> readImageFile(const std::string& path, int& width, int& height)
|
||||||
{
|
{
|
||||||
int x, y, n;
|
int x, y, n;
|
||||||
unsigned char* data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp
|
unsigned char* data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); // Image is 4 bpp
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
#include "resource_mesh.h"
|
#include "resource_mesh.h"
|
||||||
|
|
||||||
namespace engine::util {
|
namespace engine {
|
||||||
|
|
||||||
std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& vertices)
|
std::vector<uint32_t> genTangents(std::vector<engine::Vertex>& vertices)
|
||||||
{
|
{
|
||||||
|
|
||||||
using VertList = std::vector<Vertex>;
|
using VertList = std::vector<Vertex>;
|
||||||
@ -64,8 +64,8 @@ std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& ver
|
|||||||
std::vector<uint32_t> remap_table(vertices.size()); // initialised to zeros
|
std::vector<uint32_t> remap_table(vertices.size()); // initialised to zeros
|
||||||
std::vector<Vertex> vertex_data_out(vertices.size()); // initialised to zeros
|
std::vector<Vertex> vertex_data_out(vertices.size()); // initialised to zeros
|
||||||
|
|
||||||
const int new_vertex_count = WeldMesh(reinterpret_cast<int*>(remap_table.data()), reinterpret_cast<float*>(vertex_data_out.data()), reinterpret_cast<float*>(vertices.data()),
|
const int new_vertex_count = WeldMesh(reinterpret_cast<int*>(remap_table.data()), reinterpret_cast<float*>(vertex_data_out.data()),
|
||||||
static_cast<int>(vertices.size()), Vertex::floatsPerVertex());
|
reinterpret_cast<float*>(vertices.data()), static_cast<int>(vertices.size()), Vertex::floatsPerVertex());
|
||||||
assert(new_vertex_count >= 0);
|
assert(new_vertex_count >= 0);
|
||||||
|
|
||||||
// get new vertices into the vector.
|
// get new vertices into the vector.
|
||||||
@ -78,4 +78,4 @@ std::vector<uint32_t> engine::util::GenTangents(std::vector<engine::Vertex>& ver
|
|||||||
return remap_table;
|
return remap_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
@ -140,11 +140,11 @@ namespace converters {
|
|||||||
static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
|
static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
|
||||||
{
|
{
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case gfx::VertexAttribFormat::kFloat2:
|
case gfx::VertexAttribFormat::FLOAT2:
|
||||||
return VK_FORMAT_R32G32_SFLOAT;
|
return VK_FORMAT_R32G32_SFLOAT;
|
||||||
case gfx::VertexAttribFormat::kFloat3:
|
case gfx::VertexAttribFormat::FLOAT3:
|
||||||
return VK_FORMAT_R32G32B32_SFLOAT;
|
return VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
case gfx::VertexAttribFormat::kFloat4:
|
case gfx::VertexAttribFormat::FLOAT4:
|
||||||
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown vertex attribute format");
|
throw std::runtime_error("Unknown vertex attribute format");
|
||||||
@ -153,11 +153,11 @@ static VkFormat getVertexAttribFormat(gfx::VertexAttribFormat fmt)
|
|||||||
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case gfx::BufferType::kVertex:
|
case gfx::BufferType::VERTEX:
|
||||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
case gfx::BufferType::kIndex:
|
case gfx::BufferType::INDEX:
|
||||||
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
case gfx::BufferType::kUniform:
|
case gfx::BufferType::UNIFORM:
|
||||||
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("This buffer type does not have usage bits");
|
throw std::runtime_error("This buffer type does not have usage bits");
|
||||||
@ -167,9 +167,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
|||||||
[[maybe_unused]] static VkFilter getFilter(gfx::Filter filter)
|
[[maybe_unused]] static VkFilter getFilter(gfx::Filter filter)
|
||||||
{
|
{
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case gfx::Filter::kLinear:
|
case gfx::Filter::LINEAR:
|
||||||
return VK_FILTER_LINEAR;
|
return VK_FILTER_LINEAR;
|
||||||
case gfx::Filter::kNearest:
|
case gfx::Filter::NEAREST:
|
||||||
return VK_FILTER_NEAREST;
|
return VK_FILTER_NEAREST;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown filter");
|
throw std::runtime_error("Unknown filter");
|
||||||
@ -178,13 +178,13 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
|||||||
[[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode)
|
[[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case gfx::WrapMode::kRepeat:
|
case gfx::WrapMode::REPEAT:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
case gfx::WrapMode::kMirroredRepeat:
|
case gfx::WrapMode::MIRRORED_REPEAT:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||||
case gfx::WrapMode::kClampToEdge:
|
case gfx::WrapMode::CLAMP_TO_EDGE:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||||
case gfx::WrapMode::kClampToBorder:
|
case gfx::WrapMode::CLAMP_TO_BORDER:
|
||||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown wrap mode");
|
throw std::runtime_error("Unknown wrap mode");
|
||||||
@ -193,9 +193,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
|||||||
[[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter)
|
[[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter)
|
||||||
{
|
{
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case gfx::Filter::kLinear:
|
case gfx::Filter::LINEAR:
|
||||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
case gfx::Filter::kNearest:
|
case gfx::Filter::NEAREST:
|
||||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("Unknown filter");
|
throw std::runtime_error("Unknown filter");
|
||||||
@ -204,15 +204,15 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
|||||||
[[maybe_unused]] static VkSampleCountFlagBits getSampleCountFlags(gfx::MSAALevel level)
|
[[maybe_unused]] static VkSampleCountFlagBits getSampleCountFlags(gfx::MSAALevel level)
|
||||||
{
|
{
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case gfx::MSAALevel::kOff:
|
case gfx::MSAALevel::MSAA_OFF:
|
||||||
return VK_SAMPLE_COUNT_1_BIT;
|
return VK_SAMPLE_COUNT_1_BIT;
|
||||||
case gfx::MSAALevel::k2X:
|
case gfx::MSAALevel::MSAA_2X:
|
||||||
return VK_SAMPLE_COUNT_2_BIT;
|
return VK_SAMPLE_COUNT_2_BIT;
|
||||||
case gfx::MSAALevel::k4X:
|
case gfx::MSAALevel::MSAA_4X:
|
||||||
return VK_SAMPLE_COUNT_4_BIT;
|
return VK_SAMPLE_COUNT_4_BIT;
|
||||||
case gfx::MSAALevel::k8X:
|
case gfx::MSAALevel::MSAA_8X:
|
||||||
return VK_SAMPLE_COUNT_8_BIT;
|
return VK_SAMPLE_COUNT_8_BIT;
|
||||||
case gfx::MSAALevel::k16X:
|
case gfx::MSAALevel::MSAA_16X:
|
||||||
return VK_SAMPLE_COUNT_16_BIT;
|
return VK_SAMPLE_COUNT_16_BIT;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown MSAA level");
|
throw std::runtime_error("Unknown MSAA level");
|
||||||
@ -222,9 +222,9 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type)
|
|||||||
static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
|
static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case gfx::DescriptorType::kUniformBuffer:
|
case gfx::DescriptorType::UNIFORM_BUFFER:
|
||||||
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
case gfx::DescriptorType::kCombinedImageSampler:
|
case gfx::DescriptorType::COMBINED_IMAGE_SAMPLER:
|
||||||
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown descriptor type");
|
throw std::runtime_error("Unknown descriptor type");
|
||||||
@ -234,21 +234,21 @@ static VkDescriptorType getDescriptorType(gfx::DescriptorType type)
|
|||||||
static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags)
|
static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags)
|
||||||
{
|
{
|
||||||
VkShaderStageFlags out = 0;
|
VkShaderStageFlags out = 0;
|
||||||
if (flags & gfx::ShaderStageFlags::kVertex) out |= VK_SHADER_STAGE_VERTEX_BIT;
|
if (flags & gfx::ShaderStageFlags::VERTEX) out |= VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
if (flags & gfx::ShaderStageFlags::kFragment) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
if (flags & gfx::ShaderStageFlags::FRAGMENT) out |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
|
static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case gfx::CullMode::kCullNone:
|
case gfx::CullMode::CULL_NONE:
|
||||||
return VK_CULL_MODE_NONE;
|
return VK_CULL_MODE_NONE;
|
||||||
case gfx::CullMode::kCullFront:
|
case gfx::CullMode::CULL_FRONT:
|
||||||
return VK_CULL_MODE_FRONT_BIT;
|
return VK_CULL_MODE_FRONT_BIT;
|
||||||
case gfx::CullMode::kCullBack:
|
case gfx::CullMode::CULL_BACK:
|
||||||
return VK_CULL_MODE_BACK_BIT;
|
return VK_CULL_MODE_BACK_BIT;
|
||||||
case gfx::CullMode::kCullFrontAndBack:
|
case gfx::CullMode::CULL_FRONT_AND_BACK:
|
||||||
return VK_CULL_MODE_FRONT_AND_BACK;
|
return VK_CULL_MODE_FRONT_AND_BACK;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown cull mode");
|
throw std::runtime_error("Unknown cull mode");
|
||||||
@ -258,9 +258,9 @@ static VkCullModeFlags getCullModeFlags(gfx::CullMode mode)
|
|||||||
static VkFormat getImageFormat(gfx::ImageFormat format)
|
static VkFormat getImageFormat(gfx::ImageFormat format)
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case gfx::ImageFormat::kLinear:
|
case gfx::ImageFormat::LINEAR:
|
||||||
return VK_FORMAT_R8G8B8A8_UNORM;
|
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
case gfx::ImageFormat::kSRGB:
|
case gfx::ImageFormat::SRGB:
|
||||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown image format");
|
throw std::runtime_error("Unknown image format");
|
||||||
@ -562,7 +562,7 @@ GFXDevice::~GFXDevice()
|
|||||||
destroyVulkanInstance(pimpl->instance);
|
destroyVulkanInstance(pimpl->instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
|
void GFXDevice::getViewportSize(uint32_t* w, uint32_t* h)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
|
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
|
||||||
@ -576,28 +576,28 @@ void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::ChangePresentMode(gfx::PresentMode mode)
|
void GFXDevice::changePresentMode(gfx::PresentMode mode)
|
||||||
{
|
{
|
||||||
pimpl->swapchainInfo.requested_present_mode = mode;
|
pimpl->swapchainInfo.requested_present_mode = mode;
|
||||||
// need to recreate swapchain to apply changes
|
// need to recreate swapchain to apply changes
|
||||||
pimpl->swapchainIsOutOfDate = true;
|
pimpl->swapchainIsOutOfDate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::PresentMode GFXDevice::GetPresentMode()
|
gfx::PresentMode GFXDevice::getPresentMode()
|
||||||
{
|
{
|
||||||
switch (pimpl->swapchain.presentMode) {
|
switch (pimpl->swapchain.presentMode) {
|
||||||
case VK_PRESENT_MODE_FIFO_KHR:
|
case VK_PRESENT_MODE_FIFO_KHR:
|
||||||
return gfx::PresentMode::kDoubleBufferedVsync;
|
return gfx::PresentMode::DOUBLE_BUFFERED_VSYNC;
|
||||||
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||||
return gfx::PresentMode::kDoubleBufferedNoVsync;
|
return gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC;
|
||||||
case VK_PRESENT_MODE_MAILBOX_KHR:
|
case VK_PRESENT_MODE_MAILBOX_KHR:
|
||||||
return gfx::PresentMode::kTripleBuffered;
|
return gfx::PresentMode::TRIPLE_BUFFERED;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown present mode");
|
throw std::runtime_error("Unknown present mode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::SetupImguiBackend()
|
void GFXDevice::setupImguiBackend()
|
||||||
{
|
{
|
||||||
auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction {
|
auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction {
|
||||||
return vkGetInstanceProcAddr(*reinterpret_cast<VkInstance*>(user_data), function_name);
|
return vkGetInstanceProcAddr(*reinterpret_cast<VkInstance*>(user_data), function_name);
|
||||||
@ -630,18 +630,18 @@ void GFXDevice::SetupImguiBackend()
|
|||||||
ImGui_ImplVulkan_CreateFontsTexture();
|
ImGui_ImplVulkan_CreateFontsTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::ShutdownImguiBackend()
|
void GFXDevice::shutdownImguiBackend()
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_DestroyFontsTexture();
|
ImGui_ImplVulkan_DestroyFontsTexture();
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data)
|
void GFXDevice::cmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf);
|
ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
|
gfx::DrawBuffer* GFXDevice::beginRender(bool window_resized)
|
||||||
{
|
{
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
@ -899,7 +899,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
|
|||||||
return drawBuffer;
|
return drawBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
|
|
||||||
@ -1009,7 +1009,7 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
|||||||
delete drawBuffer;
|
delete drawBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Image* GFXDevice::CreateShadowmapImage()
|
gfx::Image* GFXDevice::createImageShadowmap()
|
||||||
{
|
{
|
||||||
if (pimpl->FRAMECOUNT != 0) abort();
|
if (pimpl->FRAMECOUNT != 0) abort();
|
||||||
|
|
||||||
@ -1054,7 +1054,7 @@ gfx::Image* GFXDevice::CreateShadowmapImage()
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::DrawBuffer* GFXDevice::BeginShadowmapRender(gfx::Image* image)
|
gfx::DrawBuffer* GFXDevice::beginShadowmapRender(gfx::Image* image)
|
||||||
{
|
{
|
||||||
assert(image != nullptr);
|
assert(image != nullptr);
|
||||||
if (pimpl->FRAMECOUNT != 0) throw std::runtime_error("Can only create shadowmap before proper rendering begins.");
|
if (pimpl->FRAMECOUNT != 0) throw std::runtime_error("Can only create shadowmap before proper rendering begins.");
|
||||||
@ -1152,7 +1152,7 @@ gfx::DrawBuffer* GFXDevice::BeginShadowmapRender(gfx::Image* image)
|
|||||||
return drawBuffer;
|
return drawBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image)
|
void GFXDevice::finishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image* image)
|
||||||
{
|
{
|
||||||
assert(draw_buffer != nullptr);
|
assert(draw_buffer != nullptr);
|
||||||
|
|
||||||
@ -1211,44 +1211,44 @@ void GFXDevice::FinishShadowmapRender(gfx::DrawBuffer* draw_buffer, gfx::Image*
|
|||||||
delete draw_buffer;
|
delete draw_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
|
void GFXDevice::cmdBindPipeline(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
assert(pipeline != nullptr);
|
assert(pipeline != nullptr);
|
||||||
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
vkCmdBindPipeline(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
|
void GFXDevice::cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
assert(buffer->type == gfx::BufferType::kVertex);
|
assert(buffer->type == gfx::BufferType::VERTEX);
|
||||||
const VkDeviceSize offset = 0;
|
const VkDeviceSize offset = 0;
|
||||||
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset);
|
vkCmdBindVertexBuffers(drawBuffer->frameData.drawBuf, binding, 1, &buffer->buffer, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
|
void GFXDevice::cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
assert(buffer->type == gfx::BufferType::kIndex);
|
assert(buffer->type == gfx::BufferType::INDEX);
|
||||||
vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE);
|
vkCmdBindIndexBuffer(drawBuffer->frameData.drawBuf, buffer->buffer, 0, INDEX_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
|
void GFXDevice::cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
|
||||||
uint32_t firstInstance)
|
uint32_t firstInstance)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)
|
void GFXDevice::cmdDraw(gfx::DrawBuffer* drawBuffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count, first_vertex, first_instance);
|
vkCmdDraw(drawBuffer->frameData.drawBuf, vertex_count, instance_count, first_vertex, first_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data)
|
void GFXDevice::cmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, uint32_t offset, uint32_t size, const void* data)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
assert(pipeline != nullptr);
|
assert(pipeline != nullptr);
|
||||||
@ -1256,7 +1256,7 @@ void GFXDevice::CmdPushConstants(gfx::DrawBuffer* drawBuffer, const gfx::Pipelin
|
|||||||
vkCmdPushConstants(drawBuffer->frameData.drawBuf, pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, offset, size, data);
|
vkCmdPushConstants(drawBuffer->frameData.drawBuf, pipeline->layout, VK_SHADER_STAGE_VERTEX_BIT, offset, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::CmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
|
void GFXDevice::cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
|
||||||
{
|
{
|
||||||
assert(drawBuffer != nullptr);
|
assert(drawBuffer != nullptr);
|
||||||
assert(pipeline != nullptr);
|
assert(pipeline != nullptr);
|
||||||
@ -1265,7 +1265,7 @@ void GFXDevice::CmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pip
|
|||||||
&set->sets[drawBuffer->currentFrameIndex], 0, nullptr);
|
&set->sets[drawBuffer->currentFrameIndex], 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
gfx::Pipeline* GFXDevice::createPipeline(const gfx::PipelineInfo& info)
|
||||||
{
|
{
|
||||||
[[maybe_unused]] VkResult res;
|
[[maybe_unused]] VkResult res;
|
||||||
|
|
||||||
@ -1273,13 +1273,13 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
|||||||
|
|
||||||
VkShaderModule vertShaderModule;
|
VkShaderModule vertShaderModule;
|
||||||
VkShaderModule fragShaderModule;
|
VkShaderModule fragShaderModule;
|
||||||
// be careful with these .c_str() calls. It is OK here because 'info' exists for the duration of CreatePipeline()
|
// be careful with these .c_str() calls. It is OK here because 'info' exists for the duration of createPipeline()
|
||||||
{
|
{
|
||||||
auto vertShaderCode = ReadTextFile(info.vert_shader_path.c_str());
|
auto vertShaderCode = readTextFile(info.vert_shader_path.c_str());
|
||||||
vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vert_shader_path.c_str());
|
vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vert_shader_path.c_str());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto fragShaderCode = ReadTextFile(info.frag_shader_path.c_str());
|
auto fragShaderCode = readTextFile(info.frag_shader_path.c_str());
|
||||||
fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.frag_shader_path.c_str());
|
fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.frag_shader_path.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1497,7 +1497,7 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline)
|
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
assert(pipeline != nullptr);
|
assert(pipeline != nullptr);
|
||||||
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
|
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
|
||||||
@ -1505,7 +1505,7 @@ void GFXDevice::DestroyPipeline(const gfx::Pipeline* pipeline)
|
|||||||
delete pipeline;
|
delete pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings)
|
gfx::DescriptorSetLayout* GFXDevice::createDescriptorSetLayout(const std::vector<gfx::DescriptorSetLayoutBinding>& bindings)
|
||||||
{
|
{
|
||||||
gfx::DescriptorSetLayout* out = new gfx::DescriptorSetLayout{};
|
gfx::DescriptorSetLayout* out = new gfx::DescriptorSetLayout{};
|
||||||
|
|
||||||
@ -1532,13 +1532,13 @@ gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
|
void GFXDevice::destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
|
||||||
{
|
{
|
||||||
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
|
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
|
||||||
delete layout;
|
delete layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
|
gfx::DescriptorSet* GFXDevice::allocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
|
||||||
{
|
{
|
||||||
assert(layout != nullptr);
|
assert(layout != nullptr);
|
||||||
|
|
||||||
@ -1560,13 +1560,13 @@ gfx::DescriptorSet* GFXDevice::AllocateDescriptorSet(const gfx::DescriptorSetLay
|
|||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::FreeDescriptorSet(const gfx::DescriptorSet* set)
|
void GFXDevice::freeDescriptorSet(const gfx::DescriptorSet* set)
|
||||||
{
|
{
|
||||||
assert(set != nullptr);
|
assert(set != nullptr);
|
||||||
VKCHECK(vkFreeDescriptorSets(pimpl->device.device, pimpl->descriptorPool, static_cast<uint32_t>(set->sets.size()), set->sets.data()));
|
VKCHECK(vkFreeDescriptorSets(pimpl->device.device, pimpl->descriptorPool, static_cast<uint32_t>(set->sets.size()), set->sets.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range)
|
void GFXDevice::updateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uint32_t binding, const gfx::UniformBuffer* buffer, size_t offset, size_t range)
|
||||||
{
|
{
|
||||||
assert(set != nullptr);
|
assert(set != nullptr);
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
@ -1589,7 +1589,7 @@ void GFXDevice::UpdateDescriptorUniformBuffer(const gfx::DescriptorSet* set, uin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler)
|
void GFXDevice::updateDescriptorCombinedImageSampler(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Image* image, const gfx::Sampler* sampler)
|
||||||
{
|
{
|
||||||
assert(set != nullptr);
|
assert(set != nullptr);
|
||||||
assert(image != nullptr);
|
assert(image != nullptr);
|
||||||
@ -1617,7 +1617,7 @@ void GFXDevice::UpdateDescriptorCombinedImageSampler(const gfx::DescriptorSet* s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* initialData)
|
gfx::UniformBuffer* GFXDevice::createUniformBuffer(uint64_t size, const void* initialData)
|
||||||
{
|
{
|
||||||
assert(initialData != nullptr);
|
assert(initialData != nullptr);
|
||||||
|
|
||||||
@ -1627,7 +1627,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
|
|||||||
|
|
||||||
/* first make staging buffer */
|
/* first make staging buffer */
|
||||||
out->stagingBuffer.size = size;
|
out->stagingBuffer.size = size;
|
||||||
out->stagingBuffer.type = gfx::BufferType::kUniform;
|
out->stagingBuffer.type = gfx::BufferType::UNIFORM;
|
||||||
{
|
{
|
||||||
VkBufferCreateInfo stagingBufferInfo{};
|
VkBufferCreateInfo stagingBufferInfo{};
|
||||||
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
@ -1653,7 +1653,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
|
|||||||
/* create the device-local set of buffers */
|
/* create the device-local set of buffers */
|
||||||
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
out->gpuBuffers[i].size = out->stagingBuffer.size;
|
out->gpuBuffers[i].size = out->stagingBuffer.size;
|
||||||
out->gpuBuffers[i].type = gfx::BufferType::kUniform;
|
out->gpuBuffers[i].type = gfx::BufferType::UNIFORM;
|
||||||
|
|
||||||
VkBufferCreateInfo gpuBufferInfo{};
|
VkBufferCreateInfo gpuBufferInfo{};
|
||||||
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
@ -1677,7 +1677,7 @@ gfx::UniformBuffer* GFXDevice::CreateUniformBuffer(uint64_t size, const void* in
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
|
void GFXDevice::destroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
|
||||||
{
|
{
|
||||||
assert(uniformBuffer != nullptr);
|
assert(uniformBuffer != nullptr);
|
||||||
|
|
||||||
@ -1690,7 +1690,7 @@ void GFXDevice::DestroyUniformBuffer(const gfx::UniformBuffer* uniformBuffer)
|
|||||||
delete uniformBuffer;
|
delete uniformBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data)
|
void GFXDevice::writeUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset, uint64_t size, const void* data)
|
||||||
{
|
{
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
assert(data != nullptr);
|
assert(data != nullptr);
|
||||||
@ -1710,7 +1710,7 @@ void GFXDevice::WriteUniformBuffer(gfx::UniformBuffer* buffer, uint64_t offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Buffer* GFXDevice::CreateBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
||||||
{
|
{
|
||||||
assert(data != nullptr);
|
assert(data != nullptr);
|
||||||
|
|
||||||
@ -1769,7 +1769,7 @@ gfx::Buffer* GFXDevice::CreateBuffer(gfx::BufferType type, uint64_t size, const
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
|
void GFXDevice::destroyBuffer(const gfx::Buffer* buffer)
|
||||||
{
|
{
|
||||||
assert(buffer != nullptr);
|
assert(buffer != nullptr);
|
||||||
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
|
vmaDestroyBuffer(pimpl->allocator, buffer->buffer, buffer->allocation);
|
||||||
@ -1777,7 +1777,7 @@ void GFXDevice::DestroyBuffer(const gfx::Buffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// imageData must have pixel format R8G8B8A8
|
// imageData must have pixel format R8G8B8A8
|
||||||
gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* imageData)
|
gfx::Image* GFXDevice::createImage(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const void* imageData)
|
||||||
{
|
{
|
||||||
assert(imageData != nullptr);
|
assert(imageData != nullptr);
|
||||||
|
|
||||||
@ -2032,7 +2032,7 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data)
|
gfx::Image* GFXDevice::createImageCubemap(uint32_t w, uint32_t h, gfx::ImageFormat input_format, const std::array<const void*, 6>& image_data)
|
||||||
{
|
{
|
||||||
assert(image_data[0] != nullptr);
|
assert(image_data[0] != nullptr);
|
||||||
assert(image_data[1] != nullptr);
|
assert(image_data[1] != nullptr);
|
||||||
@ -2291,7 +2291,7 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroyImage(const gfx::Image* image)
|
void GFXDevice::destroyImage(const gfx::Image* image)
|
||||||
{
|
{
|
||||||
assert(image != nullptr);
|
assert(image != nullptr);
|
||||||
vkDestroyImageView(pimpl->device.device, image->view, nullptr);
|
vkDestroyImageView(pimpl->device.device, image->view, nullptr);
|
||||||
@ -2299,7 +2299,7 @@ void GFXDevice::DestroyImage(const gfx::Image* image)
|
|||||||
delete image;
|
delete image;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gfx::Sampler* GFXDevice::CreateSampler(const gfx::SamplerInfo& info)
|
const gfx::Sampler* GFXDevice::createSampler(const gfx::SamplerInfo& info)
|
||||||
{
|
{
|
||||||
gfx::Sampler* out = new gfx::Sampler{};
|
gfx::Sampler* out = new gfx::Sampler{};
|
||||||
|
|
||||||
@ -2323,14 +2323,14 @@ const gfx::Sampler* GFXDevice::CreateSampler(const gfx::SamplerInfo& info)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::DestroySampler(const gfx::Sampler* sampler)
|
void GFXDevice::destroySampler(const gfx::Sampler* sampler)
|
||||||
{
|
{
|
||||||
assert(sampler != nullptr);
|
assert(sampler != nullptr);
|
||||||
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
|
vkDestroySampler(pimpl->device.device, sampler->sampler, nullptr);
|
||||||
delete sampler;
|
delete sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::LogPerformanceInfo()
|
void GFXDevice::logPerformanceInfo()
|
||||||
{
|
{
|
||||||
VmaTotalStatistics pStats{};
|
VmaTotalStatistics pStats{};
|
||||||
vmaCalculateStatistics(pimpl->allocator, &pStats);
|
vmaCalculateStatistics(pimpl->allocator, &pStats);
|
||||||
@ -2354,8 +2354,9 @@ void GFXDevice::LogPerformanceInfo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GFXDevice::GetFrameCount() { return pimpl->FRAMECOUNT; }
|
uint64_t GFXDevice::getFrameCount() { return pimpl->FRAMECOUNT; }
|
||||||
|
|
||||||
void GFXDevice::WaitIdle() { vkDeviceWaitIdle(pimpl->device.device); }
|
/* Waits until all the active GPU queues have finished working */
|
||||||
|
void GFXDevice::waitIdle() { vkDeviceWaitIdle(pimpl->device.device); }
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
@ -38,7 +38,7 @@ struct std::hash<Color> {
|
|||||||
|
|
||||||
namespace tg = tinygltf;
|
namespace tg = tinygltf;
|
||||||
|
|
||||||
namespace engine::util {
|
namespace engine {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
@ -88,7 +88,17 @@ static glm::mat4 MatFromDoubleArray(const std::vector<double>& arr)
|
|||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
/*
|
||||||
|
* Loads the default scene found in a glTF file into 'scene'.
|
||||||
|
* 'isStatic' will mark every transform as static to aid rendering optimisation.
|
||||||
|
* Returns the top-level glTF node as an engine entity.
|
||||||
|
*
|
||||||
|
* Loader limitations:
|
||||||
|
* - Can only load .glb files
|
||||||
|
* - glTF files must contain all textures
|
||||||
|
* - No extension support
|
||||||
|
*/
|
||||||
|
engine::Entity loadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||||
{
|
{
|
||||||
|
|
||||||
LOG_INFO("Loading gltf file: {}", path);
|
LOG_INFO("Loading gltf file: {}", path);
|
||||||
@ -161,46 +171,46 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
|
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
// default to trilinear filtering even if mipmaps are not specified
|
// default to trilinear filtering even if mipmaps are not specified
|
||||||
samplerInfo.minify = gfx::Filter::kLinear;
|
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||||
samplerInfo.magnify = gfx::Filter::kLinear;
|
samplerInfo.magnify = gfx::Filter::LINEAR;
|
||||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||||
if (texture.sampler != -1) {
|
if (texture.sampler != -1) {
|
||||||
const tg::Sampler& sampler = model.samplers.at(texture.sampler);
|
const tg::Sampler& sampler = model.samplers.at(texture.sampler);
|
||||||
switch (sampler.minFilter) {
|
switch (sampler.minFilter) {
|
||||||
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
||||||
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR:
|
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR:
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||||
break;
|
break;
|
||||||
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST:
|
case TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST:
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
break;
|
break;
|
||||||
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
||||||
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR:
|
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR:
|
||||||
samplerInfo.minify = gfx::Filter::kLinear;
|
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||||
samplerInfo.mipmap = gfx::Filter::kLinear;
|
samplerInfo.mipmap = gfx::Filter::LINEAR;
|
||||||
break;
|
break;
|
||||||
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST:
|
case TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST:
|
||||||
samplerInfo.minify = gfx::Filter::kLinear;
|
samplerInfo.minify = gfx::Filter::LINEAR;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (sampler.magFilter) {
|
switch (sampler.magFilter) {
|
||||||
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
case TINYGLTF_TEXTURE_FILTER_NEAREST:
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
break;
|
break;
|
||||||
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
case TINYGLTF_TEXTURE_FILTER_LINEAR:
|
||||||
samplerInfo.magnify = gfx::Filter::kLinear;
|
samplerInfo.magnify = gfx::Filter::LINEAR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// use aniso if min filter is LINEAR_MIPMAP_LINEAR
|
// use aniso if min filter is LINEAR_MIPMAP_LINEAR
|
||||||
samplerInfo.anisotropic_filtering = (samplerInfo.minify == gfx::Filter::kLinear && samplerInfo.mipmap == gfx::Filter::kLinear);
|
samplerInfo.anisotropic_filtering = (samplerInfo.minify == gfx::Filter::LINEAR && samplerInfo.mipmap == gfx::Filter::LINEAR);
|
||||||
|
|
||||||
const tg::Image& image = model.images.at(texture.source);
|
const tg::Image& image = model.images.at(texture.source);
|
||||||
if (image.as_is == false && image.bits == 8 && image.component == 4 && image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
|
if (image.as_is == false && image.bits == 8 && image.component == 4 && image.pixel_type == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
|
||||||
@ -265,9 +275,9 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
if (colour_textures.contains(c) == false) {
|
if (colour_textures.contains(c) == false) {
|
||||||
const uint8_t pixel[4] = {c.r, c.g, c.b, c.a};
|
const uint8_t pixel[4] = {c.r, c.g, c.b, c.a};
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
colour_textures.emplace(std::make_pair(c, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, true)));
|
colour_textures.emplace(std::make_pair(c, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, true)));
|
||||||
}
|
}
|
||||||
@ -294,9 +304,9 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
if (metal_rough_textures.contains(mr) == false) {
|
if (metal_rough_textures.contains(mr) == false) {
|
||||||
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
||||||
gfx::SamplerInfo samplerInfo{};
|
gfx::SamplerInfo samplerInfo{};
|
||||||
samplerInfo.minify = gfx::Filter::kNearest;
|
samplerInfo.minify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.magnify = gfx::Filter::kNearest;
|
samplerInfo.magnify = gfx::Filter::NEAREST;
|
||||||
samplerInfo.mipmap = gfx::Filter::kNearest;
|
samplerInfo.mipmap = gfx::Filter::NEAREST;
|
||||||
samplerInfo.anisotropic_filtering = false;
|
samplerInfo.anisotropic_filtering = false;
|
||||||
metal_rough_textures.emplace(std::make_pair(mr, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, false)));
|
metal_rough_textures.emplace(std::make_pair(mr, std::make_shared<Texture>(scene.app()->getRenderer(), pixel, 1, 1, samplerInfo, false)));
|
||||||
}
|
}
|
||||||
@ -672,4 +682,4 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine::util
|
} // namespace engine
|
218
src/renderer.cpp
218
src/renderer.cpp
@ -22,17 +22,17 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
|
std::vector<gfx::DescriptorSetLayoutBinding> globalSetBindings;
|
||||||
{
|
{
|
||||||
auto& binding0 = globalSetBindings.emplace_back();
|
auto& binding0 = globalSetBindings.emplace_back();
|
||||||
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
|
binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
|
||||||
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
|
binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
|
||||||
auto& binding1 = globalSetBindings.emplace_back();
|
auto& binding1 = globalSetBindings.emplace_back();
|
||||||
binding1.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
binding1.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||||
binding1.stage_flags = gfx::ShaderStageFlags::kFragment;
|
binding1.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||||
auto& binding2 = globalSetBindings.emplace_back();
|
auto& binding2 = globalSetBindings.emplace_back();
|
||||||
binding2.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
binding2.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||||
binding2.stage_flags = gfx::ShaderStageFlags::kFragment;
|
binding2.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||||
}
|
}
|
||||||
global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings);
|
global_uniform.layout = device_->createDescriptorSetLayout(globalSetBindings);
|
||||||
global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout);
|
global_uniform.set = device_->allocateDescriptorSet(global_uniform.layout);
|
||||||
const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f;
|
const glm::vec3 light_location = glm::vec3{-0.4278, 0.7923, 0.43502} * 40.0f;
|
||||||
// const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f};
|
// const glm::vec3 light_location = glm::vec3{10.0f, 0.0f, 10.0f};
|
||||||
const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f);
|
const glm::mat4 light_proj = glm::orthoRH_ZO(-24.0f, 24.0f, -15.0f, 15.0f, 10.0f, 65.0f);
|
||||||
@ -40,34 +40,34 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f});
|
const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{0.0f, 0.0f, 0.0f}, glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
global_uniform.uniform_buffer_data.data.proj = light_proj;
|
global_uniform.uniform_buffer_data.data.proj = light_proj;
|
||||||
global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view;
|
global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view;
|
||||||
global_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
|
global_uniform.uniform_buffer = device_->createUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
|
||||||
device_->UpdateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data));
|
device_->updateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data));
|
||||||
// binding1 is updated towards the end of the constructor once the skybox texture is loaded
|
// binding1 is updated towards the end of the constructor once the skybox texture is loaded
|
||||||
// binding2 is updated just after that
|
// binding2 is updated just after that
|
||||||
|
|
||||||
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
|
std::vector<gfx::DescriptorSetLayoutBinding> frameSetBindings;
|
||||||
{
|
{
|
||||||
auto& binding0 = frameSetBindings.emplace_back();
|
auto& binding0 = frameSetBindings.emplace_back();
|
||||||
binding0.descriptor_type = gfx::DescriptorType::kUniformBuffer;
|
binding0.descriptor_type = gfx::DescriptorType::UNIFORM_BUFFER;
|
||||||
binding0.stage_flags = gfx::ShaderStageFlags::kVertex;
|
binding0.stage_flags = gfx::ShaderStageFlags::VERTEX;
|
||||||
}
|
}
|
||||||
frame_uniform.layout = device_->CreateDescriptorSetLayout(frameSetBindings);
|
frame_uniform.layout = device_->createDescriptorSetLayout(frameSetBindings);
|
||||||
frame_uniform.set = device_->AllocateDescriptorSet(frame_uniform.layout);
|
frame_uniform.set = device_->allocateDescriptorSet(frame_uniform.layout);
|
||||||
frame_uniform.uniform_buffer_data.data = light_view;
|
frame_uniform.uniform_buffer_data.data = light_view;
|
||||||
frame_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
|
frame_uniform.uniform_buffer = device_->createUniformBuffer(sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
|
||||||
device_->UpdateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data));
|
device_->updateDescriptorUniformBuffer(frame_uniform.set, 0, frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data));
|
||||||
|
|
||||||
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
|
std::vector<gfx::DescriptorSetLayoutBinding> materialSetBindings;
|
||||||
gfx::DescriptorSetLayoutBinding materialSetBinding{};
|
gfx::DescriptorSetLayoutBinding materialSetBinding{};
|
||||||
materialSetBinding.descriptor_type = gfx::DescriptorType::kCombinedImageSampler;
|
materialSetBinding.descriptor_type = gfx::DescriptorType::COMBINED_IMAGE_SAMPLER;
|
||||||
materialSetBinding.stage_flags = gfx::ShaderStageFlags::kFragment;
|
materialSetBinding.stage_flags = gfx::ShaderStageFlags::FRAGMENT;
|
||||||
materialSetBindings.push_back(materialSetBinding); // albedo
|
materialSetBindings.push_back(materialSetBinding); // albedo
|
||||||
materialSetBindings.push_back(materialSetBinding); // normal
|
materialSetBindings.push_back(materialSetBinding); // normal
|
||||||
materialSetBindings.push_back(materialSetBinding); // occlusion
|
materialSetBindings.push_back(materialSetBinding); // occlusion
|
||||||
materialSetBindings.push_back(materialSetBinding); // metallic-roughness
|
materialSetBindings.push_back(materialSetBinding); // metallic-roughness
|
||||||
material_set_layout = device_->CreateDescriptorSetLayout(materialSetBindings);
|
material_set_layout = device_->createDescriptorSetLayout(materialSetBindings);
|
||||||
|
|
||||||
device_->SetupImguiBackend();
|
device_->setupImguiBackend();
|
||||||
|
|
||||||
gfx::VertexFormat debug_vertex_format{};
|
gfx::VertexFormat debug_vertex_format{};
|
||||||
debug_vertex_format.stride = 0;
|
debug_vertex_format.stride = 0;
|
||||||
@ -79,12 +79,12 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
debug_pipeline_info.frag_shader_path = getResourcePath("engine/shaders/debug.frag");
|
debug_pipeline_info.frag_shader_path = getResourcePath("engine/shaders/debug.frag");
|
||||||
debug_pipeline_info.vertex_format = debug_vertex_format;
|
debug_pipeline_info.vertex_format = debug_vertex_format;
|
||||||
debug_pipeline_info.alpha_blending = false;
|
debug_pipeline_info.alpha_blending = false;
|
||||||
debug_pipeline_info.face_cull_mode = gfx::CullMode::kCullNone; // probably ignored for line rendering
|
debug_pipeline_info.face_cull_mode = gfx::CullMode::CULL_NONE; // probably ignored for line rendering
|
||||||
debug_pipeline_info.write_z = false; // lines don't need the depth buffer
|
debug_pipeline_info.write_z = false; // lines don't need the depth buffer
|
||||||
// debug_pipeline_info.descriptor_set_layouts = empty;
|
// debug_pipeline_info.descriptor_set_layouts = empty;
|
||||||
debug_pipeline_info.line_primitives = true;
|
debug_pipeline_info.line_primitives = true;
|
||||||
|
|
||||||
debug_rendering_things_.pipeline = device_->CreatePipeline(debug_pipeline_info);
|
debug_rendering_things_.pipeline = device_->createPipeline(debug_pipeline_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the skybox cubemap and update global skybox combined-image-sampler
|
// create the skybox cubemap and update global skybox combined-image-sampler
|
||||||
@ -97,29 +97,29 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
|
|
||||||
for (int face = 0; face < 6; ++face) {
|
for (int face = 0; face < 6; ++face) {
|
||||||
std::string path = std::string("engine/textures/skybox") + std::to_string(face) + std::string(".jpg");
|
std::string path = std::string("engine/textures/skybox") + std::to_string(face) + std::string(".jpg");
|
||||||
face_unq_ptrs[face] = ReadImageFile(getResourcePath(path), w, h);
|
face_unq_ptrs[face] = readImageFile(getResourcePath(path), w, h);
|
||||||
if (cubemap_w != w || cubemap_h != h) throw std::runtime_error("Skybox textures must be 512x512!");
|
if (cubemap_w != w || cubemap_h != h) throw std::runtime_error("Skybox textures must be 512x512!");
|
||||||
face_unsafe_ptrs[face] = face_unq_ptrs[face]->data();
|
face_unsafe_ptrs[face] = face_unq_ptrs[face]->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
skybox_cubemap = device_->CreateImageCubemap(cubemap_w, cubemap_h, gfx::ImageFormat::kSRGB, face_unsafe_ptrs);
|
skybox_cubemap = device_->createImageCubemap(cubemap_w, cubemap_h, gfx::ImageFormat::SRGB, face_unsafe_ptrs);
|
||||||
gfx::SamplerInfo sampler_info{};
|
gfx::SamplerInfo sampler_info{};
|
||||||
sampler_info.magnify = gfx::Filter::kLinear;
|
sampler_info.magnify = gfx::Filter::LINEAR;
|
||||||
sampler_info.minify = gfx::Filter::kLinear;
|
sampler_info.minify = gfx::Filter::LINEAR;
|
||||||
sampler_info.mipmap = gfx::Filter::kLinear;
|
sampler_info.mipmap = gfx::Filter::LINEAR;
|
||||||
sampler_info.wrap_u = gfx::WrapMode::kClampToEdge;
|
sampler_info.wrap_u = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||||
sampler_info.wrap_v = gfx::WrapMode::kClampToEdge;
|
sampler_info.wrap_v = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||||
sampler_info.wrap_w = gfx::WrapMode::kClampToEdge;
|
sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_EDGE;
|
||||||
sampler_info.anisotropic_filtering = true;
|
sampler_info.anisotropic_filtering = true;
|
||||||
skybox_sampler = device_->CreateSampler(sampler_info);
|
skybox_sampler = device_->createSampler(sampler_info);
|
||||||
|
|
||||||
device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler);
|
device_->updateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create skybox shader
|
// create skybox shader
|
||||||
{
|
{
|
||||||
gfx::VertexFormat vertex_format{};
|
gfx::VertexFormat vertex_format{};
|
||||||
vertex_format.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::kFloat3, 0u);
|
vertex_format.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::FLOAT3, 0u);
|
||||||
vertex_format.stride = 3 * sizeof(float);
|
vertex_format.stride = 3 * sizeof(float);
|
||||||
|
|
||||||
gfx::PipelineInfo pipeline_info{};
|
gfx::PipelineInfo pipeline_info{};
|
||||||
@ -127,13 +127,13 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
pipeline_info.frag_shader_path = getResourcePath("engine/shaders/skybox.frag");
|
pipeline_info.frag_shader_path = getResourcePath("engine/shaders/skybox.frag");
|
||||||
pipeline_info.vertex_format = vertex_format;
|
pipeline_info.vertex_format = vertex_format;
|
||||||
pipeline_info.alpha_blending = false;
|
pipeline_info.alpha_blending = false;
|
||||||
pipeline_info.face_cull_mode = gfx::CullMode::kCullBack;
|
pipeline_info.face_cull_mode = gfx::CullMode::CULL_BACK;
|
||||||
pipeline_info.write_z = false;
|
pipeline_info.write_z = false;
|
||||||
pipeline_info.line_primitives = false;
|
pipeline_info.line_primitives = false;
|
||||||
pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout());
|
pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout());
|
||||||
pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout());
|
pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout());
|
||||||
|
|
||||||
skybox_pipeline = device_->CreatePipeline(pipeline_info);
|
skybox_pipeline = device_->createPipeline(pipeline_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create skybox vertex buffer
|
// create skybox vertex buffer
|
||||||
@ -189,19 +189,19 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
std::swap(v[i], v[i + 2]);
|
std::swap(v[i], v[i + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
skybox_buffer = device_->CreateBuffer(gfx::BufferType::kVertex, v.size() * sizeof(glm::vec3), v.data());
|
skybox_buffer = device_->createBuffer(gfx::BufferType::VERTEX, v.size() * sizeof(glm::vec3), v.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
// shadow map pipeline
|
// shadow map pipeline
|
||||||
gfx::VertexFormat shadowVertexFormat{};
|
gfx::VertexFormat shadowVertexFormat{};
|
||||||
shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped
|
shadowVertexFormat.stride = sizeof(float) * 12; // using the full meshes so a lot of data is skipped
|
||||||
shadowVertexFormat.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::kFloat3, 0u); // position
|
shadowVertexFormat.attribute_descriptions.emplace_back(0u, gfx::VertexAttribFormat::FLOAT3, 0u); // position
|
||||||
shadowVertexFormat.attribute_descriptions.emplace_back(1u, gfx::VertexAttribFormat::kFloat2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv
|
shadowVertexFormat.attribute_descriptions.emplace_back(1u, gfx::VertexAttribFormat::FLOAT2, static_cast<uint32_t>(sizeof(float)) * 10u); // uv
|
||||||
gfx::PipelineInfo shadowPipelineInfo{};
|
gfx::PipelineInfo shadowPipelineInfo{};
|
||||||
shadowPipelineInfo.vert_shader_path = getResourcePath("engine/shaders/shadow.vert");
|
shadowPipelineInfo.vert_shader_path = getResourcePath("engine/shaders/shadow.vert");
|
||||||
shadowPipelineInfo.frag_shader_path = getResourcePath("engine/shaders/shadow.frag");
|
shadowPipelineInfo.frag_shader_path = getResourcePath("engine/shaders/shadow.frag");
|
||||||
shadowPipelineInfo.vertex_format = shadowVertexFormat;
|
shadowPipelineInfo.vertex_format = shadowVertexFormat;
|
||||||
shadowPipelineInfo.face_cull_mode = gfx::CullMode::kCullFront; // shadows care about back faces
|
shadowPipelineInfo.face_cull_mode = gfx::CullMode::CULL_FRONT; // shadows care about back faces
|
||||||
shadowPipelineInfo.alpha_blending = false;
|
shadowPipelineInfo.alpha_blending = false;
|
||||||
shadowPipelineInfo.write_z = true;
|
shadowPipelineInfo.write_z = true;
|
||||||
shadowPipelineInfo.line_primitives = false;
|
shadowPipelineInfo.line_primitives = false;
|
||||||
@ -209,140 +209,142 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati
|
|||||||
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout());
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetGlobalSetLayout());
|
||||||
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetFrameSetLayout());
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetFrameSetLayout());
|
||||||
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout());
|
shadowPipelineInfo.descriptor_set_layouts.emplace_back(GetMaterialSetLayout());
|
||||||
shadow_pipeline = device_->CreatePipeline(shadowPipelineInfo);
|
shadow_pipeline = device_->createPipeline(shadowPipelineInfo);
|
||||||
|
|
||||||
// shadow map image and sampler
|
// shadow map image and sampler
|
||||||
shadow_map = device_->CreateShadowmapImage();
|
shadow_map = device_->createImageShadowmap();
|
||||||
gfx::SamplerInfo sampler_info{};
|
gfx::SamplerInfo sampler_info{};
|
||||||
sampler_info.magnify = gfx::Filter::kLinear;
|
sampler_info.magnify = gfx::Filter::LINEAR;
|
||||||
sampler_info.minify = gfx::Filter::kLinear;
|
sampler_info.minify = gfx::Filter::LINEAR;
|
||||||
sampler_info.mipmap = gfx::Filter::kNearest; // bilinear is apparently good for shadow maps, mips aren't used anyway
|
sampler_info.mipmap = gfx::Filter::NEAREST; // bilinear is apparently good for shadow maps, mips aren't used anyway
|
||||||
sampler_info.wrap_u = gfx::WrapMode::kClampToBorder; // sampler reads 1.0 out of bounds which ensures no shadowing there
|
sampler_info.wrap_u = gfx::WrapMode::CLAMP_TO_BORDER; // sampler reads 1.0 out of bounds which ensures no shadowing there
|
||||||
sampler_info.wrap_v = gfx::WrapMode::kClampToBorder;
|
sampler_info.wrap_v = gfx::WrapMode::CLAMP_TO_BORDER;
|
||||||
sampler_info.wrap_w = gfx::WrapMode::kClampToBorder;
|
sampler_info.wrap_w = gfx::WrapMode::CLAMP_TO_BORDER;
|
||||||
sampler_info.anisotropic_filtering = false; // no mip-maps so aniso won't do anything
|
sampler_info.anisotropic_filtering = false; // no mip-maps so aniso won't do anything
|
||||||
shadow_map_sampler = device_->CreateSampler(sampler_info);
|
shadow_map_sampler = device_->createSampler(sampler_info);
|
||||||
device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler);
|
device_->updateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler);
|
||||||
};
|
};
|
||||||
|
|
||||||
Renderer::~Renderer()
|
Renderer::~Renderer()
|
||||||
{
|
{
|
||||||
device_->DestroySampler(shadow_map_sampler);
|
device_->destroySampler(shadow_map_sampler);
|
||||||
device_->DestroyImage(shadow_map);
|
device_->destroyImage(shadow_map);
|
||||||
device_->DestroyPipeline(shadow_pipeline);
|
device_->destroyPipeline(shadow_pipeline);
|
||||||
|
|
||||||
device_->DestroyBuffer(skybox_buffer);
|
device_->destroyBuffer(skybox_buffer);
|
||||||
device_->DestroyPipeline(skybox_pipeline);
|
device_->destroyPipeline(skybox_pipeline);
|
||||||
device_->DestroySampler(skybox_sampler);
|
device_->destroySampler(skybox_sampler);
|
||||||
device_->DestroyImage(skybox_cubemap);
|
device_->destroyImage(skybox_cubemap);
|
||||||
|
|
||||||
device_->DestroyPipeline(debug_rendering_things_.pipeline);
|
device_->destroyPipeline(debug_rendering_things_.pipeline);
|
||||||
|
|
||||||
for (const auto& [info, sampler] : samplers) {
|
for (const auto& [info, sampler] : samplers) {
|
||||||
device_->DestroySampler(sampler);
|
device_->destroySampler(sampler);
|
||||||
}
|
}
|
||||||
device_->DestroyDescriptorSetLayout(material_set_layout);
|
device_->destroyDescriptorSetLayout(material_set_layout);
|
||||||
|
|
||||||
device_->DestroyUniformBuffer(frame_uniform.uniform_buffer);
|
device_->destroyUniformBuffer(frame_uniform.uniform_buffer);
|
||||||
device_->DestroyDescriptorSetLayout(frame_uniform.layout);
|
device_->destroyDescriptorSetLayout(frame_uniform.layout);
|
||||||
|
|
||||||
device_->DestroyUniformBuffer(global_uniform.uniform_buffer);
|
device_->destroyUniformBuffer(global_uniform.uniform_buffer);
|
||||||
device_->DestroyDescriptorSetLayout(global_uniform.layout);
|
device_->destroyDescriptorSetLayout(global_uniform.layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list, const std::vector<DebugLine>& debug_lines)
|
void Renderer::Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list,
|
||||||
|
const std::vector<DebugLine>& debug_lines)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (window_is_resized) {
|
if (window_is_resized) {
|
||||||
uint32_t w, h;
|
uint32_t w, h;
|
||||||
device_->GetViewportSize(&w, &h);
|
device_->getViewportSize(&w, &h);
|
||||||
viewport_aspect_ratio_ = (float)w / (float)h;
|
viewport_aspect_ratio_ = (float)w / (float)h;
|
||||||
const glm::mat4 proj_matrix =
|
const glm::mat4 proj_matrix =
|
||||||
glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far);
|
glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far);
|
||||||
/* update SET 0 (rarely changing uniforms)*/
|
/* update SET 0 (rarely changing uniforms)*/
|
||||||
global_uniform.uniform_buffer_data.data.proj = proj_matrix;
|
global_uniform.uniform_buffer_data.data.proj = proj_matrix;
|
||||||
device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
|
device_->writeUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::mat4 view_matrix = glm::inverse(camera_transform);
|
const glm::mat4 view_matrix = glm::inverse(camera_transform);
|
||||||
frame_uniform.uniform_buffer_data.data = view_matrix;
|
frame_uniform.uniform_buffer_data.data = view_matrix;
|
||||||
device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
|
device_->writeUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
|
||||||
|
|
||||||
if (rendering_started == false) {
|
if (rendering_started == false) {
|
||||||
// render to shadow map
|
// render to shadow map
|
||||||
gfx::DrawBuffer* shadow_draw = device_->BeginShadowmapRender(shadow_map);
|
gfx::DrawBuffer* shadow_draw = device_->beginShadowmapRender(shadow_map);
|
||||||
device_->CmdBindPipeline(shadow_draw, shadow_pipeline);
|
device_->cmdBindPipeline(shadow_draw, shadow_pipeline);
|
||||||
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
|
device_->cmdBindDescriptorSet(shadow_draw, shadow_pipeline, global_uniform.set, 0); // only need light space matrix
|
||||||
if (static_list) { // only create shadow map with static meshes
|
if (static_list) { // only create shadow map with static meshes
|
||||||
if (!static_list->empty()) {
|
for (const auto& entry : *static_list) {
|
||||||
for (const auto& entry : *static_list) {
|
device_->cmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
||||||
device_->CmdPushConstants(shadow_draw, shadow_pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
device_->cmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2); // need to sample base color texture for alpha clipping
|
||||||
device_->CmdBindDescriptorSet(shadow_draw, shadow_pipeline, entry.material_set, 2);
|
device_->cmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
||||||
device_->CmdBindVertexBuffer(shadow_draw, 0, entry.vertex_buffer);
|
device_->cmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
||||||
device_->CmdBindIndexBuffer(shadow_draw, entry.index_buffer);
|
device_->cmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
|
||||||
device_->CmdDrawIndexed(shadow_draw, entry.index_count, 1, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
device_->FinishShadowmapRender(shadow_draw, shadow_map);
|
device_->finishShadowmapRender(shadow_draw, shadow_map);
|
||||||
}
|
}
|
||||||
rendering_started = true;
|
rendering_started = true;
|
||||||
|
|
||||||
last_bound_pipeline_ = nullptr;
|
last_bound_pipeline_ = nullptr;
|
||||||
|
|
||||||
gfx::DrawBuffer* draw_buffer = device_->BeginRender(window_is_resized);
|
gfx::DrawBuffer* draw_buffer = device_->beginRender(window_is_resized);
|
||||||
|
|
||||||
|
// Draw static objects
|
||||||
if (static_list) {
|
if (static_list) {
|
||||||
if (!static_list->empty()) {
|
if (!static_list->empty()) {
|
||||||
DrawRenderList(draw_buffer, *static_list);
|
DrawRenderList(draw_buffer, *static_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw moving objects
|
||||||
if (dynamic_list) {
|
if (dynamic_list) {
|
||||||
if (!dynamic_list->empty()) {
|
if (!dynamic_list->empty()) {
|
||||||
DrawRenderList(draw_buffer, *dynamic_list);
|
DrawRenderList(draw_buffer, *dynamic_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw skybox
|
||||||
|
{
|
||||||
|
device_->cmdBindPipeline(draw_buffer, skybox_pipeline);
|
||||||
|
device_->cmdBindDescriptorSet(draw_buffer, skybox_pipeline, global_uniform.set, 0);
|
||||||
|
device_->cmdBindDescriptorSet(draw_buffer, skybox_pipeline, frame_uniform.set, 1);
|
||||||
|
device_->cmdBindVertexBuffer(draw_buffer, 0, skybox_buffer);
|
||||||
|
device_->cmdDraw(draw_buffer, 36, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
struct DebugPush {
|
struct DebugPush {
|
||||||
glm::vec4 pos1;
|
glm::vec4 pos1;
|
||||||
glm::vec4 pos2;
|
glm::vec4 pos2;
|
||||||
glm::vec3 color;
|
glm::vec3 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
// draw skybox
|
|
||||||
{
|
|
||||||
device_->CmdBindPipeline(draw_buffer, skybox_pipeline);
|
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, skybox_pipeline, global_uniform.set, 0);
|
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, skybox_pipeline, frame_uniform.set, 1);
|
|
||||||
device_->CmdBindVertexBuffer(draw_buffer, 0, skybox_buffer);
|
|
||||||
device_->CmdDraw(draw_buffer, 36, 1, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw debug shit here
|
// draw debug shit here
|
||||||
device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
device_->cmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline);
|
||||||
DebugPush push{};
|
DebugPush push{};
|
||||||
for (const DebugLine& l : debug_lines) {
|
for (const DebugLine& l : debug_lines) {
|
||||||
push.pos1 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f);
|
push.pos1 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f);
|
||||||
push.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
|
push.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f);
|
||||||
push.color = l.color;
|
push.color = l.color;
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// also make a lil crosshair
|
// also make a lil crosshair
|
||||||
push.color = glm::vec3{1.0f, 1.0f, 1.0f};
|
push.color = glm::vec3{1.0f, 1.0f, 1.0f};
|
||||||
push.pos1 = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
|
push.pos1 = glm::vec4(-0.05f, 0.0f, 0.0f, 1.0f);
|
||||||
push.pos2 = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f);
|
push.pos2 = glm::vec4(0.05f, 0.0f, 0.0f, 1.0f);
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
push.pos1 = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
|
push.pos1 = glm::vec4(0.0f, -0.05f, 0.0f, 1.0f);
|
||||||
push.pos2 = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f);
|
push.pos2 = glm::vec4(0.0f, 0.05f, 0.0f, 1.0f);
|
||||||
device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
device_->cmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push);
|
||||||
device_->CmdDraw(draw_buffer, 2, 1, 0, 0);
|
device_->cmdDraw(draw_buffer, 2, 1, 0, 0);
|
||||||
|
|
||||||
device_->CmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
|
device_->cmdRenderImguiDrawData(draw_buffer, ImGui::GetDrawData());
|
||||||
|
|
||||||
device_->FinishRender(draw_buffer);
|
device_->finishRender(draw_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list)
|
void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list)
|
||||||
@ -351,22 +353,22 @@ void Renderer::DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& re
|
|||||||
if (last_bound_pipeline_ == nullptr) {
|
if (last_bound_pipeline_ == nullptr) {
|
||||||
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
|
const gfx::Pipeline* first_pipeline = render_list.begin()->pipeline;
|
||||||
// these bindings persist between all pipelines
|
// these bindings persist between all pipelines
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
|
device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, global_uniform.set, 0);
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
|
device_->cmdBindDescriptorSet(draw_buffer, first_pipeline, frame_uniform.set, 1);
|
||||||
device_->CmdBindPipeline(draw_buffer, first_pipeline);
|
device_->cmdBindPipeline(draw_buffer, first_pipeline);
|
||||||
last_bound_pipeline_ = first_pipeline;
|
last_bound_pipeline_ = first_pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& entry : render_list) {
|
for (const auto& entry : render_list) {
|
||||||
if (entry.pipeline != last_bound_pipeline_) {
|
if (entry.pipeline != last_bound_pipeline_) {
|
||||||
device_->CmdBindPipeline(draw_buffer, entry.pipeline);
|
device_->cmdBindPipeline(draw_buffer, entry.pipeline);
|
||||||
last_bound_pipeline_ = entry.pipeline;
|
last_bound_pipeline_ = entry.pipeline;
|
||||||
}
|
}
|
||||||
device_->CmdBindDescriptorSet(draw_buffer, entry.pipeline, entry.material_set, 2);
|
device_->cmdBindDescriptorSet(draw_buffer, entry.pipeline, entry.material_set, 2);
|
||||||
device_->CmdPushConstants(draw_buffer, entry.pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
device_->cmdPushConstants(draw_buffer, entry.pipeline, 0, sizeof(entry.model_matrix), &entry.model_matrix);
|
||||||
device_->CmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
|
device_->cmdBindVertexBuffer(draw_buffer, 0, entry.vertex_buffer);
|
||||||
device_->CmdBindIndexBuffer(draw_buffer, entry.index_buffer);
|
device_->cmdBindIndexBuffer(draw_buffer, entry.index_buffer);
|
||||||
device_->CmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
|
device_->cmdDrawIndexed(draw_buffer, entry.index_count, 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace engine {
|
|||||||
|
|
||||||
Font::Font(const std::string& path)
|
Font::Font(const std::string& path)
|
||||||
{
|
{
|
||||||
m_font_buffer = ReadBinaryFile(path);
|
m_font_buffer = readBinaryFile(path);
|
||||||
m_font_info = std::make_unique<stbtt_fontinfo>();
|
m_font_info = std::make_unique<stbtt_fontinfo>();
|
||||||
|
|
||||||
if (stbtt_InitFont(m_font_info.get(), m_font_buffer->data(), 0) == 0) {
|
if (stbtt_InitFont(m_font_info.get(), m_font_buffer->data(), 0) == 0) {
|
||||||
|
@ -7,27 +7,27 @@ namespace engine {
|
|||||||
|
|
||||||
Material::Material(Renderer* renderer, std::shared_ptr<Shader> shader) : m_shader(shader), m_renderer(renderer)
|
Material::Material(Renderer* renderer, std::shared_ptr<Shader> shader) : m_shader(shader), m_renderer(renderer)
|
||||||
{
|
{
|
||||||
m_material_set = renderer->GetDevice()->AllocateDescriptorSet(renderer->GetMaterialSetLayout());
|
m_material_set = renderer->GetDevice()->allocateDescriptorSet(renderer->GetMaterialSetLayout());
|
||||||
LOG_DEBUG("Created material");
|
LOG_DEBUG("Created material");
|
||||||
}
|
}
|
||||||
|
|
||||||
Material::~Material() { m_renderer->GetDevice()->FreeDescriptorSet(m_material_set); LOG_DEBUG("Destroyed material"); }
|
Material::~Material() { m_renderer->GetDevice()->freeDescriptorSet(m_material_set); LOG_DEBUG("Destroyed material"); }
|
||||||
|
|
||||||
void Material::setAlbedoTexture(std::shared_ptr<Texture> texture)
|
void Material::setAlbedoTexture(std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 0, texture->GetImage(), texture->GetSampler());
|
m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 0, texture->GetImage(), texture->GetSampler());
|
||||||
m_texture_albedo = texture;
|
m_texture_albedo = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Material::setNormalTexture(std::shared_ptr<Texture> texture)
|
void Material::setNormalTexture(std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 1, texture->GetImage(), texture->GetSampler());
|
m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 1, texture->GetImage(), texture->GetSampler());
|
||||||
m_texture_normal = texture;
|
m_texture_normal = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Material::setOcclusionRoughnessMetallicTexture(std::shared_ptr<Texture> texture)
|
void Material::setOcclusionRoughnessMetallicTexture(std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
m_renderer->GetDevice()->UpdateDescriptorCombinedImageSampler(m_material_set, 2, texture->GetImage(), texture->GetSampler());
|
m_renderer->GetDevice()->updateDescriptorCombinedImageSampler(m_material_set, 2, texture->GetImage(), texture->GetSampler());
|
||||||
m_texture_occlusion_roughness_metallic = texture;
|
m_texture_occlusion_roughness_metallic = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ Mesh::Mesh(GFXDevice* gfx, const std::vector<Vertex>& vertices, const std::vecto
|
|||||||
|
|
||||||
Mesh::~Mesh()
|
Mesh::~Mesh()
|
||||||
{
|
{
|
||||||
m_gfx->DestroyBuffer(m_ib);
|
m_gfx->destroyBuffer(m_ib);
|
||||||
m_gfx->DestroyBuffer(m_vb);
|
m_gfx->destroyBuffer(m_vb);
|
||||||
LOG_DEBUG("Destroyed mesh");
|
LOG_DEBUG("Destroyed mesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,8 +31,8 @@ uint32_t Mesh::getCount() { return m_count; }
|
|||||||
|
|
||||||
void Mesh::initMesh(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices)
|
void Mesh::initMesh(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices)
|
||||||
{
|
{
|
||||||
m_vb = m_gfx->CreateBuffer(gfx::BufferType::kVertex, vertices.size() * sizeof(Vertex), vertices.data());
|
m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data());
|
||||||
m_ib = m_gfx->CreateBuffer(gfx::BufferType::kIndex, indices.size() * sizeof(uint32_t), indices.data());
|
m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data());
|
||||||
m_count = (uint32_t)indices.size();
|
m_count = (uint32_t)indices.size();
|
||||||
LOG_DEBUG("Created mesh, vertices: {}, indices: {}", vertices.size(), indices.size());
|
LOG_DEBUG("Created mesh, vertices: {}, indices: {}", vertices.size(), indices.size());
|
||||||
}
|
}
|
||||||
|
@ -19,27 +19,27 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
|
|||||||
gfx::VertexFormat vertFormat{};
|
gfx::VertexFormat vertFormat{};
|
||||||
|
|
||||||
vertFormat.attribute_descriptions.emplace_back(
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
index++, gfx::VertexAttribFormat::FLOAT3, stride);
|
||||||
stride += 3 * sizeof(float);
|
stride += 3 * sizeof(float);
|
||||||
|
|
||||||
if (settings.vertexParams.has_normal) {
|
if (settings.vertexParams.has_normal) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
index++, gfx::VertexAttribFormat::kFloat3, stride);
|
index++, gfx::VertexAttribFormat::FLOAT3, stride);
|
||||||
stride += 3 * sizeof(float);
|
stride += 3 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (settings.vertexParams.has_tangent) {
|
if (settings.vertexParams.has_tangent) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
index++, gfx::VertexAttribFormat::FLOAT4, stride);
|
||||||
stride += 4 * sizeof(float);
|
stride += 4 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (settings.vertexParams.has_color) {
|
if (settings.vertexParams.has_color) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
index++, gfx::VertexAttribFormat::kFloat4, stride);
|
index++, gfx::VertexAttribFormat::FLOAT4, stride);
|
||||||
stride += 4 * sizeof(float);
|
stride += 4 * sizeof(float);
|
||||||
}
|
}
|
||||||
if (settings.vertexParams.has_uv0) {
|
if (settings.vertexParams.has_uv0) {
|
||||||
vertFormat.attribute_descriptions.emplace_back(
|
vertFormat.attribute_descriptions.emplace_back(
|
||||||
index++, gfx::VertexAttribFormat::kFloat2, stride);
|
index++, gfx::VertexAttribFormat::FLOAT2, stride);
|
||||||
stride += 2 * sizeof(float);
|
stride += 2 * sizeof(float);
|
||||||
}
|
}
|
||||||
vertFormat.stride = stride;
|
vertFormat.stride = stride;
|
||||||
@ -49,21 +49,21 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin
|
|||||||
info.frag_shader_path = fragPath;
|
info.frag_shader_path = fragPath;
|
||||||
info.vertex_format = vertFormat;
|
info.vertex_format = vertFormat;
|
||||||
info.alpha_blending = settings.alpha_blending;
|
info.alpha_blending = settings.alpha_blending;
|
||||||
info.face_cull_mode = settings.cull_backface ? gfx::CullMode::kCullBack : gfx::CullMode::kCullNone;
|
info.face_cull_mode = settings.cull_backface ? gfx::CullMode::CULL_BACK : gfx::CullMode::CULL_NONE;
|
||||||
info.write_z = settings.write_z;
|
info.write_z = settings.write_z;
|
||||||
info.line_primitives = false;
|
info.line_primitives = false;
|
||||||
info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout());
|
info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout());
|
||||||
info.descriptor_set_layouts.push_back(renderer->GetFrameSetLayout());
|
info.descriptor_set_layouts.push_back(renderer->GetFrameSetLayout());
|
||||||
info.descriptor_set_layouts.push_back(renderer->GetMaterialSetLayout());
|
info.descriptor_set_layouts.push_back(renderer->GetMaterialSetLayout());
|
||||||
|
|
||||||
pipeline_ = gfx_->CreatePipeline(info);
|
pipeline_ = gfx_->createPipeline(info);
|
||||||
|
|
||||||
LOG_DEBUG("Created shader: {}, pipeline: {}", vertPath,
|
LOG_DEBUG("Created shader: {}, pipeline: {}", vertPath,
|
||||||
static_cast<const void*>(pipeline_));
|
static_cast<const void*>(pipeline_));
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader() {
|
Shader::~Shader() {
|
||||||
gfx_->DestroyPipeline(pipeline_);
|
gfx_->destroyPipeline(pipeline_);
|
||||||
LOG_DEBUG("Destroyed shader, pipeline: {}", static_cast<const void*>(pipeline_));
|
LOG_DEBUG("Destroyed shader, pipeline: {}", static_cast<const void*>(pipeline_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,12 @@ namespace engine {
|
|||||||
Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, gfx::SamplerInfo samplerInfo, bool srgb) : gfx_(renderer->GetDevice())
|
Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int height, gfx::SamplerInfo samplerInfo, bool srgb) : gfx_(renderer->GetDevice())
|
||||||
{
|
{
|
||||||
if (renderer->samplers.contains(samplerInfo) == false) {
|
if (renderer->samplers.contains(samplerInfo) == false) {
|
||||||
renderer->samplers.insert(std::make_pair(samplerInfo, gfx_->CreateSampler(samplerInfo)));
|
renderer->samplers.insert(std::make_pair(samplerInfo, gfx_->createSampler(samplerInfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::ImageFormat format = srgb ? gfx::ImageFormat::kSRGB : gfx::ImageFormat::kLinear;
|
gfx::ImageFormat format = srgb ? gfx::ImageFormat::SRGB : gfx::ImageFormat::LINEAR;
|
||||||
|
|
||||||
image_ = gfx_->CreateImage(width, height, format, bitmap);
|
image_ = gfx_->createImage(width, height, format, bitmap);
|
||||||
sampler_ = renderer->samplers.at(samplerInfo);
|
sampler_ = renderer->samplers.at(samplerInfo);
|
||||||
|
|
||||||
LOG_DEBUG("Created texture: width: {}, height: {}", width, height);
|
LOG_DEBUG("Created texture: width: {}, height: {}", width, height);
|
||||||
@ -25,14 +25,14 @@ Texture::Texture(Renderer* renderer, const uint8_t* bitmap, int width, int heigh
|
|||||||
|
|
||||||
Texture::~Texture()
|
Texture::~Texture()
|
||||||
{
|
{
|
||||||
gfx_->DestroyImage(image_);
|
gfx_->destroyImage(image_);
|
||||||
LOG_DEBUG("Destroyed texture");
|
LOG_DEBUG("Destroyed texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, gfx::SamplerInfo samplerInfo, Renderer* renderer, bool srgb)
|
std::unique_ptr<Texture> LoadTextureFromFile(const std::string& path, gfx::SamplerInfo samplerInfo, Renderer* renderer, bool srgb)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
auto bitmap = ReadImageFile(path, width, height);
|
auto bitmap = readImageFile(path, width, height);
|
||||||
return std::make_unique<Texture>(renderer, bitmap->data(), width, height, samplerInfo, srgb);
|
return std::make_unique<Texture>(renderer, bitmap->data(), width, height, samplerInfo, srgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ void Scene::Update(float ts) {
|
|||||||
system->onUpdate(ts);
|
system->onUpdate(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
event_system_->DespatchEvents(); // clears event queue
|
event_system_->despatchEvents(); // clears event queue
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
@ -55,13 +55,13 @@ namespace engine {
|
|||||||
|
|
||||||
VkPresentModeKHR present_mode_requested;
|
VkPresentModeKHR present_mode_requested;
|
||||||
switch (info.requested_present_mode) {
|
switch (info.requested_present_mode) {
|
||||||
case gfx::PresentMode::kDoubleBufferedNoVsync:
|
case gfx::PresentMode::DOUBLE_BUFFERED_NO_VSYNC:
|
||||||
present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
break;
|
break;
|
||||||
case gfx::PresentMode::kDoubleBufferedVsync:
|
case gfx::PresentMode::DOUBLE_BUFFERED_VSYNC:
|
||||||
present_mode_requested = VK_PRESENT_MODE_FIFO_KHR;
|
present_mode_requested = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
break;
|
break;
|
||||||
case gfx::PresentMode::kTripleBuffered:
|
case gfx::PresentMode::TRIPLE_BUFFERED:
|
||||||
present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR;
|
present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||||
}
|
}
|
||||||
sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available
|
sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available
|
||||||
|
@ -62,7 +62,7 @@ void CameraControllerSystem::onUpdate(float ts)
|
|||||||
// keep vel.z as gravity can increase it every frame
|
// keep vel.z as gravity can increase it every frame
|
||||||
|
|
||||||
// gravity stuff here:
|
// gravity stuff here:
|
||||||
c->vel.z += CameraControllerComponent::kGravAccel * dt;
|
c->vel.z += c->grav_accel * dt;
|
||||||
|
|
||||||
// jumping
|
// jumping
|
||||||
if (m_scene->app()->getInputManager()->GetButtonPress("jump") && (c->grounded || c->noclip)) {
|
if (m_scene->app()->getInputManager()->GetButtonPress("jump") && (c->grounded || c->noclip)) {
|
||||||
@ -208,6 +208,15 @@ void CameraControllerSystem::onUpdate(float ts)
|
|||||||
c->noclip ^= true;
|
c->noclip ^= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_scene->app()->getWindow()->GetKeyPress(engine::inputs::Key::K_T)) {
|
||||||
|
if (c->grav_accel != 0.0f) {
|
||||||
|
c->grav_accel = 0.0f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c->grav_accel = -9.81f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_scene->app()->getWindow()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
|
if (m_scene->app()->getWindow()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
|
||||||
engine::Ray ray{};
|
engine::Ray ray{};
|
||||||
ray.origin = t->position;
|
ray.origin = t->position;
|
||||||
|
@ -25,14 +25,14 @@ struct CameraControllerComponent {
|
|||||||
static constexpr float kMaxStairHeight = 0.2f;
|
static constexpr float kMaxStairHeight = 0.2f;
|
||||||
static constexpr size_t kNumHorizontalRays = 20;
|
static constexpr size_t kNumHorizontalRays = 20;
|
||||||
|
|
||||||
static constexpr float kGravAccel = -9.81f;
|
float grav_accel = -9.81f;
|
||||||
// static constexpr float kGravAccel = -1.625f; // moon gravity
|
// grav_accel = -1.625f; // moon gravity
|
||||||
static constexpr float kMaxDistanceFromOrigin = 200.0f;
|
static constexpr float kMaxDistanceFromOrigin = 200.0f;
|
||||||
|
|
||||||
bool noclip = false;
|
bool noclip = false;
|
||||||
|
|
||||||
float yaw = 0.0f;
|
float yaw = 0.0f;
|
||||||
//float pitch = glm::half_pi<float>();
|
// float pitch = glm::half_pi<float>();
|
||||||
float pitch = 0.0f;
|
float pitch = 0.0f;
|
||||||
glm::vec3 vel{0.0f, 0.0f, 0.0f};
|
glm::vec3 vel{0.0f, 0.0f, 0.0f};
|
||||||
bool grounded = false;
|
bool grounded = false;
|
||||||
@ -41,7 +41,7 @@ struct CameraControllerComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class CameraControllerSystem : public engine::System {
|
class CameraControllerSystem : public engine::System {
|
||||||
public:
|
public:
|
||||||
CameraControllerSystem(engine::Scene* scene);
|
CameraControllerSystem(engine::Scene* scene);
|
||||||
|
|
||||||
// engine::System overrides
|
// engine::System overrides
|
||||||
|
@ -47,9 +47,9 @@ void PlayGame(GameSettings settings)
|
|||||||
|
|
||||||
engine::gfx::GraphicsSettings graphics_settings{};
|
engine::gfx::GraphicsSettings graphics_settings{};
|
||||||
graphics_settings.enable_validation = settings.enable_validation;
|
graphics_settings.enable_validation = settings.enable_validation;
|
||||||
graphics_settings.present_mode = engine::gfx::PresentMode::kTripleBuffered;
|
graphics_settings.present_mode = engine::gfx::PresentMode::TRIPLE_BUFFERED;
|
||||||
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff;
|
graphics_settings.msaa_level = engine::gfx::MSAALevel::MSAA_OFF;
|
||||||
graphics_settings.enable_anisotropy = true;
|
graphics_settings.enable_anisotropy = false;
|
||||||
|
|
||||||
engine::AppConfiguration configuration{};
|
engine::AppConfiguration configuration{};
|
||||||
configuration.enable_frame_limiter = settings.enable_frame_limiter;
|
configuration.enable_frame_limiter = settings.enable_frame_limiter;
|
||||||
@ -66,7 +66,7 @@ void PlayGame(GameSettings settings)
|
|||||||
/* as of right now, the entity with tag 'camera' is used to build the view
|
/* as of right now, the entity with tag 'camera' is used to build the view
|
||||||
* matrix */
|
* matrix */
|
||||||
|
|
||||||
//engine::Entity temple = engine::util::LoadGLTF(*start_scene, "C:/games/temple.glb", true);
|
//engine::Entity temple = engine::loadGLTF(*start_scene, "C:/games/temple.glb", true);
|
||||||
|
|
||||||
start_scene->RegisterComponent<CameraControllerComponent>();
|
start_scene->RegisterComponent<CameraControllerComponent>();
|
||||||
start_scene->RegisterSystemAtIndex<CameraControllerSystem>(0);
|
start_scene->RegisterSystemAtIndex<CameraControllerSystem>(0);
|
||||||
@ -98,36 +98,38 @@ void PlayGame(GameSettings settings)
|
|||||||
main_scene->AddComponent<CameraControllerComponent>(camera);
|
main_scene->AddComponent<CameraControllerComponent>(camera);
|
||||||
|
|
||||||
/* floor */
|
/* floor */
|
||||||
engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/floor2.glb"), true);
|
engine::Entity floor = engine::loadGLTF(*main_scene, app.getResourcePath("models/floor2.glb"), true);
|
||||||
|
main_scene->GetScale(floor).x *= 100.0f;
|
||||||
|
main_scene->GetScale(floor).z *= 100.0f;
|
||||||
//main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
|
//main_scene->GetComponent<engine::MeshRenderableComponent>(main_scene->GetEntity("Cube", floor))->visible = false;
|
||||||
|
|
||||||
engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/monke.glb"), true);
|
engine::Entity monke = engine::loadGLTF(*main_scene, app.getResourcePath("models/monke.glb"), true);
|
||||||
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
|
main_scene->GetComponent<engine::TransformComponent>(monke)->position.y += 10.0f;
|
||||||
|
|
||||||
// engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"));
|
// engine::Entity bottle = engine::loadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"));
|
||||||
// main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 10.0f;
|
// main_scene->GetComponent<engine::TransformComponent>(bottle)->scale *= 10.0f;
|
||||||
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.x += 25.0f;
|
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.x += 25.0f;
|
||||||
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f;
|
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f;
|
||||||
|
|
||||||
engine::Entity helmet = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/DamagedHelmet.glb"), true);
|
engine::Entity helmet = engine::loadGLTF(*main_scene, app.getResourcePath("models/DamagedHelmet.glb"), true);
|
||||||
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 5.0f};
|
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 5.0f};
|
||||||
main_scene->GetScale(helmet) *= 3.0f;
|
main_scene->GetScale(helmet) *= 3.0f;
|
||||||
main_scene->GetRotation(helmet) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f });
|
main_scene->GetRotation(helmet) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f });
|
||||||
main_scene->GetRotation(helmet) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });
|
main_scene->GetRotation(helmet) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });
|
||||||
|
|
||||||
engine::Entity toycar = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/ToyCar.glb"), true);
|
engine::Entity toycar = engine::loadGLTF(*main_scene, app.getResourcePath("models/ToyCar.glb"), true);
|
||||||
main_scene->GetScale(toycar) *= 150.0f;
|
main_scene->GetScale(toycar) *= 150.0f;
|
||||||
main_scene->GetPosition(toycar).z -= 0.07f;
|
main_scene->GetPosition(toycar).z -= 0.07f;
|
||||||
|
|
||||||
engine::Entity stairs = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/stairs.glb"), true);
|
engine::Entity stairs = engine::loadGLTF(*main_scene, app.getResourcePath("models/stairs.glb"), true);
|
||||||
main_scene->GetPosition(stairs) += glm::vec3{-8.0f, -5.0f, 0.1f};
|
main_scene->GetPosition(stairs) += glm::vec3{-8.0f, -5.0f, 0.1f};
|
||||||
main_scene->GetRotation(stairs) = glm::angleAxis(glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f});
|
main_scene->GetRotation(stairs) = glm::angleAxis(glm::half_pi<float>(), glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
main_scene->GetRotation(stairs) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{1.0f, 0.0f, 0.0f});
|
main_scene->GetRotation(stairs) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{1.0f, 0.0f, 0.0f});
|
||||||
|
|
||||||
engine::Entity axes = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/MY_AXES.glb"), true);
|
engine::Entity axes = engine::loadGLTF(*main_scene, app.getResourcePath("models/MY_AXES.glb"), true);
|
||||||
main_scene->GetPosition(axes) += glm::vec3{-40.0f, -40.0f, 1.0f};
|
main_scene->GetPosition(axes) += glm::vec3{-40.0f, -40.0f, 1.0f};
|
||||||
|
|
||||||
engine::Entity bottle = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"), true);
|
engine::Entity bottle = engine::loadGLTF(*main_scene, app.getResourcePath("models/bottle.glb"), true);
|
||||||
main_scene->GetPosition(bottle).y -= 10.0f;
|
main_scene->GetPosition(bottle).y -= 10.0f;
|
||||||
main_scene->GetPosition(bottle).z += 2.5f;
|
main_scene->GetPosition(bottle).z += 2.5f;
|
||||||
main_scene->GetScale(bottle) *= 25.0f;
|
main_scene->GetScale(bottle) *= 25.0f;
|
||||||
@ -149,15 +151,15 @@ void PlayGame(GameSettings settings)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
engine::Entity teapot = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/teapot.glb"), true);
|
engine::Entity teapot = engine::loadGLTF(*main_scene, app.getResourcePath("models/teapot.glb"), true);
|
||||||
main_scene->GetPosition(teapot).y += 5.0f;
|
main_scene->GetPosition(teapot).y += 5.0f;
|
||||||
main_scene->GetPosition(teapot).x -= 5.0f;
|
main_scene->GetPosition(teapot).x -= 5.0f;
|
||||||
main_scene->GetScale(teapot) *= 5.0f;
|
main_scene->GetScale(teapot) *= 5.0f;
|
||||||
|
|
||||||
engine::Entity tree = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/tree.glb"), true);
|
engine::Entity tree = engine::loadGLTF(*main_scene, app.getResourcePath("models/tree.glb"), true);
|
||||||
main_scene->GetPosition(tree) = glm::vec3{-5.0f, -5.0f, 0.0f};
|
main_scene->GetPosition(tree) = glm::vec3{-5.0f, -5.0f, 0.0f};
|
||||||
|
|
||||||
engine::Entity box = engine::util::LoadGLTF(*main_scene, app.getResourcePath("models/box.glb"), true);
|
engine::Entity box = engine::loadGLTF(*main_scene, app.getResourcePath("models/box.glb"), true);
|
||||||
main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f };
|
main_scene->GetPosition(box) = glm::vec3{ -5.0f, -17.0f, 0.1f };
|
||||||
main_scene->GetScale(box) *= 10.0f;
|
main_scene->GetScale(box) *= 10.0f;
|
||||||
main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f });
|
main_scene->GetRotation(box) = glm::angleAxis(glm::pi<float>() * 0.0f, glm::vec3{ 0.0f, 0.0f, 1.0f });
|
||||||
|
@ -73,7 +73,7 @@ std::unique_ptr<engine::Mesh> GenSphereMesh(engine::GFXDevice* gfx, float r, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> indices = engine::util::GenTangents(vertices);
|
std::vector<uint32_t> indices = engine::genTangents(vertices);
|
||||||
|
|
||||||
return std::make_unique<engine::Mesh>(gfx, vertices, indices);
|
return std::make_unique<engine::Mesh>(gfx, vertices, indices);
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ std::unique_ptr<engine::Mesh> GenCuboidMesh(engine::GFXDevice* gfx, float x, flo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> indices = engine::util::GenTangents(vertices);
|
std::vector<uint32_t> indices = engine::genTangents(vertices);
|
||||||
|
|
||||||
return std::make_unique<engine::Mesh>(gfx, vertices, indices);
|
return std::make_unique<engine::Mesh>(gfx, vertices, indices);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user