Archived
1
Fork 0

Okay, reformat the rest of the engine code!

This commit is contained in:
Joshua Goins 2022-08-15 11:07:28 -04:00
parent 100e1d7434
commit b00a39c474
75 changed files with 3059 additions and 2975 deletions

View file

@ -11,7 +11,7 @@ add_subdirectory(shadercompiler)
add_subdirectory(platform) add_subdirectory(platform)
add_subdirectory(base) add_subdirectory(base)
if(NOT ENABLE_IOS AND NOT ENABLE_TVOS) if (NOT ENABLE_IOS AND NOT ENABLE_TVOS)
add_subdirectory(audio) add_subdirectory(audio)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif ()

View file

@ -19,14 +19,14 @@ set_target_properties(GFXInterface PROPERTIES CMAKE_FOLDER "GFX")
add_subdirectory(dummy) add_subdirectory(dummy)
if(ENABLE_DX12) if (ENABLE_DX12)
add_subdirectory(dx12) add_subdirectory(dx12)
endif() endif ()
if(ENABLE_METAL) if (ENABLE_METAL)
add_subdirectory(metal) add_subdirectory(metal)
endif() endif ()
if(ENABLE_VULKAN) if (ENABLE_VULKAN)
add_subdirectory(vulkan) add_subdirectory(vulkan)
endif() endif ()

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <dxgi1_6.h>
#include <wrl.h> #include <wrl.h>
#include "gfx.hpp" #include "gfx.hpp"
@ -11,9 +11,18 @@ using namespace Microsoft::WRL;
class gfx_dx12 : public GFX { class gfx_dx12 : public GFX {
public: public:
bool is_supported() override { return true; } bool is_supported() override {
ShaderLanguage accepted_shader_language() override { return ShaderLanguage::HLSL; } return true;
GFXContext required_context() override { return GFXContext::DirectX; } }
ShaderLanguage accepted_shader_language() override {
return ShaderLanguage::HLSL;
}
GFXContext required_context() override {
return GFXContext::DirectX;
}
bool initialize(const GFXCreateInfo& info) override; bool initialize(const GFXCreateInfo& info) override;
const char* get_name() override; const char* get_name() override;

View file

@ -1,11 +1,11 @@
#include "gfx_dx12.hpp" #include "gfx_dx12.hpp"
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <dxgi1_6.h>
#include <wrl.h>
#include <codecvt> #include <codecvt>
#include <wrl.h>
// from https://stackoverflow.com/a/18374698 // from https://stackoverflow.com/a/18374698
std::string ws2s(const std::wstring& wstr) { std::string ws2s(const std::wstring& wstr) {

View file

@ -8,15 +8,23 @@
class GFXMetal : public GFX { class GFXMetal : public GFX {
public: public:
bool is_supported() override; bool is_supported() override;
GFXContext required_context() override { return GFXContext::Metal; }
ShaderLanguage accepted_shader_language() override { return ShaderLanguage::MSL; } GFXContext required_context() override {
return GFXContext::Metal;
}
ShaderLanguage accepted_shader_language() override {
return ShaderLanguage::MSL;
}
const char* get_name() override; const char* get_name() override;
bool supports_feature(GFXFeature feature) override; bool supports_feature(GFXFeature feature) override;
bool initialize(const GFXCreateInfo& createInfo) override; bool initialize(const GFXCreateInfo& createInfo) override;
void initialize_view(void* native_handle, platform::window_ptr identifier, uint32_t width, uint32_t height) override; void
initialize_view(void* native_handle, platform::window_ptr identifier, uint32_t width, uint32_t height) override;
void remove_view(platform::window_ptr identifier) override; void remove_view(platform::window_ptr identifier) override;
// buffer operations // buffer operations
@ -59,8 +67,8 @@ private:
std::vector<NativeMTLView*> nativeViews; std::vector<NativeMTLView*> nativeViews;
NativeMTLView* getNativeView(platform::window_ptr identifier) { NativeMTLView* getNativeView(platform::window_ptr identifier) {
for(auto& view : nativeViews) { for (auto& view : nativeViews) {
if(view->identifier == identifier) if (view->identifier == identifier)
return view; return view;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include <variant> #include <variant>
#include <vector>
#include "shadercompiler.hpp"
#include "platform.hpp"
#include "gfx_context.hpp" #include "gfx_context.hpp"
#include "platform.hpp"
#include "shadercompiler.hpp"
class GFXBuffer; class GFXBuffer;
class GFXPipeline; class GFXPipeline;
@ -293,69 +293,112 @@ enum class GFXFeature {
class GFX { class GFX {
public: public:
// check for runtime support // check for runtime support
virtual bool is_supported() { return false; } virtual bool is_supported() {
virtual GFXContext required_context() { return GFXContext::None; } return false;
virtual ShaderLanguage accepted_shader_language() { return ShaderLanguage::GLSL; } }
virtual const char* get_name() { return nullptr; }
virtual bool supports_feature([[maybe_unused]] const GFXFeature feature) { return false; } virtual GFXContext required_context() {
return GFXContext::None;
}
virtual ShaderLanguage accepted_shader_language() {
return ShaderLanguage::GLSL;
}
virtual const char* get_name() {
return nullptr;
}
virtual bool supports_feature([[maybe_unused]] const GFXFeature feature) {
return false;
}
// try to initialize // try to initialize
virtual bool initialize([[maybe_unused]] const GFXCreateInfo& createInfo) { return false; } virtual bool initialize([[maybe_unused]] const GFXCreateInfo& createInfo) {
return false;
}
virtual void initialize_view([[maybe_unused]] void* native_handle, virtual void initialize_view(
[[maybe_unused]] void* native_handle,
[[maybe_unused]] const platform::window_ptr identifier, [[maybe_unused]] const platform::window_ptr identifier,
[[maybe_unused]] const uint32_t width, [[maybe_unused]] const uint32_t width,
[[maybe_unused]] const uint32_t height) {} [[maybe_unused]] const uint32_t height) {}
virtual void recreate_view([[maybe_unused]] const platform::window_ptr identifier, virtual void recreate_view(
[[maybe_unused]] const platform::window_ptr identifier,
[[maybe_unused]] const uint32_t width, [[maybe_unused]] const uint32_t width,
[[maybe_unused]] const uint32_t height) {} [[maybe_unused]] const uint32_t height) {}
virtual void remove_view([[maybe_unused]] const platform::window_ptr identifier) {} virtual void remove_view([[maybe_unused]] const platform::window_ptr identifier) {}
// buffer operations // buffer operations
virtual GFXBuffer* create_buffer([[maybe_unused]] void* data, virtual GFXBuffer* create_buffer(
[[maybe_unused]] void* data,
[[maybe_unused]] const GFXSize size, [[maybe_unused]] const GFXSize size,
[[maybe_unused]] const bool is_dynamic, [[maybe_unused]] const bool is_dynamic,
[[maybe_unused]] const GFXBufferUsage usage) { return nullptr; } [[maybe_unused]] const GFXBufferUsage usage) {
virtual void copy_buffer([[maybe_unused]] GFXBuffer* buffer, return nullptr;
}
virtual void copy_buffer(
[[maybe_unused]] GFXBuffer* buffer,
[[maybe_unused]] void* data, [[maybe_unused]] void* data,
[[maybe_unused]] const GFXSize offset, [[maybe_unused]] const GFXSize offset,
[[maybe_unused]] const GFXSize size) { } [[maybe_unused]] const GFXSize size) {}
virtual void* get_buffer_contents([[maybe_unused]] GFXBuffer* buffer) { return nullptr; } virtual void* get_buffer_contents([[maybe_unused]] GFXBuffer* buffer) {
virtual void release_buffer_contents([[maybe_unused]] GFXBuffer* buffer, return nullptr;
[[maybe_unused]] void* handle) {} }
virtual void release_buffer_contents([[maybe_unused]] GFXBuffer* buffer, [[maybe_unused]] void* handle) {}
// texture operations // texture operations
virtual GFXTexture* create_texture([[maybe_unused]] const GFXTextureCreateInfo& info) { return nullptr; } virtual GFXTexture* create_texture([[maybe_unused]] const GFXTextureCreateInfo& info) {
virtual void copy_texture([[maybe_unused]] GFXTexture* texture, return nullptr;
}
virtual void copy_texture(
[[maybe_unused]] GFXTexture* texture,
[[maybe_unused]] void* data, [[maybe_unused]] void* data,
[[maybe_unused]] const GFXSize size) {} [[maybe_unused]] const GFXSize size) {}
virtual void copy_texture([[maybe_unused]] GFXTexture* from,
[[maybe_unused]] GFXTexture* to) {} virtual void copy_texture([[maybe_unused]] GFXTexture* from, [[maybe_unused]] GFXTexture* to) {}
virtual void copy_texture([[maybe_unused]] GFXTexture* from,
[[maybe_unused]] GFXBuffer* to) {} virtual void copy_texture([[maybe_unused]] GFXTexture* from, [[maybe_unused]] GFXBuffer* to) {}
// sampler opeations // sampler opeations
virtual GFXSampler* create_sampler([[maybe_unused]] const GFXSamplerCreateInfo& info) { return nullptr; } virtual GFXSampler* create_sampler([[maybe_unused]] const GFXSamplerCreateInfo& info) {
return nullptr;
}
// framebuffer operations // framebuffer operations
virtual GFXFramebuffer* create_framebuffer([[maybe_unused]] const GFXFramebufferCreateInfo& info) { return nullptr; } virtual GFXFramebuffer* create_framebuffer([[maybe_unused]] const GFXFramebufferCreateInfo& info) {
return nullptr;
}
// render pass operations // render pass operations
virtual GFXRenderPass* create_render_pass([[maybe_unused]] const GFXRenderPassCreateInfo& info) { return nullptr; } virtual GFXRenderPass* create_render_pass([[maybe_unused]] const GFXRenderPassCreateInfo& info) {
return nullptr;
}
// pipeline operations // pipeline operations
virtual GFXPipeline* create_graphics_pipeline([[maybe_unused]] const GFXGraphicsPipelineCreateInfo& info) { return nullptr; } virtual GFXPipeline* create_graphics_pipeline([[maybe_unused]] const GFXGraphicsPipelineCreateInfo& info) {
virtual GFXPipeline* create_compute_pipeline([[maybe_unused]] const GFXComputePipelineCreateInfo& info) { return nullptr; } return nullptr;
}
virtual GFXPipeline* create_compute_pipeline([[maybe_unused]] const GFXComputePipelineCreateInfo& info) {
return nullptr;
}
// misc operations // misc operations
virtual GFXSize get_alignment(const GFXSize size) { return size; } virtual GFXSize get_alignment(const GFXSize size) {
return size;
}
virtual GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) { return nullptr; } virtual GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) {
return nullptr;
}
virtual void submit([[maybe_unused]] GFXCommandBuffer* command_buffer, virtual void
[[maybe_unused]] const platform::window_ptr window) {} submit([[maybe_unused]] GFXCommandBuffer* command_buffer, [[maybe_unused]] const platform::window_ptr window) {}
}; };

View file

@ -4,5 +4,4 @@
class GFXBuffer : public GFXObject { class GFXBuffer : public GFXObject {
public: public:
}; };

View file

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <vector>
#include <cstring>
#include <array> #include <array>
#include <cstring>
#include <string_view> #include <string_view>
#include <vector>
#include "common.hpp" #include "common.hpp"
@ -126,7 +126,7 @@ struct GFXDrawCommand {
} draw_indexed; } draw_indexed;
struct CopyTextureData { struct CopyTextureData {
GFXTexture* src = nullptr, *dst = nullptr; GFXTexture *src = nullptr, *dst = nullptr;
int width = 0, height = 0; int width = 0, height = 0;
int to_slice = 0; int to_slice = 0;
int to_layer = 0; int to_layer = 0;
@ -230,7 +230,6 @@ public:
command.data.bind_shader_buffer.index = index; command.data.bind_shader_buffer.index = index;
command.data.bind_shader_buffer.size = size; command.data.bind_shader_buffer.size = size;
commands.push_back(command); commands.push_back(command);
} }
@ -252,7 +251,8 @@ public:
commands.push_back(command); commands.push_back(command);
} }
void draw(const uint32_t offset, const uint32_t count, const uint32_t instance_base, const uint32_t instance_count) { void
draw(const uint32_t offset, const uint32_t count, const uint32_t instance_base, const uint32_t instance_count) {
GFXDrawCommand command; GFXDrawCommand command;
command.type = GFXCommandType::Draw; command.type = GFXCommandType::Draw;
command.data.draw.vertex_offset = offset; command.data.draw.vertex_offset = offset;
@ -263,7 +263,11 @@ public:
commands.push_back(command); commands.push_back(command);
} }
void draw_indexed(const uint32_t indexCount, const uint32_t firstIndex, const int32_t vertexOffset, const uint32_t base_instance) { void draw_indexed(
const uint32_t indexCount,
const uint32_t firstIndex,
const int32_t vertexOffset,
const uint32_t base_instance) {
GFXDrawCommand command; GFXDrawCommand command;
command.type = GFXCommandType::DrawIndexed; command.type = GFXCommandType::DrawIndexed;
command.data.draw_indexed.vertex_offset = vertexOffset; command.data.draw_indexed.vertex_offset = vertexOffset;
@ -281,7 +285,8 @@ public:
commands.push_back(command); commands.push_back(command);
} }
void copy_texture(GFXTexture* src, int width, int height, GFXTexture* dst, int to_slice, int to_layer, int to_level) { void
copy_texture(GFXTexture* src, int width, int height, GFXTexture* dst, int to_slice, int to_layer, int to_level) {
GFXDrawCommand command; GFXDrawCommand command;
command.type = GFXCommandType::CopyTexture; command.type = GFXCommandType::CopyTexture;
command.data.copy_texture.src = src; command.data.copy_texture.src = src;

View file

@ -4,5 +4,4 @@
class GFXFramebuffer : public GFXObject { class GFXFramebuffer : public GFXObject {
public: public:
}; };

View file

@ -4,5 +4,4 @@
class GFXRenderPass : public GFXObject { class GFXRenderPass : public GFXObject {
public: public:
}; };

View file

@ -4,5 +4,4 @@
class GFXSampler : public GFXObject { class GFXSampler : public GFXObject {
public: public:
}; };

View file

@ -2,8 +2,8 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <map>
#include <array> #include <array>
#include <map>
#include "gfx.hpp" #include "gfx.hpp"
#include "gfx_vulkan_constants.hpp" #include "gfx_vulkan_constants.hpp"
@ -37,16 +37,26 @@ class GFXVulkanPipeline;
class GFXVulkan : public GFX { class GFXVulkan : public GFX {
public: public:
bool is_supported() override { return true; } bool is_supported() override {
ShaderLanguage accepted_shader_language() override { return ShaderLanguage::SPIRV; } return true;
GFXContext required_context() override { return GFXContext::Vulkan; } }
ShaderLanguage accepted_shader_language() override {
return ShaderLanguage::SPIRV;
}
GFXContext required_context() override {
return GFXContext::Vulkan;
}
const char* get_name() override; const char* get_name() override;
bool supports_feature(GFXFeature feature) override; bool supports_feature(GFXFeature feature) override;
bool initialize(const GFXCreateInfo& info) override; bool initialize(const GFXCreateInfo& info) override;
void initialize_view(void* native_handle, platform::window_ptr identifier, uint32_t width, uint32_t height) override; void
initialize_view(void* native_handle, platform::window_ptr identifier, uint32_t width, uint32_t height) override;
void recreate_view(platform::window_ptr identifier, uint32_t width, uint32_t height) override; void recreate_view(platform::window_ptr identifier, uint32_t width, uint32_t height) override;
// buffer operations // buffer operations
@ -95,8 +105,15 @@ private:
uint64_t getDescriptorHash(GFXVulkanPipeline* pipeline); uint64_t getDescriptorHash(GFXVulkanPipeline* pipeline);
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
void transitionImageLayout(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageSubresourceRange range, VkImageLayout oldLayout, VkImageLayout newLayout); void transitionImageLayout(
void inlineTransitionImageLayout(VkCommandBuffer command_buffer, VkImage image,
VkFormat format,
VkImageAspectFlags aspect,
VkImageSubresourceRange range,
VkImageLayout oldLayout,
VkImageLayout newLayout);
void inlineTransitionImageLayout(
VkCommandBuffer command_buffer,
VkImage image, VkImage image,
VkFormat format, VkFormat format,
VkImageAspectFlags aspect, VkImageAspectFlags aspect,

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
#include "gfx_sampler.hpp" #include "gfx_sampler.hpp"
class GFXVulkanSampler: public GFXSampler { class GFXVulkanSampler : public GFXSampler {
public: public:
VkSampler sampler = VK_NULL_HANDLE; VkSampler sampler = VK_NULL_HANDLE;
}; };

View file

@ -11,8 +11,7 @@ namespace prism {
log_output += str + "\n"; log_output += str + "\n";
} }
template <typename S, typename... Args> template<typename S, typename... Args> inline void log(const S& format, Args&&... args) {
inline void log(const S& format, Args&&... args) {
vlog(format, fmt::make_args_checked<Args...>(format, args...)); vlog(format, fmt::make_args_checked<Args...>(format, args...));
} }
} } // namespace prism

View file

@ -22,4 +22,4 @@ namespace prism {
float3(aabb.min.x, aabb.max.y, aabb.max.z), float3(aabb.min.x, aabb.max.y, aabb.max.z),
float3(aabb.max.x, aabb.max.y, aabb.max.z)}; float3(aabb.max.x, aabb.max.y, aabb.max.z)};
} }
} } // namespace prism

View file

@ -1,26 +1,23 @@
#pragma once #pragma once
#include "matrix.hpp" #include "matrix.hpp"
#include "ray.hpp"
#include "transform.hpp" #include "transform.hpp"
#include "vector.hpp" #include "vector.hpp"
#include "ray.hpp"
constexpr double PI = 3.141592653589793; constexpr double PI = 3.141592653589793;
template<typename T> template<typename T> constexpr inline T radians(const T degrees) {
constexpr inline T radians(const T degrees) {
return degrees / static_cast<T>(180) * static_cast<T>(PI); return degrees / static_cast<T>(180) * static_cast<T>(PI);
} }
template<typename T> template<typename T> constexpr inline T degrees(const T radians) {
constexpr inline T degrees(const T radians) {
return radians / static_cast<T>(PI) * static_cast<T>(180); return radians / static_cast<T>(PI) * static_cast<T>(180);
} }
template<typename T> template<typename T> constexpr inline bool nearly_equal(const T a, const T b) {
constexpr inline bool nearly_equal(const T a, const T b) { return std::nextafter(a, std::numeric_limits<T>::lowest()) <= b &&
return std::nextafter(a, std::numeric_limits<T>::lowest()) <= b std::nextafter(a, std::numeric_limits<T>::max()) >= b;
&& std::nextafter(a, std::numeric_limits<T>::max()) >= b;
} }
Matrix4x4 matrix_from_quat(Quaternion quat); Matrix4x4 matrix_from_quat(Quaternion quat);

View file

@ -5,15 +5,18 @@
// m = rows // m = rows
// n = columns // n = columns
// row major storage mode? // row major storage mode?
template<class T, std::size_t M, std::size_t N> template<class T, std::size_t M, std::size_t N> class Matrix {
class Matrix {
public: public:
constexpr Matrix(const T diagonal = T(1)) { constexpr Matrix(const T diagonal = T(1)) {
for(std::size_t i = 0; i < (M * N); i++) for (std::size_t i = 0; i < (M * N); i++)
unordered_data[i] = ((i / M) == (i % N) ? diagonal : T(0)); unordered_data[i] = ((i / M) == (i % N) ? diagonal : T(0));
} }
constexpr Matrix(const prism::float4 m1_, const prism::float4 m2_, const prism::float4 m3_, const prism::float4 m4_) { constexpr Matrix(
const prism::float4 m1_,
const prism::float4 m2_,
const prism::float4 m3_,
const prism::float4 m4_) {
columns[0] = m1_; columns[0] = m1_;
columns[1] = m2_; columns[1] = m2_;
columns[2] = m3_; columns[2] = m3_;
@ -24,8 +27,13 @@ public:
using VectorType = prism::Vector<N, T>; using VectorType = prism::Vector<N, T>;
constexpr VectorType& operator[](const size_t index) { return columns[index]; } constexpr VectorType& operator[](const size_t index) {
constexpr VectorType operator[](const size_t index) const { return columns[index]; } return columns[index];
}
constexpr VectorType operator[](const size_t index) const {
return columns[index];
}
union { union {
VectorType columns[M]; VectorType columns[M];
@ -39,9 +47,9 @@ using Matrix3x3 = Matrix<float, 3, 3>;
constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const Matrix4x4 rhs) { constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const Matrix4x4 rhs) {
Matrix4x4 tmp(0.0f); Matrix4x4 tmp(0.0f);
for(int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
for(int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for(int k = 0; k < 4; k++) for (int k = 0; k < 4; k++)
tmp.data[j][i] += lhs.data[k][i] * rhs.data[j][k]; tmp.data[j][i] += lhs.data[k][i] * rhs.data[j][k];
} }
} }
@ -51,8 +59,8 @@ constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const Matrix4x4 rhs) {
constexpr inline prism::float4 operator*(const Matrix4x4 lhs, const prism::float4 rhs) { constexpr inline prism::float4 operator*(const Matrix4x4 lhs, const prism::float4 rhs) {
prism::float4 tmp; prism::float4 tmp;
for(int r = 0; r < 4; r++) { for (int r = 0; r < 4; r++) {
for(int c = 0; c < 4; c++) for (int c = 0; c < 4; c++)
tmp[r] += lhs.data[c][r] * rhs.data[c]; tmp[r] += lhs.data[c][r] * rhs.data[c];
} }
@ -61,9 +69,9 @@ constexpr inline prism::float4 operator*(const Matrix4x4 lhs, const prism::float
constexpr inline Matrix4x4 operator/(const Matrix4x4 lhs, const float rhs) { constexpr inline Matrix4x4 operator/(const Matrix4x4 lhs, const float rhs) {
Matrix4x4 tmp(0.0f); Matrix4x4 tmp(0.0f);
for(int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
for(int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
for(int k = 0; k < 4; k++) for (int k = 0; k < 4; k++)
tmp.data[k][i] = lhs.data[k][i] / rhs; tmp.data[k][i] = lhs.data[k][i] / rhs;
} }
} }
@ -84,4 +92,6 @@ constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const float rhs) {
} }
template<typename T, std::size_t M, std::size_t N> template<typename T, std::size_t M, std::size_t N>
constexpr void Matrix<T, M, N>::operator*=(const Matrix<T, M, N> rhs) { *this = *this * rhs; } constexpr void Matrix<T, M, N>::operator*=(const Matrix<T, M, N> rhs) {
*this = *this * rhs;
}

View file

@ -9,9 +9,7 @@ struct Plane {
}; };
inline Plane normalize(const Plane& plane) { inline Plane normalize(const Plane& plane) {
const float magnitude = std::sqrt(plane.a * plane.a + const float magnitude = std::sqrt(plane.a * plane.a + plane.b * plane.b + plane.c * plane.c);
plane.b * plane.b +
plane.c * plane.c);
Plane normalized_plane = plane; Plane normalized_plane = plane;
normalized_plane.a = plane.a / magnitude; normalized_plane.a = plane.a / magnitude;
@ -23,8 +21,5 @@ inline Plane normalize(const Plane& plane) {
} }
inline float distance_to_point(const Plane& plane, const prism::float3& point) { inline float distance_to_point(const Plane& plane, const prism::float3& point) {
return plane.a * point.x + return plane.a * point.x + plane.b * point.y + plane.c * point.z + plane.d;
plane.b * point.y +
plane.c * point.z +
plane.d;
} }

View file

@ -51,7 +51,7 @@ constexpr inline Quaternion lerp(const Quaternion& a, const Quaternion& b, const
float cosom = dot(a, b); float cosom = dot(a, b);
Quaternion end = b; Quaternion end = b;
if(cosom < 0.0f) { if (cosom < 0.0f) {
cosom = -cosom; cosom = -cosom;
end.x = -end.x; end.x = -end.x;
end.y = -end.y; end.y = -end.y;
@ -60,20 +60,17 @@ constexpr inline Quaternion lerp(const Quaternion& a, const Quaternion& b, const
} }
float sclp = 0.0f, sclq = 0.0f; float sclp = 0.0f, sclq = 0.0f;
if((1.0f - cosom) > 0.0001f) { if ((1.0f - cosom) > 0.0001f) {
const float omega = std::acos(cosom); const float omega = std::acos(cosom);
const float sinom = std::sin(omega); const float sinom = std::sin(omega);
sclp = std::sin((1.0f - time) * omega) / sinom; sclp = std::sin((1.0f - time) * omega) / sinom;
sclq = std::sin(time* omega) / sinom; sclq = std::sin(time * omega) / sinom;
} else { } else {
sclp = 1.0f - time; sclp = 1.0f - time;
sclq = time; sclq = time;
} }
return {sclp * a.x + sclq * end.x, return {sclp * a.x + sclq * end.x, sclp * a.y + sclq * end.y, sclp * a.z + sclq * end.z, sclp * a.w + sclq * end.w};
sclp * a.y + sclq * end.y,
sclp * a.z + sclq * end.z,
sclp * a.w + sclq * end.w};
} }
constexpr inline Quaternion operator*(const Quaternion lhs, const Quaternion rhs) { constexpr inline Quaternion operator*(const Quaternion lhs, const Quaternion rhs) {

View file

@ -9,4 +9,4 @@ namespace prism {
}; };
float closest_distance_between_lines(ray& l1, ray& l2); float closest_distance_between_lines(ray& l1, ray& l2);
} } // namespace prism

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "matrix.hpp" #include "matrix.hpp"
#include "vector.hpp"
#include "quaternion.hpp" #include "quaternion.hpp"
#include "vector.hpp"
namespace prism { namespace prism {
Matrix4x4 perspective(float field_of_view, float aspect, float z_near, float z_far); Matrix4x4 perspective(float field_of_view, float aspect, float z_near, float z_far);
@ -16,4 +16,4 @@ namespace prism {
Matrix4x4 translate(Matrix4x4 matrix, float3 translation); Matrix4x4 translate(Matrix4x4 matrix, float3 translation);
Matrix4x4 rotate(Matrix4x4 matrix, float angle, float3 axis); Matrix4x4 rotate(Matrix4x4 matrix, float angle, float3 axis);
Matrix4x4 scale(Matrix4x4 matrix, float3 scale); Matrix4x4 scale(Matrix4x4 matrix, float3 scale);
} } // namespace prism

View file

@ -1,62 +1,50 @@
#pragma once #pragma once
#include <array>
#include <cmath> #include <cmath>
#include <type_traits> #include <type_traits>
#include <typeinfo> #include <typeinfo>
#include <array>
namespace prism { namespace prism {
#define DEFINE_OPERATORS(Size) \ #define DEFINE_OPERATORS(Size) \
constexpr Vector(const T scalar = T(0)) { \ constexpr Vector(const T scalar = T(0)) { \
for(std::size_t i = 0; i < (Size); i++) \ for (std::size_t i = 0; i < (Size); i++) \
data[i] = scalar; \ data[i] = scalar; \
} \ } \
constexpr T& operator[](const size_t index) { \ constexpr T& operator[](const size_t index) { return data[index]; } \
return data[index]; \ constexpr T operator[](const size_t index) const { return data[index]; } \
} \
constexpr T operator[](const size_t index) const { \
return data[index]; \
} \
constexpr Vector& operator+=(const Vector rhs) { \ constexpr Vector& operator+=(const Vector rhs) { \
for(std::size_t i = 0; i < (Size); i++)\ for (std::size_t i = 0; i < (Size); i++) \
data[i] += rhs[i]; \ data[i] += rhs[i]; \
return *this; \ return *this; \
} \ } \
constexpr Vector& operator-=(const Vector rhs) { \ constexpr Vector& operator-=(const Vector rhs) { \
for(std::size_t i = 0; i < (Size); i++)\ for (std::size_t i = 0; i < (Size); i++) \
data[i] -= rhs[i]; \ data[i] -= rhs[i]; \
return *this; \ return *this; \
} \ } \
constexpr Vector& operator*=(const Vector rhs) { \ constexpr Vector& operator*=(const Vector rhs) { \
for(std::size_t i = 0; i < (Size); i++) \ for (std::size_t i = 0; i < (Size); i++) \
data[i] *= rhs[i]; \ data[i] *= rhs[i]; \
return *this; \ return *this; \
} \ } \
constexpr Vector& operator/=(const T scalar) { \ constexpr Vector& operator/=(const T scalar) { \
for(std::size_t i = 0; i < (Size); i++) \ for (std::size_t i = 0; i < (Size); i++) \
data[i] /= scalar; \ data[i] /= scalar; \
return *this; \ return *this; \
} \ } \
constexpr T* ptr() const { \ constexpr T* ptr() const { return data.data(); } \
return data.data(); \ constexpr T* ptr() { return data.data(); } \
} \ constexpr Vector operator-() const { \
constexpr T* ptr() { \
return data.data(); \
} \
constexpr Vector operator- () const { \
Vector vec; \ Vector vec; \
for(std::size_t i = 0; i < (Size); i++) \ for (std::size_t i = 0; i < (Size); i++) \
vec[i] = -data[i]; \ vec[i] = -data[i]; \
return vec; \ return vec; \
} }
template<std::size_t N, class T> template<std::size_t N, class T> struct Vector { std::array<T, N> data; };
struct Vector {
std::array<T, N> data;
};
template<class T> template<class T> struct Vector<2, T> {
struct Vector<2, T> {
constexpr Vector(const T x_, const T y_) { constexpr Vector(const T x_, const T y_) {
x = x_; x = x_;
y = y_; y = y_;
@ -73,8 +61,7 @@ namespace prism {
}; };
}; };
template<class T> template<class T> struct Vector<3, T> {
struct Vector<3, T> {
constexpr Vector(const T x_, const T y_, const T z_) { constexpr Vector(const T x_, const T y_, const T z_) {
x = x_; x = x_;
y = y_; y = y_;
@ -92,8 +79,7 @@ namespace prism {
}; };
}; };
template<class T> template<class T> struct alignas(16) Vector<4, T> {
struct alignas(16) Vector<4, T> {
constexpr Vector(const T x_, const T y_, const T z_, const T w_) { constexpr Vector(const T x_, const T y_, const T z_, const T w_) {
x = x_; x = x_;
y = y_; y = y_;
@ -101,7 +87,7 @@ namespace prism {
w = w_; w = w_;
} }
constexpr Vector(const Vector<3, T> &v, const float w = 0.0f) : x(v.x), y(v.y), z(v.z), w(w) {} constexpr Vector(const Vector<3, T>& v, const float w = 0.0f) : x(v.x), y(v.y), z(v.z), w(w) {}
DEFINE_OPERATORS(4) DEFINE_OPERATORS(4)
@ -123,8 +109,7 @@ namespace prism {
using float3 = Vector<3, float>; using float3 = Vector<3, float>;
using float4 = Vector<4, float>; using float4 = Vector<4, float>;
template<std::size_t N, class T> template<std::size_t N, class T> constexpr inline T dot(const Vector<N, T> lhs, const Vector<N, T> rhs) {
constexpr inline T dot(const Vector<N, T> lhs, const Vector<N, T> rhs) {
T product = T(0.0); T product = T(0.0);
for (std::size_t i = 0; i < N; i++) for (std::size_t i = 0; i < N; i++)
@ -133,8 +118,7 @@ namespace prism {
return product; return product;
} }
template<std::size_t N, class T> template<std::size_t N, class T> constexpr inline T length(const Vector<N, T> vec) {
constexpr inline T length(const Vector<N, T> vec) {
return sqrtf(dot(vec, vec)); return sqrtf(dot(vec, vec));
} }
@ -147,8 +131,7 @@ namespace prism {
return vec; return vec;
} }
template<std::size_t N, class T> template<std::size_t N, class T> constexpr inline Vector<N, T> normalize(const Vector<N, T> vec) {
constexpr inline Vector<N, T> normalize(const Vector<N, T> vec) {
Vector<N, T> result; Vector<N, T> result;
const float len = length(vec); const float len = length(vec);
@ -170,15 +153,14 @@ namespace prism {
return std::sqrt((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)); return std::sqrt((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ));
} }
template<std::size_t N, class T> template<std::size_t N, class T> constexpr inline T norm(const Vector<N, T> vec) {
constexpr inline T norm(const Vector<N, T> vec) {
T val = T(0); T val = T(0);
for (std::size_t i = 0; i < N; i++) for (std::size_t i = 0; i < N; i++)
val += abs(vec[i]); val += abs(vec[i]);
return sqrtf(dot(vec, vec)); return sqrtf(dot(vec, vec));
} }
} } // namespace prism
template<std::size_t N, class T> template<std::size_t N, class T>
constexpr inline bool operator==(const prism::Vector<N, T> lhs, const prism::Vector<N, T> rhs) { constexpr inline bool operator==(const prism::Vector<N, T> lhs, const prism::Vector<N, T> rhs) {

View file

@ -35,17 +35,17 @@ Quaternion quat_from_matrix(const Matrix3x3 m) {
int biggestIndex = 0; int biggestIndex = 0;
float fourBiggestSquaredMinus1 = fourWSquaredMinus1; float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) { if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourXSquaredMinus1; fourBiggestSquaredMinus1 = fourXSquaredMinus1;
biggestIndex = 1; biggestIndex = 1;
} }
if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) { if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourYSquaredMinus1; fourBiggestSquaredMinus1 = fourYSquaredMinus1;
biggestIndex = 2; biggestIndex = 2;
} }
if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) { if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) {
fourBiggestSquaredMinus1 = fourZSquaredMinus1; fourBiggestSquaredMinus1 = fourZSquaredMinus1;
biggestIndex = 3; biggestIndex = 3;
} }
@ -53,7 +53,7 @@ Quaternion quat_from_matrix(const Matrix3x3 m) {
const float biggestVal = sqrt(fourBiggestSquaredMinus1 + 1.0f) * 0.5f; const float biggestVal = sqrt(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
const float mult = 0.25f / biggestVal; const float mult = 0.25f / biggestVal;
switch(biggestIndex) { switch (biggestIndex) {
case 0: case 0:
return {(m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult, biggestVal}; return {(m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult, biggestVal};
case 1: case 1:

View file

@ -46,7 +46,7 @@ Matrix4x4 prism::orthographic(float left, float right, float bottom, float top,
result[2][2] = 1.0f / (zFar - zNear); result[2][2] = 1.0f / (zFar - zNear);
result[3][0] = -(right + left) / (right - left); result[3][0] = -(right + left) / (right - left);
result[3][1] = -(top + bottom) / (top - bottom); result[3][1] = -(top + bottom) / (top - bottom);
result[3][2] = - zNear / (zFar - zNear); result[3][2] = -zNear / (zFar - zNear);
return result; return result;
} }

View file

@ -1,10 +1,10 @@
if(ENABLE_VULKAN) if (ENABLE_VULKAN)
set(EXTRA_LIBRARIES Vulkan::Vulkan ${EXTRA_LIBRARIES}) set(EXTRA_LIBRARIES Vulkan::Vulkan ${EXTRA_LIBRARIES})
endif() endif ()
if(ENABLE_METAL) if (ENABLE_METAL)
set(EXTRA_LIBRARIES metal-cpp ${EXTRA_LIBRARIES}) set(EXTRA_LIBRARIES metal-cpp ${EXTRA_LIBRARIES})
endif() endif ()
add_library(Platform INTERFACE) add_library(Platform INTERFACE)
target_include_directories(Platform INTERFACE include) target_include_directories(Platform INTERFACE include)

View file

@ -1,11 +1,11 @@
#pragma once #pragma once
#include <fstream>
#include <string>
#include <vector>
#include <optional>
#include <array> #include <array>
#include <filesystem> #include <filesystem>
#include <fstream>
#include <optional>
#include <string>
#include <vector>
#include "log.hpp" #include "log.hpp"
#include "path.hpp" #include "path.hpp"
@ -21,13 +21,11 @@ namespace prism {
public: public:
explicit file(FILE* handle) : handle(handle) {} explicit file(FILE* handle) : handle(handle) {}
file(file&& f) noexcept : file(file&& f) noexcept
mem(std::move(f.mem)), : mem(std::move(f.mem)), handle(std::exchange(f.handle, nullptr)), data(std::move(f.data)) {}
handle(std::exchange(f.handle, nullptr)),
data(std::move(f.data)) {}
~file() { ~file() {
if(handle != nullptr) if (handle != nullptr)
fclose(handle); fclose(handle);
} }
@ -35,8 +33,7 @@ namespace prism {
@param t The pointer to the type. @param t The pointer to the type.
@param s If not 0, the size to load is derived from sizeof(T). @param s If not 0, the size to load is derived from sizeof(T).
*/ */
template<typename T> template<typename T> void read(T* t, const size_t s = 0) {
void read(T* t, const size_t s = 0) {
fread(t, s == 0 ? sizeof(T) : s, 1, handle); fread(t, s == 0 ? sizeof(T) : s, 1, handle);
} }
@ -49,7 +46,7 @@ namespace prism {
unsigned int length = 0; unsigned int length = 0;
read(&length); read(&length);
if(length > 0) { if (length > 0) {
str.resize(length); str.resize(length);
read(str.data(), sizeof(char) * length); read(str.data(), sizeof(char) * length);
@ -67,8 +64,7 @@ namespace prism {
} }
/// If the file is loaded in memory, cast the underlying data. /// If the file is loaded in memory, cast the underlying data.
template<typename T> template<typename T> T* cast_data() {
T* cast_data() {
return reinterpret_cast<T*>(data.data()); return reinterpret_cast<T*>(data.data());
} }
@ -133,6 +129,6 @@ namespace prism {
path get_file_path(const path& path); path get_file_path(const path& path);
inline path base_domain = "/base", game_domain = "/game"; inline path base_domain = "/base", game_domain = "/game";
} } // namespace prism
inline std::array<std::string, 3> domain_data; inline std::array<std::string, 3> domain_data;

View file

@ -77,8 +77,8 @@ enum class PlatformTheme {
// note: a platform may be built with support for a specific context (e.g. ENABLE_VULKAN, ENABLE_DIRECTX, etc) // note: a platform may be built with support for a specific context (e.g. ENABLE_VULKAN, ENABLE_DIRECTX, etc)
// this only determines it at build-time, not at runtime. // this only determines it at build-time, not at runtime.
#ifdef ENABLE_VULKAN #ifdef ENABLE_VULKAN
#include <vulkan/vulkan.h> #include <vector>
#include <vector> #include <vulkan/vulkan.h>
struct vulkan_information { struct vulkan_information {
std::vector<const char*> surface_extensions; std::vector<const char*> surface_extensions;
@ -100,8 +100,8 @@ struct directx_surface_creation_info {
#endif #endif
#ifdef ENABLE_METAL #ifdef ENABLE_METAL
#include <Metal/Metal.hpp> #include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalDrawable.hpp> #include <QuartzCore/CAMetalDrawable.hpp>
struct metal_surface_creation_info { struct metal_surface_creation_info {
MTL::Device* device; MTL::Device* device;
@ -140,9 +140,9 @@ namespace platform {
void initialize_context(GFXContext context); void initialize_context(GFXContext context);
/* /*
* This is used in specific cases where the gfx backend may need to know important information before window creation. * This is used in specific cases where the gfx backend may need to know important information before window
* A good example is the surface extension required by a specific window backend, but this is between initialize_context * creation. A good example is the surface extension required by a specific window backend, but this is between
* and create_surface calls. * initialize_context and create_surface calls.
* *
* the returned structs are in a naming scheme of X_information. * the returned structs are in a naming scheme of X_information.
*/ */
@ -152,8 +152,10 @@ namespace platform {
@param title The title of the window. @param title The title of the window.
@param rect The requested size and position of the window. @param rect The requested size and position of the window.
@param flags The requested window flags. @param flags The requested window flags.
@note Depending on the platform, some of these parameters might be unused. The best practice is to always assume that none of them may be used. @note Depending on the platform, some of these parameters might be unused. The best practice is to always assume
@note On platforms that do not support the Windowing feature, calling open_window more than once is not supported. In this case, the same identifier is returned. that none of them may be used.
@note On platforms that do not support the Windowing feature, calling open_window more than once is not supported.
In this case, the same identifier is returned.
@return A valid window identifier. @return A valid window identifier.
*/ */
window_ptr open_window(std::string_view title, prism::Rectangle rect, WindowFlags flags); window_ptr open_window(std::string_view title, prism::Rectangle rect, WindowFlags flags);
@ -171,8 +173,8 @@ namespace platform {
void* create_surface(window_ptr window, void* surface_creation_info); void* create_surface(window_ptr window, void* surface_creation_info);
/* /*
* This needs to be implemented under certain gfx contexts (such as metal) which calls [layer nextDrawable] underneath * This needs to be implemented under certain gfx contexts (such as metal) which calls [layer nextDrawable]
* can be no-op for contexts such as vulkan which can happen within it's own API. * underneath can be no-op for contexts such as vulkan which can happen within it's own API.
* *
* the return type is named as X_next_image. may be null. * the return type is named as X_next_image. may be null.
*/ */
@ -201,7 +203,8 @@ namespace platform {
/// Get the window size, note that in hidpi scenarios this is the non-scaled resolution. /// Get the window size, note that in hidpi scenarios this is the non-scaled resolution.
prism::Extent get_window_size(window_ptr window); prism::Extent get_window_size(window_ptr window);
/// Get the window's drawable size. Always use this instead of manually multiplying the window size by the content scale. /// Get the window's drawable size. Always use this instead of manually multiplying the window size by the content
/// scale.
prism::Extent get_window_drawable_size(window_ptr window); prism::Extent get_window_drawable_size(window_ptr window);
/// Query whether or not the window is focused. /// Query whether or not the window is focused.
@ -249,8 +252,9 @@ namespace platform {
/// On platforms that support moue capture, this will lock the mouse cursor to the window and hide it. /// On platforms that support moue capture, this will lock the mouse cursor to the window and hide it.
void capture_mouse(bool capture); void capture_mouse(bool capture);
// TODO: right now the OS intercepting and saying "We dont want text input anymore" ala software keyboards is NOT supported yet // TODO: right now the OS intercepting and saying "We dont want text input anymore" ala software keyboards is NOT
// supported yet
void begin_text_input(); void begin_text_input();
void end_text_input(); void end_text_input();
} } // namespace platform

View file

@ -2,13 +2,13 @@
#include <array> #include <array>
#include "aabb.hpp"
#include "asset_types.hpp"
#include "components.hpp"
#include "frustum.hpp" #include "frustum.hpp"
#include "matrix.hpp" #include "matrix.hpp"
#include "vector.hpp"
#include "components.hpp"
#include "aabb.hpp"
#include "plane.hpp" #include "plane.hpp"
#include "asset_types.hpp" #include "vector.hpp"
class Scene; class Scene;

View file

@ -2,8 +2,8 @@
#include <string_view> #include <string_view>
#include "pass.hpp"
#include "file.hpp" #include "file.hpp"
#include "pass.hpp"
class GFXBuffer; class GFXBuffer;
class GFXCommandBuffer; class GFXCommandBuffer;

View file

@ -15,11 +15,13 @@ constexpr int bone_buffer_index = 10;
class MaterialCompiler { class MaterialCompiler {
public: public:
GFXPipeline* create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false, bool cubemap = false); GFXPipeline*
create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false, bool cubemap = false);
GFXPipeline* create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false); GFXPipeline* create_skinned_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only = false);
// generates static and skinned versions of the pipeline provided // generates static and skinned versions of the pipeline provided
std::tuple<GFXPipeline*, GFXPipeline*> create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only = false); std::tuple<GFXPipeline*, GFXPipeline*>
create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only = false);
ShaderSource compile_material_fragment(Material& material, bool use_ibl = true); ShaderSource compile_material_fragment(Material& material, bool use_ibl = true);
}; };

View file

@ -21,11 +21,14 @@ public:
virtual void create_render_target_resources([[maybe_unused]] RenderTarget& target) {} virtual void create_render_target_resources([[maybe_unused]] RenderTarget& target) {}
virtual void render_scene([[maybe_unused]] Scene& scene, virtual void render_scene([[maybe_unused]] Scene& scene, [[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
[[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
virtual void render_post([[maybe_unused]] GFXCommandBuffer* commandBuffer, virtual void render_post(
[[maybe_unused]] GFXCommandBuffer* commandBuffer,
[[maybe_unused]] RenderTarget& target, [[maybe_unused]] RenderTarget& target,
[[maybe_unused]] platform::window_ptr index) {} [[maybe_unused]] platform::window_ptr index) {}
virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) { return nullptr; } virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) {
return nullptr;
}
}; };

View file

@ -1,19 +1,19 @@
#pragma once #pragma once
#include <string_view>
#include <vector>
#include <cmath> #include <cmath>
#include <functional> #include <functional>
#include <string_view>
#include <vector>
#include "pass.hpp" #include "common.hpp"
#include "matrix.hpp" #include "matrix.hpp"
#include "object.hpp" #include "object.hpp"
#include "common.hpp" #include "pass.hpp"
#include "render_options.hpp"
#include "path.hpp" #include "path.hpp"
#include "shadercompiler.hpp"
#include "rendertarget.hpp"
#include "platform.hpp" #include "platform.hpp"
#include "render_options.hpp"
#include "rendertarget.hpp"
#include "shadercompiler.hpp"
class GFX; class GFX;
class GFXBuffer; class GFXBuffer;
@ -58,14 +58,19 @@ namespace prism {
void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, platform::window_ptr index); void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, platform::window_ptr index);
void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, void render_camera(
prism::Extent extent, RenderTarget& target, controller_continuity &continuity); GFXCommandBuffer* command_buffer,
Scene& scene,
Object camera_object,
Camera& camera,
prism::Extent extent,
RenderTarget& target,
controller_continuity& continuity);
void create_mesh_pipeline(Material& material) const; void create_mesh_pipeline(Material& material) const;
// passes // passes
template<class T, typename... Args> template<class T, typename... Args> T* addPass(Args&&... args) {
T* addPass(Args &&... args) {
auto t = std::make_unique<T>(args...); auto t = std::make_unique<T>(args...);
t->initialize(); t->initialize();
@ -93,7 +98,7 @@ namespace prism {
ShaderSource register_shader(std::string_view shader_file); ShaderSource register_shader(std::string_view shader_file);
void associate_shader_reload(std::string_view shader_file, const std::function<void()> &reload_function); void associate_shader_reload(std::string_view shader_file, const std::function<void()>& reload_function);
void reload_shader(std::string_view shader_file, std::string_view shader_source); void reload_shader(std::string_view shader_file, std::string_view shader_source);
@ -142,7 +147,7 @@ namespace prism {
GFXRenderPass* brdf_render_pass = nullptr; GFXRenderPass* brdf_render_pass = nullptr;
// histogram compute // histogram compute
GFXPipeline* histogram_pipeline = nullptr, *histogram_average_pipeline = nullptr; GFXPipeline *histogram_pipeline = nullptr, *histogram_average_pipeline = nullptr;
GFXBuffer* histogram_buffer = nullptr; GFXBuffer* histogram_buffer = nullptr;
GFXTexture* average_luminance_texture = nullptr; GFXTexture* average_luminance_texture = nullptr;
@ -151,4 +156,4 @@ namespace prism {
std::vector<std::unique_ptr<Pass>> passes; std::vector<std::unique_ptr<Pass>> passes;
}; };
} } // namespace prism

View file

@ -14,7 +14,8 @@ public:
prism::Extent extent; prism::Extent extent;
[[nodiscard]] prism::Extent get_render_extent() const { [[nodiscard]] prism::Extent get_render_extent() const {
return {static_cast<uint32_t>(std::max(int(extent.width * render_options.render_scale), 1)), return {
static_cast<uint32_t>(std::max(int(extent.width * render_options.render_scale), 1)),
static_cast<uint32_t>(std::max(int(extent.height * render_options.render_scale), 1))}; static_cast<uint32_t>(std::max(int(extent.height * render_options.render_scale), 1))};
} }

View file

@ -22,14 +22,15 @@ public:
void render(GFXCommandBuffer* command_buffer, Scene* scene); void render(GFXCommandBuffer* command_buffer, Scene* scene);
GFXPipeline* irradiancePipeline, *prefilterPipeline = nullptr, *skyPipeline = nullptr; GFXPipeline *irradiancePipeline, *prefilterPipeline = nullptr, *skyPipeline = nullptr;
GFXRenderPass* renderPass = nullptr, *irradianceRenderPass = nullptr; GFXRenderPass *renderPass = nullptr, *irradianceRenderPass = nullptr;
GFXTexture* environmentCube = nullptr; GFXTexture* environmentCube = nullptr;
GFXTexture* offscreenTexture = nullptr, *irradianceOffscreenTexture = nullptr, *prefilteredOffscreenTexture = nullptr; GFXTexture *offscreenTexture = nullptr, *irradianceOffscreenTexture = nullptr,
*prefilteredOffscreenTexture = nullptr;
GFXTexture* offscreenDepth = nullptr; GFXTexture* offscreenDepth = nullptr;
GFXFramebuffer* offscreenFramebuffer = nullptr, *irradianceFramebuffer = nullptr, *prefilteredFramebuffer = nullptr; GFXFramebuffer *offscreenFramebuffer = nullptr, *irradianceFramebuffer = nullptr, *prefilteredFramebuffer = nullptr;
GFXBuffer* sceneBuffer = nullptr; GFXBuffer* sceneBuffer = nullptr;

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "components.hpp"
#include "math.hpp" #include "math.hpp"
#include "object.hpp" #include "object.hpp"
#include "components.hpp"
class GFX; class GFX;
class GFXCommandBuffer; class GFXCommandBuffer;
@ -24,7 +24,15 @@ public:
void render(GFXCommandBuffer* command_buffer, Scene& scene); void render(GFXCommandBuffer* command_buffer, Scene& scene);
private: private:
void render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, Matrix4x4 light_matrix, Matrix4x4 model, prism::float3 light_position, Light::Type type, const CameraFrustum& frustum, int base_instance); void render_meshes(
GFXCommandBuffer* command_buffer,
Scene& scene,
Matrix4x4 light_matrix,
Matrix4x4 model,
prism::float3 light_position,
Light::Type type,
const CameraFrustum& frustum,
int base_instance);
void render_sun(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light); void render_sun(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light);
void render_spot(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light); void render_spot(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light);

View file

@ -1,10 +1,10 @@
#include "dofpass.hpp" #include "dofpass.hpp"
#include "renderer.hpp" #include "asset.hpp"
#include "engine.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "gfx_commandbuffer.hpp" #include "gfx_commandbuffer.hpp"
#include "engine.hpp" #include "renderer.hpp"
#include "asset.hpp"
AssetPtr<Texture> aperture_texture; AssetPtr<Texture> aperture_texture;
@ -17,7 +17,7 @@ DoFPass::DoFPass(GFX* gfx) {
renderpass = gfx->create_render_pass(renderPassInfo); renderpass = gfx->create_render_pass(renderPassInfo);
//const auto extent = renderer->get_render_extent(); // const auto extent = renderer->get_render_extent();
const auto extent = prism::Extent(); const auto extent = prism::Extent();
GFXShaderConstant width_constant = {}; GFXShaderConstant width_constant = {};
@ -36,12 +36,9 @@ DoFPass::DoFPass(GFX* gfx) {
{0, GFXBindingType::StorageImage}, {0, GFXBindingType::StorageImage},
{1, GFXBindingType::Texture}, {1, GFXBindingType::Texture},
{3, GFXBindingType::Texture}, {3, GFXBindingType::Texture},
{2, GFXBindingType::PushConstant} {2, GFXBindingType::PushConstant}};
};
create_info.shader_input.push_constants = { create_info.shader_input.push_constants = {{sizeof(prism::float4), 0}};
{sizeof(prism::float4), 0}
};
create_info.render_pass = renderpass; create_info.render_pass = renderpass;
@ -68,17 +65,17 @@ DoFPass::DoFPass(GFX* gfx) {
GFXFramebufferCreateInfo framebufferInfo = {}; GFXFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.render_pass = renderpass; framebufferInfo.render_pass = renderpass;
framebufferInfo.attachments = { normal_field }; framebufferInfo.attachments = {normal_field};
normal_framebuffer = gfx->create_framebuffer(framebufferInfo); normal_framebuffer = gfx->create_framebuffer(framebufferInfo);
framebufferInfo.attachments = { far_field }; framebufferInfo.attachments = {far_field};
far_framebuffer = gfx->create_framebuffer(framebufferInfo); far_framebuffer = gfx->create_framebuffer(framebufferInfo);
} }
void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) { void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) {
//const auto render_extent = renderer->get_render_extent(); // const auto render_extent = renderer->get_render_extent();
const auto extent = prism::Extent(); const auto extent = prism::Extent();
const auto render_extent = prism::Extent(); const auto render_extent = prism::Extent();
@ -97,11 +94,11 @@ void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) {
command_buffer->set_graphics_pipeline(pipeline); command_buffer->set_graphics_pipeline(pipeline);
//command_buffer->bind_texture(renderer->offscreenColorTexture, 0); // command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
//command_buffer->bind_texture(renderer->offscreenDepthTexture, 1); // command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
command_buffer->bind_texture(aperture_texture->handle, 3); command_buffer->bind_texture(aperture_texture->handle, 3);
//const auto extent = renderer->get_render_extent(); // const auto extent = renderer->get_render_extent();
prism::float4 params(render_options.depth_of_field_strength, 0.0, 0.0, 0.0); prism::float4 params(render_options.depth_of_field_strength, 0.0, 0.0, 0.0);
@ -116,8 +113,8 @@ void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) {
command_buffer->set_graphics_pipeline(pipeline); command_buffer->set_graphics_pipeline(pipeline);
//command_buffer->bind_texture(renderer->offscreenColorTexture, 0); // command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
//command_buffer->bind_texture(renderer->offscreenDepthTexture, 1); // command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
command_buffer->bind_texture(aperture_texture->handle, 2); command_buffer->bind_texture(aperture_texture->handle, 2);
params.y = 1; params.y = 1;

View file

@ -53,7 +53,7 @@ CameraFrustum camera_extract_frustum(Scene& scene, prism::Object cam) {
CameraFrustum normalize_frustum(const CameraFrustum& frustum) { CameraFrustum normalize_frustum(const CameraFrustum& frustum) {
CameraFrustum normalized_frustum; CameraFrustum normalized_frustum;
for(int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
normalized_frustum.planes[i] = normalize(frustum.planes[i]); normalized_frustum.planes[i] = normalize(frustum.planes[i]);
return normalized_frustum; return normalized_frustum;
@ -66,20 +66,20 @@ bool test_point_plane(const Plane& plane, const prism::float3& point) {
bool test_point_frustum(const CameraFrustum& frustum, const prism::float3& point) { bool test_point_frustum(const CameraFrustum& frustum, const prism::float3& point) {
bool inside_frustum = false; bool inside_frustum = false;
for(int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
inside_frustum |= !test_point_plane(frustum.planes[i], point); inside_frustum |= !test_point_plane(frustum.planes[i], point);
return !inside_frustum; return !inside_frustum;
} }
bool test_aabb_frustum(const CameraFrustum& frustum, const prism::aabb& aabb) { bool test_aabb_frustum(const CameraFrustum& frustum, const prism::aabb& aabb) {
for(int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
int out = 0; int out = 0;
for(const auto point : get_points(aabb)) for (const auto point : get_points(aabb))
out += (distance_to_point(frustum.planes[i], point) < 0.0) ? 1 : 0; out += (distance_to_point(frustum.planes[i], point) < 0.0) ? 1 : 0;
if(out == 8) if (out == 8)
return false; return false;
} }

View file

@ -2,11 +2,11 @@
#include <imgui.h> #include <imgui.h>
#include "assertions.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "gfx_commandbuffer.hpp" #include "gfx_commandbuffer.hpp"
#include "log.hpp" #include "log.hpp"
#include "assertions.hpp"
#include "renderer.hpp" #include "renderer.hpp"
void ImGuiPass::initialize() { void ImGuiPass::initialize() {
@ -20,7 +20,7 @@ void ImGuiPass::initialize() {
} }
void ImGuiPass::create_render_target_resources(RenderTarget& target) { void ImGuiPass::create_render_target_resources(RenderTarget& target) {
if(pipeline == nullptr) { if (pipeline == nullptr) {
GFXGraphicsPipelineCreateInfo createInfo; GFXGraphicsPipelineCreateInfo createInfo;
createInfo.label = "ImGui"; createInfo.label = "ImGui";
createInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/imgui.vert")); createInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/imgui.vert"));
@ -53,18 +53,13 @@ void ImGuiPass::create_render_target_resources(RenderTarget& target) {
createInfo.blending.enable_blending = true; createInfo.blending.enable_blending = true;
createInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha; createInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
createInfo.blending.src_alpha= GFXBlendFactor::SrcAlpha; createInfo.blending.src_alpha = GFXBlendFactor::SrcAlpha;
createInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha; createInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
createInfo.blending.dst_alpha = GFXBlendFactor::OneMinusSrcAlpha; createInfo.blending.dst_alpha = GFXBlendFactor::OneMinusSrcAlpha;
createInfo.shader_input.push_constants = { createInfo.shader_input.push_constants = {{sizeof(Matrix4x4), 0}};
{sizeof(Matrix4x4), 0}
};
createInfo.shader_input.bindings = { createInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
{1, GFXBindingType::PushConstant},
{2, GFXBindingType::Texture}
};
pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo); pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
} }
@ -72,15 +67,15 @@ void ImGuiPass::create_render_target_resources(RenderTarget& target) {
void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, const platform::window_ptr index) { void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, const platform::window_ptr index) {
ImDrawData* draw_data = nullptr; ImDrawData* draw_data = nullptr;
if(!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) { if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) {
draw_data = ImGui::GetDrawData(); draw_data = ImGui::GetDrawData();
} else { } else {
auto viewport = ImGui::FindViewportByPlatformHandle(index); auto viewport = ImGui::FindViewportByPlatformHandle(index);
if(viewport != nullptr) if (viewport != nullptr)
draw_data = viewport->DrawData; draw_data = viewport->DrawData;
} }
if(draw_data == nullptr) if (draw_data == nullptr)
return; return;
const int framebuffer_width = static_cast<int>(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); const int framebuffer_width = static_cast<int>(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
@ -91,10 +86,11 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ
command_buffer->set_graphics_pipeline(pipeline); command_buffer->set_graphics_pipeline(pipeline);
if(draw_data->TotalVtxCount > 0) if (draw_data->TotalVtxCount > 0)
update_buffers(target, *draw_data); update_buffers(target, *draw_data);
const Matrix4x4 projection = prism::orthographic(draw_data->DisplayPos.x, const Matrix4x4 projection = prism::orthographic(
draw_data->DisplayPos.x,
draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x,
draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y + draw_data->DisplaySize.y,
draw_data->DisplayPos.y, draw_data->DisplayPos.y,
@ -108,25 +104,37 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ
int vertex_offset = 0; int vertex_offset = 0;
int index_offset = 0; int index_offset = 0;
for(int n = 0; n < draw_data->CmdListsCount; n++) { for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
for(int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if(pcmd->TextureId != nullptr) if (pcmd->TextureId != nullptr)
command_buffer->bind_texture((GFXTexture*)pcmd->TextureId, 2); command_buffer->bind_texture((GFXTexture*)pcmd->TextureId, 2);
if(pcmd->UserCallback != nullptr) { if (pcmd->UserCallback != nullptr) {
pcmd->UserCallback(cmd_list, pcmd); pcmd->UserCallback(cmd_list, pcmd);
} else { } else {
ImVec2 clip_min((pcmd->ClipRect.x - clip_offset.x) * clip_scale.x, (pcmd->ClipRect.y - clip_offset.y) * clip_scale.y); ImVec2 clip_min(
ImVec2 clip_max((pcmd->ClipRect.z - clip_offset.x) * clip_scale.x, (pcmd->ClipRect.w - clip_offset.y) * clip_scale.y); (pcmd->ClipRect.x - clip_offset.x) * clip_scale.x,
(pcmd->ClipRect.y - clip_offset.y) * clip_scale.y);
ImVec2 clip_max(
(pcmd->ClipRect.z - clip_offset.x) * clip_scale.x,
(pcmd->ClipRect.w - clip_offset.y) * clip_scale.y);
// Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds // Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; } if (clip_min.x < 0.0f) {
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; } clip_min.x = 0.0f;
if (clip_max.x > framebuffer_width) { clip_max.x = (float)framebuffer_width; } }
if (clip_max.y > framebuffer_height) { clip_max.y = (float)framebuffer_height; } if (clip_min.y < 0.0f) {
clip_min.y = 0.0f;
}
if (clip_max.x > framebuffer_width) {
clip_max.x = (float)framebuffer_width;
}
if (clip_max.y > framebuffer_height) {
clip_max.y = (float)framebuffer_height;
}
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
continue; continue;
@ -140,12 +148,12 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ
command_buffer->set_scissor(scissor); command_buffer->set_scissor(scissor);
command_buffer->set_vertex_buffer(target.vertex_buffer[target.current_frame], 0, 0); command_buffer->set_vertex_buffer(target.vertex_buffer[target.current_frame], 0, 0);
command_buffer->set_index_buffer(target.index_buffer[target.current_frame], sizeof(ImDrawIdx) == 2 ? IndexType::UINT16 : IndexType::UINT32); command_buffer->set_index_buffer(
target.index_buffer[target.current_frame],
command_buffer->draw_indexed(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? IndexType::UINT16 : IndexType::UINT32);
(index_offset + pcmd->IdxOffset),
(vertex_offset + pcmd->VtxOffset), 0);
command_buffer->draw_indexed(
pcmd->ElemCount, (index_offset + pcmd->IdxOffset), (vertex_offset + pcmd->VtxOffset), 0);
} }
} }
@ -159,14 +167,15 @@ void ImGuiPass::load_font(const std::string_view filename) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if(io.Fonts->Fonts.empty()) { if (io.Fonts->Fonts.empty()) {
auto file = prism::open_file(prism::base_domain / filename); auto file = prism::open_file(prism::base_domain / filename);
if(file != std::nullopt) { if (file != std::nullopt) {
font_file = std::make_unique<prism::file>(std::move(file.value())); font_file = std::make_unique<prism::file>(std::move(file.value()));
font_file->read_all(); font_file->read_all();
io.Fonts->AddFontFromMemoryTTF(font_file->cast_data<unsigned char>(), font_file->size(), 15.0f * platform::get_monitor_dpi()); io.Fonts->AddFontFromMemoryTTF(
font_file->cast_data<unsigned char>(), font_file->size(), 15.0f * platform::get_monitor_dpi());
ImGui::GetIO().FontGlobalScale = 1.0f / platform::get_monitor_dpi(); ImGui::GetIO().FontGlobalScale = 1.0f / platform::get_monitor_dpi();
} else { } else {
prism::log("Failed to load font file for imgui!"); prism::log("Failed to load font file for imgui!");
@ -202,13 +211,17 @@ void ImGuiPass::update_buffers(RenderTarget& target, const ImDrawData& draw_data
Expects(new_vertex_size > 0); Expects(new_vertex_size > 0);
Expects(new_index_size > 0); Expects(new_index_size > 0);
if(target.vertex_buffer[target.current_frame] == nullptr || target.current_vertex_size[target.current_frame] < new_vertex_size) { if (target.vertex_buffer[target.current_frame] == nullptr ||
target.vertex_buffer[target.current_frame] = engine->get_gfx()->create_buffer(nullptr, new_vertex_size, true, GFXBufferUsage::Vertex); target.current_vertex_size[target.current_frame] < new_vertex_size) {
target.vertex_buffer[target.current_frame] =
engine->get_gfx()->create_buffer(nullptr, new_vertex_size, true, GFXBufferUsage::Vertex);
target.current_vertex_size[target.current_frame] = new_vertex_size; target.current_vertex_size[target.current_frame] = new_vertex_size;
} }
if(target.index_buffer[target.current_frame] == nullptr || target.current_index_size[target.current_frame] < new_index_size) { if (target.index_buffer[target.current_frame] == nullptr ||
target.index_buffer[target.current_frame] = engine->get_gfx()->create_buffer(nullptr, new_index_size, true, GFXBufferUsage::Index); target.current_index_size[target.current_frame] < new_index_size) {
target.index_buffer[target.current_frame] =
engine->get_gfx()->create_buffer(nullptr, new_index_size, true, GFXBufferUsage::Index);
target.current_index_size[target.current_frame] = new_index_size; target.current_index_size[target.current_frame] = new_index_size;
} }
@ -216,13 +229,13 @@ void ImGuiPass::update_buffers(RenderTarget& target, const ImDrawData& draw_data
auto vtx_map = engine->get_gfx()->get_buffer_contents(target.vertex_buffer[target.current_frame]); auto vtx_map = engine->get_gfx()->get_buffer_contents(target.vertex_buffer[target.current_frame]);
auto idx_map = engine->get_gfx()->get_buffer_contents(target.index_buffer[target.current_frame]); auto idx_map = engine->get_gfx()->get_buffer_contents(target.index_buffer[target.current_frame]);
if(vtx_map == nullptr || idx_map == nullptr) if (vtx_map == nullptr || idx_map == nullptr)
return; return;
auto vtx_dst = (ImDrawVert*)vtx_map; auto vtx_dst = (ImDrawVert*)vtx_map;
auto idx_dst = (ImDrawIdx*)idx_map; auto idx_dst = (ImDrawIdx*)idx_map;
for(int i = 0; i < draw_data.CmdListsCount; i++) { for (int i = 0; i < draw_data.CmdListsCount; i++) {
const ImDrawList* cmd_list = draw_data.CmdLists[i]; const ImDrawList* cmd_list = draw_data.CmdLists[i];
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));

View file

@ -1,37 +1,43 @@
#include "materialcompiler.hpp" #include "materialcompiler.hpp"
#include "engine.hpp"
#include "file.hpp" #include "file.hpp"
#include "log.hpp" #include "log.hpp"
#include "engine.hpp"
#include "string_utils.hpp"
#include "shadercompiler.hpp"
#include "renderer.hpp" #include "renderer.hpp"
#include "shadercompiler.hpp"
#include "string_utils.hpp"
ShaderSource get_shader(const std::string& filename, bool skinned, bool cubemap) { ShaderSource get_shader(const std::string& filename, bool skinned, bool cubemap) {
auto shader_file = prism::open_file(prism::base_domain / filename); auto shader_file = prism::open_file(prism::base_domain / filename);
if(!shader_file.has_value()) { if (!shader_file.has_value()) {
prism::log("Failed to open shader file {}!", filename); prism::log("Failed to open shader file {}!", filename);
return {}; return {};
} }
ShaderStage stage; ShaderStage stage;
if(filename.find("vert") != std::string::npos) { if (filename.find("vert") != std::string::npos) {
stage = ShaderStage::Vertex; stage = ShaderStage::Vertex;
} else { } else {
stage = ShaderStage::Fragment; stage = ShaderStage::Fragment;
} }
CompileOptions options; CompileOptions options;
if(skinned) if (skinned)
options.add_definition("BONE"); options.add_definition("BONE");
if(cubemap) if (cubemap)
options.add_definition("CUBEMAP"); options.add_definition("CUBEMAP");
return *shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(shader_file->read_as_string()), engine->get_gfx()->accepted_shader_language(), options); return *shader_compiler.compile(
ShaderLanguage::GLSL,
stage,
ShaderSource(shader_file->read_as_string()),
engine->get_gfx()->accepted_shader_language(),
options);
} }
GFXPipeline* MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only, bool cubemap) { GFXPipeline*
MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateInfo createInfo, bool positions_only, bool cubemap) {
// take vertex src // take vertex src
const std::string vertex_path = fmt::format("{}.glsl", createInfo.shaders.vertex_src.as_path().string()); const std::string vertex_path = fmt::format("{}.glsl", createInfo.shaders.vertex_src.as_path().string());
@ -43,30 +49,24 @@ GFXPipeline* MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateI
createInfo.shaders.vertex_src = get_shader(vertex_path, false, cubemap); createInfo.shaders.vertex_src = get_shader(vertex_path, false, cubemap);
if(positions_only) { if (positions_only) {
createInfo.vertex_input.inputs = { createInfo.vertex_input.inputs = {{position_buffer_index, sizeof(prism::float3)}};
{position_buffer_index, sizeof(prism::float3)}
};
createInfo.vertex_input.attributes = { createInfo.vertex_input.attributes = {{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}};
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}
};
} else { } else {
createInfo.vertex_input.inputs = { createInfo.vertex_input.inputs = {
{position_buffer_index, sizeof(prism::float3)}, {position_buffer_index, sizeof(prism::float3)},
{normal_buffer_index, sizeof(prism::float3)}, {normal_buffer_index, sizeof(prism::float3)},
{texcoord_buffer_index, sizeof(prism::float2)}, {texcoord_buffer_index, sizeof(prism::float2)},
{tangent_buffer_index, sizeof(prism::float3)}, {tangent_buffer_index, sizeof(prism::float3)},
{bitangent_buffer_index, sizeof(prism::float3)} {bitangent_buffer_index, sizeof(prism::float3)}};
};
createInfo.vertex_input.attributes = { createInfo.vertex_input.attributes = {
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}, {position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
{normal_buffer_index, 1, 0, GFXVertexFormat::FLOAT3}, {normal_buffer_index, 1, 0, GFXVertexFormat::FLOAT3},
{texcoord_buffer_index, 2, 0, GFXVertexFormat::FLOAT2}, {texcoord_buffer_index, 2, 0, GFXVertexFormat::FLOAT2},
{tangent_buffer_index, 3, 0, GFXVertexFormat::FLOAT3}, {tangent_buffer_index, 3, 0, GFXVertexFormat::FLOAT3},
{bitangent_buffer_index, 4, 0, GFXVertexFormat::FLOAT3} {bitangent_buffer_index, 4, 0, GFXVertexFormat::FLOAT3}};
};
} }
return engine->get_gfx()->create_graphics_pipeline(createInfo); return engine->get_gfx()->create_graphics_pipeline(createInfo);
@ -80,19 +80,16 @@ GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreate
createInfo.shaders.vertex_src = get_shader(vertex_path, true, false); createInfo.shaders.vertex_src = get_shader(vertex_path, true, false);
createInfo.shader_input.bindings.push_back({ 14, GFXBindingType::StorageBuffer }); createInfo.shader_input.bindings.push_back({14, GFXBindingType::StorageBuffer});
if(positions_only) { if (positions_only) {
createInfo.vertex_input.inputs = { createInfo.vertex_input.inputs = {
{position_buffer_index, sizeof(prism::float3)}, {position_buffer_index, sizeof(prism::float3)}, {bone_buffer_index, sizeof(BoneVertexData)}};
{bone_buffer_index, sizeof(BoneVertexData)}
};
createInfo.vertex_input.attributes = { createInfo.vertex_input.attributes = {
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}, {position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
{bone_buffer_index, 4, offsetof(BoneVertexData, ids), GFXVertexFormat::INT4}, {bone_buffer_index, 4, offsetof(BoneVertexData, ids), GFXVertexFormat::INT4},
{bone_buffer_index, 5, offsetof(BoneVertexData, weights), GFXVertexFormat::FLOAT4} {bone_buffer_index, 5, offsetof(BoneVertexData, weights), GFXVertexFormat::FLOAT4}};
};
} else { } else {
createInfo.vertex_input.inputs = { createInfo.vertex_input.inputs = {
{position_buffer_index, sizeof(prism::float3)}, {position_buffer_index, sizeof(prism::float3)},
@ -100,8 +97,7 @@ GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreate
{texcoord_buffer_index, sizeof(prism::float2)}, {texcoord_buffer_index, sizeof(prism::float2)},
{tangent_buffer_index, sizeof(prism::float3)}, {tangent_buffer_index, sizeof(prism::float3)},
{bitangent_buffer_index, sizeof(prism::float3)}, {bitangent_buffer_index, sizeof(prism::float3)},
{bone_buffer_index, sizeof(BoneVertexData)} {bone_buffer_index, sizeof(BoneVertexData)}};
};
createInfo.vertex_input.attributes = { createInfo.vertex_input.attributes = {
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}, {position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
@ -117,7 +113,8 @@ GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreate
return engine->get_gfx()->create_graphics_pipeline(createInfo); return engine->get_gfx()->create_graphics_pipeline(createInfo);
} }
std::tuple<GFXPipeline*, GFXPipeline*> MaterialCompiler::create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only) { std::tuple<GFXPipeline*, GFXPipeline*>
MaterialCompiler::create_pipeline_permutations(GFXGraphicsPipelineCreateInfo& createInfo, bool positions_only) {
auto st = create_static_pipeline(createInfo, positions_only); auto st = create_static_pipeline(createInfo, positions_only);
auto ss = create_skinned_pipeline(createInfo, positions_only); auto ss = create_skinned_pipeline(createInfo, positions_only);
@ -125,7 +122,7 @@ std::tuple<GFXPipeline*, GFXPipeline*> MaterialCompiler::create_pipeline_permuta
} }
constexpr std::string_view struct_info = constexpr std::string_view struct_info =
R"(layout (constant_id = 0) const int max_materials = 25; R"(layout (constant_id = 0) const int max_materials = 25;
layout (constant_id = 1) const int max_lights = 25; layout (constant_id = 1) const int max_lights = 25;
layout (constant_id = 2) const int max_spot_lights = 4; layout (constant_id = 2) const int max_spot_lights = 4;
layout (constant_id = 3) const int max_probes = 4; layout (constant_id = 3) const int max_probes = 4;
@ -159,12 +156,12 @@ layout(push_constant) uniform PushConstant {{
)"; )";
ShaderSource MaterialCompiler::compile_material_fragment(Material& material, bool use_ibl) { ShaderSource MaterialCompiler::compile_material_fragment(Material& material, bool use_ibl) {
if(!render_options.enable_ibl) if (!render_options.enable_ibl)
use_ibl = false; use_ibl = false;
auto src = fmt::memory_buffer(); auto src = fmt::memory_buffer();
switch(render_options.shadow_filter) { switch (render_options.shadow_filter) {
case ShadowFilter::None: case ShadowFilter::None:
format_to(std::back_inserter(src), "#define SHADOW_FILTER_NONE\n"); format_to(std::back_inserter(src), "#define SHADOW_FILTER_NONE\n");
break; break;
@ -176,15 +173,17 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
break; break;
} }
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(layout (location = 0) in vec3 in_frag_pos; R"(layout (location = 0) in vec3 in_frag_pos;
layout(location = 1) in vec3 in_normal; layout(location = 1) in vec3 in_normal;
layout(location = 2) in vec2 in_uv; layout(location = 2) in vec2 in_uv;
layout(location = 0) out vec4 frag_output; layout(location = 0) out vec4 frag_output;
)"); )");
if(render_options.enable_point_shadows) { if (render_options.enable_point_shadows) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(#define POINT_SHADOWS_SUPPORTED R"(#define POINT_SHADOWS_SUPPORTED
layout (binding = 3) uniform samplerCubeArray point_shadow; layout (binding = 3) uniform samplerCubeArray point_shadow;
)"); )");
@ -192,15 +191,17 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
format_to(std::back_inserter(src), struct_info); format_to(std::back_inserter(src), struct_info);
if(use_ibl) { if (use_ibl) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(layout (binding = 7) uniform samplerCubeArray irrandianceSampler; R"(layout (binding = 7) uniform samplerCubeArray irrandianceSampler;
layout (binding = 8) uniform samplerCubeArray prefilterSampler; layout (binding = 8) uniform samplerCubeArray prefilterSampler;
layout (binding = 9) uniform sampler2D brdfSampler; layout (binding = 9) uniform sampler2D brdfSampler;
)"); )");
} }
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(layout(location = 4) in vec4 fragPosLightSpace; R"(layout(location = 4) in vec4 fragPosLightSpace;
layout(location = 5) in mat3 in_tbn; layout(location = 5) in mat3 in_tbn;
layout(location = 14) in vec4 fragPostSpotLightSpace[max_spot_lights]; layout(location = 14) in vec4 fragPostSpotLightSpace[max_spot_lights];
@ -213,20 +214,21 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
// insert samplers as needed // insert samplers as needed
int sampler_index = 10; int sampler_index = 10;
if(material.colorProperty.type == DataType::AssetTexture) { if (material.colorProperty.type == DataType::AssetTexture) {
material.bound_textures[sampler_index] = material.colorProperty.value_tex; material.bound_textures[sampler_index] = material.colorProperty.value_tex;
format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D colorTexture;\n", sampler_index++); format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D colorTexture;\n", sampler_index++);
} }
if(material.normalProperty.type == DataType::AssetTexture) { if (material.normalProperty.type == DataType::AssetTexture) {
material.bound_textures[sampler_index] = material.normalProperty.value_tex; material.bound_textures[sampler_index] = material.normalProperty.value_tex;
format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D normalTexture;\n", sampler_index++); format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D normalTexture;\n", sampler_index++);
} }
if(use_ibl) { if (use_ibl) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(vec3 get_reflect(int i, vec3 final_normal) {{ R"(vec3 get_reflect(int i, vec3 final_normal) {{
const vec3 direction = normalize(in_frag_pos - scene.camPos.xyz); const vec3 direction = normalize(in_frag_pos - scene.camPos.xyz);
const vec3 reflection = reflect(direction, normalize(final_normal)); const vec3 reflection = reflect(direction, normalize(final_normal));
@ -243,8 +245,9 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
)"); )");
} }
if(render_options.enable_normal_shadowing) { if (render_options.enable_normal_shadowing) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(float calculate_normal_lighting(in sampler2D normal_map, const vec3 normal, const vec3 light_dir) {{ R"(float calculate_normal_lighting(in sampler2D normal_map, const vec3 normal, const vec3 light_dir) {{
float height_scale = 0.8; float height_scale = 0.8;
float sample_count = 100.0; float sample_count = 100.0;
@ -278,8 +281,9 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
)"); )");
} }
if(use_ibl) { if (use_ibl) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(vec3 ibl(const int probe, const ComputedSurfaceInfo surface_info, const float intensity) {{ R"(vec3 ibl(const int probe, const ComputedSurfaceInfo surface_info, const float intensity) {{
const vec3 F = fresnel_schlick_roughness(surface_info.NdotV, surface_info.F0, surface_info.roughness); const vec3 F = fresnel_schlick_roughness(surface_info.NdotV, surface_info.F0, surface_info.roughness);
const vec3 R = get_reflect(probe, surface_info.N); const vec3 R = get_reflect(probe, surface_info.N);
@ -295,22 +299,29 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
format_to(std::back_inserter(src), "void main() {{\n"); format_to(std::back_inserter(src), "void main() {{\n");
if(material.colorProperty.type == DataType::Vector3) { if (material.colorProperty.type == DataType::Vector3) {
format_to(std::back_inserter(src), "vec3 Color = vec3({}, {}, {});\n", material.colorProperty.value.x, material.colorProperty.value.y, material.colorProperty.value.z); format_to(
} else if(material.colorProperty.type == DataType::AssetTexture) { std::back_inserter(src),
"vec3 Color = vec3({}, {}, {});\n",
material.colorProperty.value.x,
material.colorProperty.value.y,
material.colorProperty.value.z);
} else if (material.colorProperty.type == DataType::AssetTexture) {
format_to(std::back_inserter(src), "vec3 Color = texture(colorTexture, in_uv).rgb;\n"); format_to(std::back_inserter(src), "vec3 Color = texture(colorTexture, in_uv).rgb;\n");
} else if(material.colorProperty.type == DataType::Float) { } else if (material.colorProperty.type == DataType::Float) {
format_to(std::back_inserter(src),"vec3 Color = vec3({}});\n", material.colorProperty.float_value); format_to(std::back_inserter(src), "vec3 Color = vec3({}});\n", material.colorProperty.float_value);
} }
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(vec3 final_diffuse_color = from_srgb_to_linear(Color); R"(vec3 final_diffuse_color = from_srgb_to_linear(Color);
float final_roughness = scene.materials[inMaterialIndex].info.y; float final_roughness = scene.materials[inMaterialIndex].info.y;
float final_metallic = scene.materials[inMaterialIndex].info.x; float final_metallic = scene.materials[inMaterialIndex].info.x;
)"); )");
if(material.normalProperty.type == DataType::AssetTexture) { if (material.normalProperty.type == DataType::AssetTexture) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(vec3 final_normal = texture(normalTexture, in_uv).rgb; R"(vec3 final_normal = texture(normalTexture, in_uv).rgb;
final_normal = final_normal * 2.0 - 1.0; final_normal = final_normal * 2.0 - 1.0;
final_normal = in_tbn * final_normal; final_normal = in_tbn * final_normal;
@ -319,7 +330,8 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
format_to(std::back_inserter(src), "vec3 final_normal = in_normal;\n"); format_to(std::back_inserter(src), "vec3 final_normal = in_normal;\n");
} }
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness); R"(ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness);
vec3 Lo = vec3(0); vec3 Lo = vec3(0);
for(int i = 0; i < scene.numLights; i++) {{ for(int i = 0; i < scene.numLights; i++) {{
@ -339,15 +351,21 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
SurfaceBRDF surface_brdf = brdf(light_info.direction, surface_info); SurfaceBRDF surface_brdf = brdf(light_info.direction, surface_info);
)"); )");
if(render_options.enable_normal_mapping && material.normalProperty.type == DataType::AssetTexture && render_options.enable_normal_shadowing) { if (render_options.enable_normal_mapping && material.normalProperty.type == DataType::AssetTexture &&
format_to(std::back_inserter(src), "light_info.radiance *= calculate_normal_lighting(normalTexture, final_normal, light_info.direction);\n"); render_options.enable_normal_shadowing) {
format_to(
std::back_inserter(src),
"light_info.radiance *= calculate_normal_lighting(normalTexture, final_normal, light_info.direction);\n");
} }
format_to(std::back_inserter(src), "Lo += ((surface_brdf.specular + surface_brdf.diffuse) * light_info.radiance * surface_brdf.NdotL) * scene.lights[i].colorSize.rgb;\n \ format_to(
std::back_inserter(src),
"Lo += ((surface_brdf.specular + surface_brdf.diffuse) * light_info.radiance * surface_brdf.NdotL) * scene.lights[i].colorSize.rgb;\n \
}}\n"); }}\n");
if(use_ibl) { if (use_ibl) {
format_to(std::back_inserter(src), format_to(
std::back_inserter(src),
R"(vec3 ambient = vec3(0.0); R"(vec3 ambient = vec3(0.0);
float sum = 0.0; float sum = 0.0;
for(int i = 0; i < max_probes; i++) {{ for(int i = 0; i < max_probes; i++) {{
@ -376,5 +394,9 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
format_to(std::back_inserter(src), "}}\n"); format_to(std::back_inserter(src), "}}\n");
return *shader_compiler.compile(ShaderLanguage::GLSL, ShaderStage::Fragment, ShaderSource(to_string(src)), engine->get_gfx()->accepted_shader_language()); return *shader_compiler.compile(
ShaderLanguage::GLSL,
ShaderStage::Fragment,
ShaderSource(to_string(src)),
engine->get_gfx()->accepted_shader_language());
} }

View file

@ -1,22 +1,22 @@
#include "renderer.hpp" #include "renderer.hpp"
#include "gfx_commandbuffer.hpp" #include "assertions.hpp"
#include "math.hpp" #include "debug.hpp"
#include "dofpass.hpp"
#include "file.hpp" #include "file.hpp"
#include "scene.hpp" #include "frustum.hpp"
#include "vector.hpp"
#include "imguipass.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "gfx_commandbuffer.hpp"
#include "imguipass.hpp"
#include "materialcompiler.hpp"
#include "math.hpp"
#include "pass.hpp" #include "pass.hpp"
#include "scene.hpp"
#include "scenecapture.hpp"
#include "shadercompiler.hpp"
#include "shadowpass.hpp" #include "shadowpass.hpp"
#include "smaapass.hpp" #include "smaapass.hpp"
#include "scenecapture.hpp" #include "vector.hpp"
#include "materialcompiler.hpp"
#include "assertions.hpp"
#include "dofpass.hpp"
#include "frustum.hpp"
#include "shadercompiler.hpp"
#include "debug.hpp"
using prism::renderer; using prism::renderer;
@ -69,7 +69,7 @@ renderer::renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
scene_capture = std::make_unique<SceneCapture>(gfx); scene_capture = std::make_unique<SceneCapture>(gfx);
smaa_pass = std::make_unique<SMAAPass>(gfx); smaa_pass = std::make_unique<SMAAPass>(gfx);
if(enable_imgui) if (enable_imgui)
addPass<ImGuiPass>(); addPass<ImGuiPass>();
generate_brdf(); generate_brdf();
@ -109,13 +109,11 @@ void renderer::resize_render_target(RenderTarget& target, const prism::Extent ex
smaa_pass->create_render_target_resources(target); smaa_pass->create_render_target_resources(target);
create_post_pipelines(); create_post_pipelines();
for(auto& pass : passes) for (auto& pass : passes)
pass->create_render_target_resources(target); pass->create_render_target_resources(target);
} }
void renderer::recreate_all_render_targets() { void renderer::recreate_all_render_targets() {}
}
void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, platform::window_ptr index) { void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarget& target, platform::window_ptr index) {
const auto extent = target.extent; const auto extent = target.extent;
@ -133,7 +131,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->set_viewport(viewport); commandbuffer->set_viewport(viewport);
for (auto &pass: passes) for (auto& pass : passes)
pass->render_post(commandbuffer, target, index); pass->render_post(commandbuffer, target, index);
return; return;
@ -163,19 +161,19 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->set_render_pass(beginInfo); commandbuffer->set_render_pass(beginInfo);
const auto &cameras = scene->get_all<Camera>(); const auto& cameras = scene->get_all<Camera>();
for (auto&[obj, camera]: cameras) { for (auto& [obj, camera] : cameras) {
const bool requires_limited_perspective = render_options.enable_depth_of_field; const bool requires_limited_perspective = render_options.enable_depth_of_field;
if (requires_limited_perspective) { if (requires_limited_perspective) {
camera.perspective = prism::perspective(radians(camera.fov), camera.perspective = prism::perspective(
static_cast<float>(render_extent.width) / radians(camera.fov),
static_cast<float>(render_extent.height), static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height),
camera.near, camera.near,
100.0f); 100.0f);
} else { } else {
camera.perspective = prism::infinite_perspective(radians(camera.fov), camera.perspective = prism::infinite_perspective(
static_cast<float>(render_extent.width) / radians(camera.fov),
static_cast<float>(render_extent.height), static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height),
camera.near); camera.near);
} }
@ -209,33 +207,30 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->set_compute_pipeline(histogram_pipeline); commandbuffer->set_compute_pipeline(histogram_pipeline);
commandbuffer->bind_texture(target.offscreenColorTexture, 0); commandbuffer->bind_texture(target.offscreenColorTexture, 0);
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
sizeof(uint32_t) * 256);
const float lum_range = const float lum_range = render_options.max_luminance - render_options.min_luminance;
render_options.max_luminance - render_options.min_luminance;
prism::float4 params = prism::float4 params = prism::float4(
prism::float4(render_options.min_luminance, 1.0f / lum_range, render_options.min_luminance,
1.0f / lum_range,
static_cast<float>(render_extent.width), static_cast<float>(render_extent.width),
static_cast<float>(render_extent.height)); static_cast<float>(render_extent.height));
commandbuffer->set_push_constant(&params, sizeof(prism::float4)); commandbuffer->set_push_constant(&params, sizeof(prism::float4));
commandbuffer->dispatch( commandbuffer->dispatch(
static_cast<uint32_t>( static_cast<uint32_t>(std::ceil(static_cast<float>(render_extent.width) / 16.0f)),
std::ceil(static_cast<float>(render_extent.width) / 16.0f)), static_cast<uint32_t>(std::ceil(static_cast<float>(render_extent.height) / 16.0f)),
static_cast<uint32_t>(
std::ceil(static_cast<float>(render_extent.height) / 16.0f)),
1); 1);
commandbuffer->set_compute_pipeline(histogram_average_pipeline); commandbuffer->set_compute_pipeline(histogram_average_pipeline);
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
sizeof(uint32_t) * 256);
params = prism::float4( params = prism::float4(
render_options.min_luminance, lum_range, render_options.min_luminance,
lum_range,
std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f), std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f),
static_cast<float>(render_extent.width * render_extent.height)); static_cast<float>(render_extent.width * render_extent.height));
@ -250,14 +245,18 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
pc.options.x = render_options.enable_aa; pc.options.x = render_options.enable_aa;
pc.options.z = render_options.exposure; pc.options.z = render_options.exposure;
if(render_options.enable_depth_of_field) if (render_options.enable_depth_of_field)
pc.options.w = 2; pc.options.w = 2;
pc.transform_ops.x = static_cast<float>(render_options.display_color_space); pc.transform_ops.x = static_cast<float>(render_options.display_color_space);
pc.transform_ops.y = static_cast<float>(render_options.tonemapping); pc.transform_ops.y = static_cast<float>(render_options.tonemapping);
const auto [width, height] = render_extent; const auto [width, height] = render_extent;
pc.viewport = prism::float4(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height), static_cast<float>(width), static_cast<float>(height)); pc.viewport = prism::float4(
1.0f / static_cast<float>(width),
1.0f / static_cast<float>(height),
static_cast<float>(width),
static_cast<float>(height));
// continue post processing // continue post processing
// first we want to manually "expose" the scene, otherwise AA wouldn't work properly // first we want to manually "expose" the scene, otherwise AA wouldn't work properly
@ -284,7 +283,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->bind_texture(average_luminance_texture, 6); commandbuffer->bind_texture(average_luminance_texture, 6);
if(render_options.enable_depth_of_field) if (render_options.enable_depth_of_field)
commandbuffer->bind_texture(dof_pass->far_field, 7); commandbuffer->bind_texture(dof_pass->far_field, 7);
else else
commandbuffer->bind_texture(dummy_texture, 7); commandbuffer->bind_texture(dummy_texture, 7);
@ -325,7 +324,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->bind_texture(dummy_texture, 3); commandbuffer->bind_texture(dummy_texture, 3);
} }
if(auto texture = get_requested_texture(PassTextureType::SelectionSobel)) if (auto texture = get_requested_texture(PassTextureType::SelectionSobel))
commandbuffer->bind_texture(texture, 5); commandbuffer->bind_texture(texture, 5);
else else
commandbuffer->bind_texture(dummy_texture, 5); commandbuffer->bind_texture(dummy_texture, 5);
@ -339,7 +338,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
commandbuffer->push_group("Extra Passes"); commandbuffer->push_group("Extra Passes");
for(auto& pass : passes) for (auto& pass : passes)
pass->render_post(commandbuffer, target, index); pass->render_post(commandbuffer, target, index);
commandbuffer->pop_group(); commandbuffer->pop_group();
@ -347,7 +346,14 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
target.current_frame = (target.current_frame + 1) % RT_MAX_FRAMES_IN_FLIGHT; target.current_frame = (target.current_frame + 1) % RT_MAX_FRAMES_IN_FLIGHT;
} }
void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, RenderTarget& target, controller_continuity& continuity) { void renderer::render_camera(
GFXCommandBuffer* command_buffer,
Scene& scene,
Object camera_object,
Camera& camera,
prism::Extent extent,
RenderTarget& target,
controller_continuity& continuity) {
// frustum test // frustum test
const auto frustum = normalize_frustum(camera_extract_frustum(scene, camera_object)); const auto frustum = normalize_frustum(camera_extract_frustum(scene, camera_object));
@ -355,11 +361,12 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
sceneInfo.lightspace = scene.lightSpace; sceneInfo.lightspace = scene.lightSpace;
sceneInfo.options = prism::float4(1, 0, 0, 0); sceneInfo.options = prism::float4(1, 0, 0, 0);
sceneInfo.camPos = scene.get<Transform>(camera_object).get_world_position(); sceneInfo.camPos = scene.get<Transform>(camera_object).get_world_position();
sceneInfo.camPos.w = 2.0f * camera.near * std::tan(camera.fov * 0.5f) * (static_cast<float>(extent.width) / static_cast<float>(extent.height)); sceneInfo.camPos.w = 2.0f * camera.near * std::tan(camera.fov * 0.5f) *
(static_cast<float>(extent.width) / static_cast<float>(extent.height));
sceneInfo.vp = camera.perspective * camera.view; sceneInfo.vp = camera.perspective * camera.view;
int last_point_light = 0; int last_point_light = 0;
for(const auto& [obj, light] : scene.get_all<Light>()) { for (const auto& [obj, light] : scene.get_all<Light>()) {
SceneLight sl; SceneLight sl;
sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type)); sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type));
@ -370,17 +377,17 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
sl.shadowsEnable = prism::float4(light.enable_shadows, radians(light.size), last_point_light, 0); sl.shadowsEnable = prism::float4(light.enable_shadows, radians(light.size), last_point_light, 0);
if(light.enable_shadows) if (light.enable_shadows)
last_point_light++; last_point_light++;
sceneInfo.lights[sceneInfo.numLights++] = sl; sceneInfo.lights[sceneInfo.numLights++] = sl;
} }
for(int i = 0; i < max_spot_shadows; i++) for (int i = 0; i < max_spot_shadows; i++)
sceneInfo.spotLightSpaces[i] = scene.spotLightSpaces[i]; sceneInfo.spotLightSpaces[i] = scene.spotLightSpaces[i];
int last_probe = 0; int last_probe = 0;
for(const auto& [obj, probe] : scene.get_all<EnvironmentProbe>()) { for (const auto& [obj, probe] : scene.get_all<EnvironmentProbe>()) {
SceneProbe p; SceneProbe p;
p.position = prism::float4(scene.get<Transform>(obj).position, probe.is_sized ? 1.0f : 2.0f); p.position = prism::float4(scene.get<Transform>(obj).position, probe.is_sized ? 1.0f : 2.0f);
p.size = prism::float4(probe.size, probe.intensity); p.size = prism::float4(probe.size, probe.intensity);
@ -392,21 +399,21 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
std::map<Material*, int> material_indices; std::map<Material*, int> material_indices;
const auto& meshes = scene.get_all<Renderable>(); const auto& meshes = scene.get_all<Renderable>();
for(const auto& [obj, mesh] : meshes) { for (const auto& [obj, mesh] : meshes) {
if(!mesh.mesh) if (!mesh.mesh)
continue; continue;
if(mesh.materials.empty()) if (mesh.materials.empty())
continue; continue;
for(auto& material : mesh.materials) { for (auto& material : mesh.materials) {
if(!material) if (!material)
continue; continue;
if(material->static_pipeline == nullptr || material->skinned_pipeline == nullptr) if (material->static_pipeline == nullptr || material->skinned_pipeline == nullptr)
create_mesh_pipeline(*material.handle); create_mesh_pipeline(*material.handle);
if(!material_indices.count(material.handle)) { if (!material_indices.count(material.handle)) {
sceneInfo.materials[numMaterialsInBuffer].info.x = material->metallic; sceneInfo.materials[numMaterialsInBuffer].info.x = material->metallic;
sceneInfo.materials[numMaterialsInBuffer].info.y = material->roughness; sceneInfo.materials[numMaterialsInBuffer].info.y = material->roughness;
@ -426,24 +433,28 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->set_vertex_buffer(mesh.mesh->tangent_buffer, 0, tangent_buffer_index); command_buffer->set_vertex_buffer(mesh.mesh->tangent_buffer, 0, tangent_buffer_index);
command_buffer->set_vertex_buffer(mesh.mesh->bitangent_buffer, 0, bitangent_buffer_index); command_buffer->set_vertex_buffer(mesh.mesh->bitangent_buffer, 0, bitangent_buffer_index);
if(!mesh.mesh->bones.empty()) if (!mesh.mesh->bones.empty())
command_buffer->set_vertex_buffer(mesh.mesh->bone_buffer, 0, bone_buffer_index); command_buffer->set_vertex_buffer(mesh.mesh->bone_buffer, 0, bone_buffer_index);
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32); command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
for(const auto& part : mesh.mesh->parts) { for (const auto& part : mesh.mesh->parts) {
const int material_index = part.material_override == -1 ? 0 : part.material_override; const int material_index = part.material_override == -1 ? 0 : part.material_override;
if(material_index >= mesh.materials.size()) if (material_index >= mesh.materials.size())
continue; continue;
if(mesh.materials[material_index].handle == nullptr || mesh.materials[material_index]->static_pipeline == nullptr) if (mesh.materials[material_index].handle == nullptr ||
mesh.materials[material_index]->static_pipeline == nullptr)
continue; continue;
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part))) if (render_options.enable_frustum_culling &&
!test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part)))
continue; continue;
command_buffer->set_graphics_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline); command_buffer->set_graphics_pipeline(
mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline
: mesh.materials[material_index]->skinned_pipeline);
command_buffer->bind_shader_buffer(target.sceneBuffer, 0, 1, sizeof(SceneInformation)); command_buffer->bind_shader_buffer(target.sceneBuffer, 0, 1, sizeof(SceneInformation));
@ -454,20 +465,24 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->bind_texture(scene.prefilteredCubeArray, 8); command_buffer->bind_texture(scene.prefilteredCubeArray, 8);
command_buffer->bind_texture(brdf_texture, 9); command_buffer->bind_texture(brdf_texture, 9);
if(!mesh.mesh->bones.empty()) if (!mesh.mesh->bones.empty())
command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128); command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128);
command_buffer->set_push_constant(&pc, sizeof(PushConstant)); command_buffer->set_push_constant(&pc, sizeof(PushConstant));
for(const auto& [index, texture] : mesh.materials[material_index]->bound_textures) { for (const auto& [index, texture] : mesh.materials[material_index]->bound_textures) {
GFXTexture* texture_to_bind = dummy_texture; GFXTexture* texture_to_bind = dummy_texture;
if(texture) if (texture)
texture_to_bind = texture->handle; texture_to_bind = texture->handle;
command_buffer->bind_texture(texture_to_bind, index); command_buffer->bind_texture(texture_to_bind, index);
} }
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, material_indices.at(*mesh.materials[material_index])); command_buffer->draw_indexed(
part.index_count,
part.index_offset,
part.vertex_offset,
material_indices.at(*mesh.materials[material_index]));
} }
} }
@ -475,8 +490,8 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
pc.view = matrix_from_quat(scene.get<Transform>(camera_object).rotation); pc.view = matrix_from_quat(scene.get<Transform>(camera_object).rotation);
pc.aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height); pc.aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height);
for(const auto& [obj, light] : scene.get_all<Light>()) { for (const auto& [obj, light] : scene.get_all<Light>()) {
if(light.type == Light::Type::Sun) if (light.type == Light::Type::Sun)
pc.sun_position_fov = prism::float4(scene.get<Transform>(obj).get_world_position(), radians(camera.fov)); pc.sun_position_fov = prism::float4(scene.get<Transform>(obj).get_world_position(), radians(camera.fov));
} }
@ -486,8 +501,8 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->draw(0, 4, 0, 1); command_buffer->draw(0, 4, 0, 1);
if(render_options.enable_extra_passes) { if (render_options.enable_extra_passes) {
for(auto& pass : passes) for (auto& pass : passes)
pass->render_scene(scene, command_buffer); pass->render_scene(scene, command_buffer);
} }
@ -519,12 +534,12 @@ void renderer::create_mesh_pipeline(Material& material) const {
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/mesh.vert")); pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/mesh.vert"));
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/mesh.frag")); pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/mesh.frag"));
pipelineInfo.shaders.vertex_constants = {materials_constant, lights_constant, spot_lights_constant, probes_constant}; pipelineInfo.shaders.vertex_constants = {
pipelineInfo.shaders.fragment_constants = {materials_constant, lights_constant, spot_lights_constant, probes_constant}; materials_constant, lights_constant, spot_lights_constant, probes_constant};
pipelineInfo.shaders.fragment_constants = {
materials_constant, lights_constant, spot_lights_constant, probes_constant};
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4), 0}};
{sizeof(Matrix4x4), 0}
};
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {
{1, GFXBindingType::StorageBuffer}, {1, GFXBindingType::StorageBuffer},
@ -534,8 +549,7 @@ void renderer::create_mesh_pipeline(Material& material) const {
{6, GFXBindingType::Texture}, {6, GFXBindingType::Texture},
{7, GFXBindingType::Texture}, {7, GFXBindingType::Texture},
{8, GFXBindingType::Texture}, {8, GFXBindingType::Texture},
{9, GFXBindingType::Texture} {9, GFXBindingType::Texture}};
};
pipelineInfo.render_pass = offscreen_render_pass; pipelineInfo.render_pass = offscreen_render_pass;
pipelineInfo.depth.depth_mode = GFXDepthMode::Less; pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
@ -560,7 +574,8 @@ void renderer::create_mesh_pipeline(Material& material) const {
pipelineInfo.render_pass = scene_capture->renderPass; pipelineInfo.render_pass = scene_capture->renderPass;
pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL pipelineInfo.shaders.fragment_src =
material_compiler.compile_material_fragment(material, false); // scene capture does not use IBL
pipelineInfo.shader_input.push_constants[0].size += sizeof(Matrix4x4); pipelineInfo.shader_input.push_constants[0].size += sizeof(Matrix4x4);
@ -592,8 +607,7 @@ void renderer::create_render_target_resources(RenderTarget& target) {
textureInfo.width = extent.width; textureInfo.width = extent.width;
textureInfo.height = extent.height; textureInfo.height = extent.height;
textureInfo.format = GFXPixelFormat::RGBA_32F; textureInfo.format = GFXPixelFormat::RGBA_32F;
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::Storage;
GFXTextureUsage::Storage;
textureInfo.samplingMode = SamplingMode::ClampToEdge; textureInfo.samplingMode = SamplingMode::ClampToEdge;
target.offscreenColorTexture = gfx->create_texture(textureInfo); target.offscreenColorTexture = gfx->create_texture(textureInfo);
@ -648,9 +662,7 @@ void renderer::create_post_pipelines() {
{5, GFXBindingType::Texture} // sobelSampler {5, GFXBindingType::Texture} // sobelSampler
}; };
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(PostPushConstants), 0}};
{sizeof(PostPushConstants), 0}
};
post_pipeline = gfx->create_graphics_pipeline(pipelineInfo); post_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
@ -677,13 +689,9 @@ void renderer::create_sky_pipeline() {
pipelineInfo.shaders.vertex_src = register_shader("shaders/sky.vert"); pipelineInfo.shaders.vertex_src = register_shader("shaders/sky.vert");
pipelineInfo.shaders.fragment_src = register_shader("shaders/sky.frag"); pipelineInfo.shaders.fragment_src = register_shader("shaders/sky.frag");
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}};
{0, GFXBindingType::PushConstant}
};
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(SkyPushConstant), 0}};
{sizeof(SkyPushConstant), 0}
};
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual; pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
@ -754,14 +762,9 @@ void renderer::create_histogram_resources() {
create_info.workgroup_size_y = 16; create_info.workgroup_size_y = 16;
create_info.shader_input.bindings = { create_info.shader_input.bindings = {
{0, GFXBindingType::StorageImage}, {0, GFXBindingType::StorageImage}, {1, GFXBindingType::StorageBuffer}, {2, GFXBindingType::PushConstant}};
{1, GFXBindingType::StorageBuffer},
{2, GFXBindingType::PushConstant}
};
create_info.shader_input.push_constants = { create_info.shader_input.push_constants = {{sizeof(prism::float4), 0}};
{sizeof(prism::float4), 0}
};
histogram_pipeline = gfx->create_compute_pipeline(create_info); histogram_pipeline = gfx->create_compute_pipeline(create_info);
@ -785,7 +788,7 @@ void renderer::create_histogram_resources() {
} }
ShaderSource renderer::register_shader(const std::string_view shader_file) { ShaderSource renderer::register_shader(const std::string_view shader_file) {
if(!reloading_shader) { if (!reloading_shader) {
RegisteredShader shader; RegisteredShader shader;
shader.filename = shader_file; shader.filename = shader_file;
@ -793,8 +796,8 @@ ShaderSource renderer::register_shader(const std::string_view shader_file) {
} }
std::string found_shader_source; std::string found_shader_source;
for(auto& shader : registered_shaders) { for (auto& shader : registered_shaders) {
if(shader.filename == shader_file) { if (shader.filename == shader_file) {
found_shader_source = shader.injected_shader_source; found_shader_source = shader.injected_shader_source;
} }
} }
@ -802,7 +805,7 @@ ShaderSource renderer::register_shader(const std::string_view shader_file) {
prism::path base_shader_path = get_shader_source_directory(); prism::path base_shader_path = get_shader_source_directory();
// if shader editor system is not initialized, use prebuilt shaders // if shader editor system is not initialized, use prebuilt shaders
if(base_shader_path.empty()) if (base_shader_path.empty())
return ShaderSource(prism::path(shader_file)); return ShaderSource(prism::path(shader_file));
shader_compiler.set_include_path(base_shader_path.string()); shader_compiler.set_include_path(base_shader_path.string());
@ -810,33 +813,40 @@ ShaderSource renderer::register_shader(const std::string_view shader_file) {
prism::path shader_path = prism::path(shader_file); prism::path shader_path = prism::path(shader_file);
ShaderStage stage = ShaderStage::Vertex; ShaderStage stage = ShaderStage::Vertex;
if(shader_path.extension() == ".vert") if (shader_path.extension() == ".vert")
stage = ShaderStage::Vertex; stage = ShaderStage::Vertex;
else if(shader_path.extension() == ".frag") else if (shader_path.extension() == ".frag")
stage = ShaderStage::Fragment; stage = ShaderStage::Fragment;
if(found_shader_source.empty()) { if (found_shader_source.empty()) {
auto file = prism::open_file(base_shader_path / shader_path.replace_extension(shader_path.extension().string() + ".glsl")); auto file = prism::open_file(
base_shader_path / shader_path.replace_extension(shader_path.extension().string() + ".glsl"));
return shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(file->read_as_string()), gfx->accepted_shader_language()).value(); return shader_compiler
.compile(ShaderLanguage::GLSL, stage, ShaderSource(file->read_as_string()), gfx->accepted_shader_language())
.value();
} else { } else {
return shader_compiler.compile(ShaderLanguage::GLSL, stage, ShaderSource(found_shader_source), gfx->accepted_shader_language()).value(); return shader_compiler
.compile(ShaderLanguage::GLSL, stage, ShaderSource(found_shader_source), gfx->accepted_shader_language())
.value();
} }
} }
void renderer::associate_shader_reload(const std::string_view shader_file, const std::function<void()>& reload_function) { void renderer::associate_shader_reload(
if(reloading_shader) const std::string_view shader_file,
const std::function<void()>& reload_function) {
if (reloading_shader)
return; return;
for(auto& shader : registered_shaders) { for (auto& shader : registered_shaders) {
if(shader.filename == shader_file) if (shader.filename == shader_file)
shader.reload_function = reload_function; shader.reload_function = reload_function;
} }
} }
void renderer::reload_shader(const std::string_view shader_file, const std::string_view shader_source) { void renderer::reload_shader(const std::string_view shader_file, const std::string_view shader_source) {
for(auto& shader : registered_shaders) { for (auto& shader : registered_shaders) {
if(shader.filename == shader_file) { if (shader.filename == shader_file) {
shader.injected_shader_source = shader_source; shader.injected_shader_source = shader_source;
reloading_shader = true; reloading_shader = true;
shader.reload_function(); shader.reload_function();

View file

@ -1,14 +1,14 @@
#include "scenecapture.hpp" #include "scenecapture.hpp"
#include "gfx_commandbuffer.hpp"
#include "scene.hpp"
#include "gfx.hpp"
#include "engine.hpp"
#include "renderer.hpp"
#include "shadowpass.hpp"
#include "materialcompiler.hpp"
#include "frustum.hpp"
#include "asset.hpp" #include "asset.hpp"
#include "engine.hpp"
#include "frustum.hpp"
#include "gfx.hpp"
#include "gfx_commandbuffer.hpp"
#include "materialcompiler.hpp"
#include "renderer.hpp"
#include "scene.hpp"
#include "shadowpass.hpp"
struct PushConstant { struct PushConstant {
Matrix4x4 m, v; Matrix4x4 m, v;
@ -110,7 +110,8 @@ SceneCapture::SceneCapture(GFX* gfx) {
cubeTextureInfo.width = scene_cubemap_resolution; cubeTextureInfo.width = scene_cubemap_resolution;
cubeTextureInfo.height = scene_cubemap_resolution; cubeTextureInfo.height = scene_cubemap_resolution;
cubeTextureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM; cubeTextureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
cubeTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst | GFXTextureUsage::TransferSrc; // dst used for cubemap copy, src used for mipmap gen cubeTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst |
GFXTextureUsage::TransferSrc; // dst used for cubemap copy, src used for mipmap gen
cubeTextureInfo.samplingMode = SamplingMode::ClampToEdge; cubeTextureInfo.samplingMode = SamplingMode::ClampToEdge;
cubeTextureInfo.mip_count = mipLevels; cubeTextureInfo.mip_count = mipLevels;
@ -126,7 +127,7 @@ SceneCapture::SceneCapture(GFX* gfx) {
void SceneCapture::create_scene_resources(Scene& scene) { void SceneCapture::create_scene_resources(Scene& scene) {
auto gfx = engine->get_gfx(); auto gfx = engine->get_gfx();
if(gfx->supports_feature(GFXFeature::CubemapArray)) { if (gfx->supports_feature(GFXFeature::CubemapArray)) {
GFXTextureCreateInfo cubeTextureInfo = {}; GFXTextureCreateInfo cubeTextureInfo = {};
cubeTextureInfo.label = "Irriadiance Cubemap"; cubeTextureInfo.label = "Irriadiance Cubemap";
cubeTextureInfo.type = GFXTextureType::CubemapArray; cubeTextureInfo.type = GFXTextureType::CubemapArray;
@ -155,18 +156,18 @@ void SceneCapture::create_scene_resources(Scene& scene) {
} }
void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) { void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
if(scene->probe_refresh_timer > 0) { if (scene->probe_refresh_timer > 0) {
scene->probe_refresh_timer--; scene->probe_refresh_timer--;
return; return;
} }
int last_probe = 0; int last_probe = 0;
auto probes = scene->get_all<EnvironmentProbe>(); auto probes = scene->get_all<EnvironmentProbe>();
for(auto [obj, probe] : probes) { for (auto [obj, probe] : probes) {
if(last_probe > max_environment_probes) if (last_probe > max_environment_probes)
return; return;
if(scene->environment_dirty[last_probe]) { if (scene->environment_dirty[last_probe]) {
std::map<Material*, int> material_indices; std::map<Material*, int> material_indices;
int numMaterialsInBuffer = 0; int numMaterialsInBuffer = 0;
@ -181,7 +182,7 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
sceneInfo.camPos = lightPos; sceneInfo.camPos = lightPos;
sceneInfo.vp = projection; sceneInfo.vp = projection;
for(const auto [obj, light] : scene->get_all<Light>()) { for (const auto [obj, light] : scene->get_all<Light>()) {
SceneLight sl; SceneLight sl;
sl.positionType = prism::float4(scene->get<Transform>(obj).get_world_position(), (int)light.type); sl.positionType = prism::float4(scene->get<Transform>(obj).get_world_position(), (int)light.type);
@ -194,26 +195,26 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
sceneInfo.lights[sceneInfo.numLights++] = sl; sceneInfo.lights[sceneInfo.numLights++] = sl;
} }
for(int i = 0; i < max_spot_shadows; i++) for (int i = 0; i < max_spot_shadows; i++)
sceneInfo.spotLightSpaces[i] = scene->spotLightSpaces[i]; sceneInfo.spotLightSpaces[i] = scene->spotLightSpaces[i];
const auto& meshes = scene->get_all<Renderable>(); const auto& meshes = scene->get_all<Renderable>();
for(const auto [obj, mesh] : meshes) { for (const auto [obj, mesh] : meshes) {
if(!mesh.mesh) if (!mesh.mesh)
continue; continue;
if(mesh.materials.empty()) if (mesh.materials.empty())
continue; continue;
for(const auto& material : mesh.materials) { for (const auto& material : mesh.materials) {
if(!material) if (!material)
continue; continue;
if(material->static_pipeline == nullptr || material->skinned_pipeline == nullptr) if (material->static_pipeline == nullptr || material->skinned_pipeline == nullptr)
engine->get_renderer()->create_mesh_pipeline(*material.handle); engine->get_renderer()->create_mesh_pipeline(*material.handle);
if(!material_indices.count(material.handle)) { if (!material_indices.count(material.handle)) {
material_indices[material.handle] = numMaterialsInBuffer++; material_indices[material.handle] = numMaterialsInBuffer++;
} }
} }
@ -235,12 +236,12 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->set_viewport(viewport); command_buffer->set_viewport(viewport);
if(probe.is_sized) { if (probe.is_sized) {
for(const auto [obj, mesh] : meshes) { for (const auto [obj, mesh] : meshes) {
if(!mesh.mesh) if (!mesh.mesh)
continue; continue;
if(mesh.materials.empty()) if (mesh.materials.empty())
continue; continue;
PushConstant pc; PushConstant pc;
@ -255,17 +256,19 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32); command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
if(mesh.mesh->bones.empty()) { if (mesh.mesh->bones.empty()) {
for (auto& part : mesh.mesh->parts) { for (auto& part : mesh.mesh->parts) {
const int material_index = part.material_override == -1 ? 0 : part.material_override; const int material_index = part.material_override == -1 ? 0 : part.material_override;
if(material_index >= mesh.materials.size()) if (material_index >= mesh.materials.size())
continue; continue;
if(mesh.materials[material_index].handle == nullptr || mesh.materials[material_index]->static_pipeline == nullptr) if (mesh.materials[material_index].handle == nullptr ||
mesh.materials[material_index]->static_pipeline == nullptr)
continue; continue;
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene->get<Transform>(obj), part))) if (render_options.enable_frustum_culling &&
!test_aabb_frustum(frustum, get_aabb_for_part(scene->get<Transform>(obj), part)))
continue; continue;
command_buffer->set_graphics_pipeline(mesh.materials[material_index]->capture_pipeline); command_buffer->set_graphics_pipeline(mesh.materials[material_index]->capture_pipeline);
@ -277,15 +280,16 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->set_push_constant(&pc, sizeof(PushConstant)); command_buffer->set_push_constant(&pc, sizeof(PushConstant));
for(auto& [index, texture] : mesh.materials[material_index]->bound_textures) { for (auto& [index, texture] : mesh.materials[material_index]->bound_textures) {
GFXTexture* texture_to_bind = engine->get_renderer()->dummy_texture; GFXTexture* texture_to_bind = engine->get_renderer()->dummy_texture;
if(texture) if (texture)
texture_to_bind = texture->handle; texture_to_bind = texture->handle;
command_buffer->bind_texture(texture_to_bind, index); command_buffer->bind_texture(texture_to_bind, index);
} }
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, 0); command_buffer->draw_indexed(
part.index_count, part.index_offset, part.vertex_offset, 0);
} }
} }
} }
@ -297,9 +301,10 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
pc.view = sceneTransforms[face]; pc.view = sceneTransforms[face];
pc.aspect = 1.0f; pc.aspect = 1.0f;
for(auto& [obj, light] : scene->get_all<Light>()) { for (auto& [obj, light] : scene->get_all<Light>()) {
if(light.type == Light::Type::Sun) if (light.type == Light::Type::Sun)
pc.sun_position_fov = prism::float4(scene->get<Transform>(obj).get_world_position(), radians(90.0f)); pc.sun_position_fov =
prism::float4(scene->get<Transform>(obj).get_world_position(), radians(90.0f));
} }
command_buffer->set_graphics_pipeline(skyPipeline); command_buffer->set_graphics_pipeline(skyPipeline);
@ -309,7 +314,8 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->draw(0, 4, 0, 1); command_buffer->draw(0, 4, 0, 1);
command_buffer->end_render_pass(); command_buffer->end_render_pass();
command_buffer->copy_texture(offscreenTexture, scene_cubemap_resolution, scene_cubemap_resolution, environmentCube, face, 0, 0); command_buffer->copy_texture(
offscreenTexture, scene_cubemap_resolution, scene_cubemap_resolution, environmentCube, face, 0, 0);
}; };
engine->get_gfx()->copy_buffer(sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation)); engine->get_gfx()->copy_buffer(sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
@ -347,7 +353,8 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0); command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0);
command_buffer->end_render_pass(); command_buffer->end_render_pass();
command_buffer->copy_texture(irradianceOffscreenTexture, command_buffer->copy_texture(
irradianceOffscreenTexture,
irradiance_cubemap_resolution, irradiance_cubemap_resolution,
irradiance_cubemap_resolution, irradiance_cubemap_resolution,
scene->irradianceCubeArray, scene->irradianceCubeArray,
@ -390,13 +397,18 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0); command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0);
command_buffer->end_render_pass(); command_buffer->end_render_pass();
command_buffer->copy_texture(prefilteredOffscreenTexture, command_buffer->copy_texture(
resolution, resolution, prefilteredOffscreenTexture,
scene->prefilteredCubeArray, face, last_probe, mip); resolution,
resolution,
scene->prefilteredCubeArray,
face,
last_probe,
mip);
}; };
for(int mip = 0; mip < mipLevels; mip++) { for (int mip = 0; mip < mipLevels; mip++) {
for(int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
prefilter_face(i, mip); prefilter_face(i, mip);
} }
@ -415,13 +427,9 @@ void SceneCapture::createSkyResources() {
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/sky.vert")); pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/sky.vert"));
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/sky.frag")); pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/sky.frag"));
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}};
{0, GFXBindingType::PushConstant}
};
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(SkyPushConstant), 0}};
{sizeof(SkyPushConstant), 0}
};
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual; pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
@ -469,14 +477,9 @@ void SceneCapture::createIrradianceResources() {
pipelineInfo.vertex_input.attributes.push_back(positionAttribute); pipelineInfo.vertex_input.attributes.push_back(positionAttribute);
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4), 0}};
{sizeof(Matrix4x4), 0}
};
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
{1, GFXBindingType::PushConstant},
{2, GFXBindingType::Texture}
};
pipelineInfo.render_pass = irradianceRenderPass; pipelineInfo.render_pass = irradianceRenderPass;
@ -523,14 +526,9 @@ void SceneCapture::createPrefilterResources() {
pipelineInfo.vertex_input.attributes.push_back(positionAttribute); pipelineInfo.vertex_input.attributes.push_back(positionAttribute);
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(FilterPushConstant), 0}};
{sizeof(FilterPushConstant), 0}
};
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
{0, GFXBindingType::PushConstant},
{2, GFXBindingType::Texture}
};
pipelineInfo.render_pass = irradianceRenderPass; pipelineInfo.render_pass = irradianceRenderPass;

View file

@ -1,13 +1,13 @@
#include "shadowpass.hpp" #include "shadowpass.hpp"
#include "gfx_commandbuffer.hpp"
#include "scene.hpp"
#include "gfx.hpp"
#include "engine.hpp"
#include "materialcompiler.hpp"
#include "assertions.hpp" #include "assertions.hpp"
#include "engine.hpp"
#include "frustum.hpp" #include "frustum.hpp"
#include "gfx.hpp"
#include "gfx_commandbuffer.hpp"
#include "materialcompiler.hpp"
#include "renderer.hpp" #include "renderer.hpp"
#include "scene.hpp"
struct PushConstant { struct PushConstant {
Matrix4x4 mvp, model; Matrix4x4 mvp, model;
@ -55,7 +55,7 @@ void ShadowPass::create_scene_resources(Scene& scene) {
} }
// point lights // point lights
if(gfx->supports_feature(GFXFeature::CubemapArray)) { if (gfx->supports_feature(GFXFeature::CubemapArray)) {
GFXTextureCreateInfo cubeTextureInfo = {}; GFXTextureCreateInfo cubeTextureInfo = {};
cubeTextureInfo.label = "Point Light Array"; cubeTextureInfo.label = "Point Light Array";
cubeTextureInfo.type = GFXTextureType::CubemapArray; cubeTextureInfo.type = GFXTextureType::CubemapArray;
@ -91,17 +91,17 @@ void ShadowPass::render(GFXCommandBuffer* command_buffer, Scene& scene) {
last_spot_light = 0; last_spot_light = 0;
last_point_light = 0; last_point_light = 0;
if(scene.shadow_refresh_timer > 0) { if (scene.shadow_refresh_timer > 0) {
scene.shadow_refresh_timer--; scene.shadow_refresh_timer--;
return; return;
} }
auto lights = scene.get_all<Light>(); auto lights = scene.get_all<Light>();
for(auto [obj, light] : lights) { for (auto [obj, light] : lights) {
if(!light.enable_shadows) if (!light.enable_shadows)
continue; continue;
switch(light.type) { switch (light.type) {
case Light::Type::Sun: case Light::Type::Sun:
render_sun(command_buffer, scene, obj, light); render_sun(command_buffer, scene, obj, light);
break; break;
@ -115,9 +115,17 @@ void ShadowPass::render(GFXCommandBuffer* command_buffer, Scene& scene) {
} }
} }
void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, const Matrix4x4 light_matrix, const Matrix4x4 model, const prism::float3, const Light::Type type, const CameraFrustum& frustum, const int base_instance) { void ShadowPass::render_meshes(
for(auto [obj, mesh] : scene.get_all<Renderable>()) { GFXCommandBuffer* command_buffer,
if(!mesh.mesh) Scene& scene,
const Matrix4x4 light_matrix,
const Matrix4x4 model,
const prism::float3,
const Light::Type type,
const CameraFrustum& frustum,
const int base_instance) {
for (auto [obj, mesh] : scene.get_all<Renderable>()) {
if (!mesh.mesh)
continue; continue;
command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index); command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index);
@ -128,8 +136,8 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
pc.mvp = light_matrix * model * scene.get<Transform>(obj).model; pc.mvp = light_matrix * model * scene.get<Transform>(obj).model;
pc.model = scene.get<Transform>(obj).model; pc.model = scene.get<Transform>(obj).model;
if(mesh.mesh->bones.empty()) { if (mesh.mesh->bones.empty()) {
switch(type) { switch (type) {
case Light::Type::Sun: case Light::Type::Sun:
command_buffer->set_graphics_pipeline(static_sun_pipeline); command_buffer->set_graphics_pipeline(static_sun_pipeline);
break; break;
@ -147,13 +155,14 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f); command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
for (auto& part : mesh.mesh->parts) { for (auto& part : mesh.mesh->parts) {
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part))) if (render_options.enable_frustum_culling &&
!test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part)))
continue; continue;
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance); command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance);
} }
} else { } else {
switch(type) { switch (type) {
case Light::Type::Sun: case Light::Type::Sun:
command_buffer->set_graphics_pipeline(skinned_sun_pipeline); command_buffer->set_graphics_pipeline(skinned_sun_pipeline);
break; break;
@ -173,7 +182,8 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f); command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
for (auto& part : mesh.mesh->parts) { for (auto& part : mesh.mesh->parts) {
if(render_options.enable_frustum_culling && !test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part))) if (render_options.enable_frustum_culling &&
!test_aabb_frustum(frustum, get_aabb_for_part(scene.get<Transform>(obj), part)))
continue; continue;
command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128); command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128);
@ -184,11 +194,13 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
} }
void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) { void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) {
if(scene.sun_light_dirty || light.use_dynamic_shadows) { if (scene.sun_light_dirty || light.use_dynamic_shadows) {
GFXRenderPassBeginInfo info = {}; GFXRenderPassBeginInfo info = {};
info.framebuffer = scene.framebuffer; info.framebuffer = scene.framebuffer;
info.render_pass = render_pass; info.render_pass = render_pass;
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)}; info.render_area.extent = {
static_cast<uint32_t>(render_options.shadow_resolution),
static_cast<uint32_t>(render_options.shadow_resolution)};
command_buffer->set_render_pass(info); command_buffer->set_render_pass(info);
@ -211,7 +223,7 @@ void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, pris
const auto frustum = normalize_frustum(extract_frustum(projection * view)); const auto frustum = normalize_frustum(extract_frustum(projection * view));
if(light.enable_shadows) if (light.enable_shadows)
render_meshes(command_buffer, scene, realMVP, Matrix4x4(), lightPos, Light::Type::Sun, frustum, 0); render_meshes(command_buffer, scene, realMVP, Matrix4x4(), lightPos, Light::Type::Sun, frustum, 0);
scene.sun_light_dirty = false; scene.sun_light_dirty = false;
@ -221,14 +233,16 @@ void ShadowPass::render_sun(GFXCommandBuffer* command_buffer, Scene& scene, pris
} }
void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) { void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) {
if((last_spot_light + 1) == max_spot_shadows) if ((last_spot_light + 1) == max_spot_shadows)
return; return;
if(scene.spot_light_dirty[last_spot_light] || light.use_dynamic_shadows) { if (scene.spot_light_dirty[last_spot_light] || light.use_dynamic_shadows) {
GFXRenderPassBeginInfo info = {}; GFXRenderPassBeginInfo info = {};
info.framebuffer = offscreen_framebuffer; info.framebuffer = offscreen_framebuffer;
info.render_pass = cube_render_pass; info.render_pass = cube_render_pass;
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)}; info.render_area.extent = {
static_cast<uint32_t>(render_options.shadow_resolution),
static_cast<uint32_t>(render_options.shadow_resolution)};
command_buffer->set_render_pass(info); command_buffer->set_render_pass(info);
@ -244,16 +258,33 @@ void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, pri
scene.spotLightSpaces[last_spot_light] = perspective; scene.spotLightSpaces[last_spot_light] = perspective;
scene.spotLightSpaces[last_spot_light][1][1] *= -1; scene.spotLightSpaces[last_spot_light][1][1] *= -1;
scene.spotLightSpaces[last_spot_light] = scene.spotLightSpaces[last_spot_light] * inverse(scene.get<Transform>(light_object).model); scene.spotLightSpaces[last_spot_light] =
scene.spotLightSpaces[last_spot_light] * inverse(scene.get<Transform>(light_object).model);
const auto frustum = normalize_frustum(extract_frustum(perspective * inverse(scene.get<Transform>(light_object).model))); const auto frustum =
normalize_frustum(extract_frustum(perspective * inverse(scene.get<Transform>(light_object).model)));
if(light.enable_shadows) if (light.enable_shadows)
render_meshes(command_buffer, scene, realMVP, Matrix4x4(), scene.get<Transform>(light_object).get_world_position(), Light::Type::Spot, frustum, 0); render_meshes(
command_buffer,
scene,
realMVP,
Matrix4x4(),
scene.get<Transform>(light_object).get_world_position(),
Light::Type::Spot,
frustum,
0);
command_buffer->end_render_pass(); command_buffer->end_render_pass();
command_buffer->copy_texture(offscreen_depth, render_options.shadow_resolution, render_options.shadow_resolution, scene.spotLightArray, 0, last_spot_light, 0); command_buffer->copy_texture(
offscreen_depth,
render_options.shadow_resolution,
render_options.shadow_resolution,
scene.spotLightArray,
0,
last_spot_light,
0);
scene.spot_light_dirty[last_spot_light] = false; scene.spot_light_dirty[last_spot_light] = false;
} }
@ -261,26 +292,32 @@ void ShadowPass::render_spot(GFXCommandBuffer* command_buffer, Scene& scene, pri
last_spot_light++; last_spot_light++;
} }
void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) { void ShadowPass::render_point(
if(!render_options.enable_point_shadows) GFXCommandBuffer* command_buffer,
Scene& scene,
prism::Object light_object,
Light& light) {
if (!render_options.enable_point_shadows)
return; return;
if((last_point_light + 1) == max_point_shadows) if ((last_point_light + 1) == max_point_shadows)
return; return;
if(point_location_map == nullptr) if (point_location_map == nullptr)
return; return;
if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) { if (scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) {
const prism::float3 lightPos = scene.get<Transform>(light_object).get_world_position(); const prism::float3 lightPos = scene.get<Transform>(light_object).get_world_position();
(point_location_map + last_point_light)->xyz = lightPos; (point_location_map + last_point_light)->xyz = lightPos;
for(int face = 0; face < 6; face++) { for (int face = 0; face < 6; face++) {
GFXRenderPassBeginInfo info = {}; GFXRenderPassBeginInfo info = {};
info.framebuffer = offscreen_framebuffer; info.framebuffer = offscreen_framebuffer;
info.render_pass = cube_render_pass; info.render_pass = cube_render_pass;
info.render_area.extent = {static_cast<uint32_t>(render_options.shadow_resolution), static_cast<uint32_t>(render_options.shadow_resolution)}; info.render_area.extent = {
static_cast<uint32_t>(render_options.shadow_resolution),
static_cast<uint32_t>(render_options.shadow_resolution)};
command_buffer->set_render_pass(info); command_buffer->set_render_pass(info);
@ -295,11 +332,26 @@ void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, pr
const auto frustum = normalize_frustum(extract_frustum(projection * shadowTransforms[face] * model)); const auto frustum = normalize_frustum(extract_frustum(projection * shadowTransforms[face] * model));
render_meshes(command_buffer, scene, projection * shadowTransforms[face], model, lightPos, Light::Type::Point, frustum, last_point_light); render_meshes(
command_buffer,
scene,
projection * shadowTransforms[face],
model,
lightPos,
Light::Type::Point,
frustum,
last_point_light);
command_buffer->end_render_pass(); command_buffer->end_render_pass();
command_buffer->copy_texture(offscreen_color_texture, render_options.shadow_resolution, render_options.shadow_resolution, scene.pointLightArray, face, last_point_light, 0); command_buffer->copy_texture(
offscreen_color_texture,
render_options.shadow_resolution,
render_options.shadow_resolution,
scene.pointLightArray,
face,
last_point_light,
0);
} }
scene.point_light_dirty[last_point_light] = false; scene.point_light_dirty[last_point_light] = false;
@ -335,17 +387,12 @@ void ShadowPass::create_pipelines() {
pipelineInfo.shaders.vertex_constants = {point_light_max_constant}; pipelineInfo.shaders.vertex_constants = {point_light_max_constant};
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/shadow.vert")); pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/shadow.vert"));
pipelineInfo.shaders.fragment_constants = { point_light_max_constant }; pipelineInfo.shaders.fragment_constants = {point_light_max_constant};
pipelineInfo.shader_input.bindings = { pipelineInfo.shader_input.bindings = {
{0, GFXBindingType::PushConstant}, {0, GFXBindingType::PushConstant}, {1, GFXBindingType::StorageBuffer}, {2, GFXBindingType::StorageBuffer}};
{1, GFXBindingType::StorageBuffer},
{2, GFXBindingType::StorageBuffer}
};
pipelineInfo.shader_input.push_constants = { pipelineInfo.shader_input.push_constants = {{sizeof(PushConstant), 0}};
{sizeof(PushConstant), 0}
};
pipelineInfo.render_pass = render_pass; pipelineInfo.render_pass = render_pass;
@ -415,6 +462,7 @@ void ShadowPass::create_offscreen_resources() {
offscreen_framebuffer = gfx->create_framebuffer(info); offscreen_framebuffer = gfx->create_framebuffer(info);
point_location_buffer = gfx->create_buffer(nullptr, sizeof(prism::float4) * max_point_shadows, false, GFXBufferUsage::Storage); point_location_buffer =
gfx->create_buffer(nullptr, sizeof(prism::float4) * max_point_shadows, false, GFXBufferUsage::Storage);
point_location_map = reinterpret_cast<prism::float4*>(gfx->get_buffer_contents(point_location_buffer)); point_location_map = reinterpret_cast<prism::float4*>(gfx->get_buffer_contents(point_location_buffer));
} }

View file

@ -1,10 +1,10 @@
#include "smaapass.hpp" #include "smaapass.hpp"
#include "gfx_commandbuffer.hpp" #include "assertions.hpp"
#include "renderer.hpp"
#include "engine.hpp" #include "engine.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "assertions.hpp" #include "gfx_commandbuffer.hpp"
#include "renderer.hpp"
#include <AreaTex.h> #include <AreaTex.h>
#include <SearchTex.h> #include <SearchTex.h>
@ -52,7 +52,11 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) {
prism::float4 viewport; prism::float4 viewport;
} pc; } pc;
pc.viewport = prism::float4(1.0f / static_cast<float>(target.extent.width), 1.0f / static_cast<float>(target.extent.height), target.extent.width, target.extent.height); pc.viewport = prism::float4(
1.0f / static_cast<float>(target.extent.width),
1.0f / static_cast<float>(target.extent.height),
target.extent.width,
target.extent.height);
// edge // edge
{ {
@ -97,7 +101,7 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) {
void SMAAPass::create_textures() { void SMAAPass::create_textures() {
auto gfx = engine->get_gfx(); auto gfx = engine->get_gfx();
//load area image // load area image
GFXTextureCreateInfo areaInfo = {}; GFXTextureCreateInfo areaInfo = {};
areaInfo.label = "SMAA Area"; areaInfo.label = "SMAA Area";
areaInfo.width = AREATEX_WIDTH; areaInfo.width = AREATEX_WIDTH;
@ -147,15 +151,10 @@ void SMAAPass::create_pipelines() {
createInfo.render_pass = render_pass; createInfo.render_pass = render_pass;
createInfo.shader_input.push_constants = { createInfo.shader_input.push_constants = {{sizeof(prism::float4), 0}};
{sizeof(prism::float4), 0}
};
createInfo.shader_input.bindings = { createInfo.shader_input.bindings = {
{0, GFXBindingType::Texture}, {0, GFXBindingType::Texture}, {1, GFXBindingType::Texture}, {2, GFXBindingType::PushConstant}};
{1, GFXBindingType::Texture},
{2, GFXBindingType::PushConstant}
};
edge_pipeline = gfx->create_graphics_pipeline(createInfo); edge_pipeline = gfx->create_graphics_pipeline(createInfo);

View file

@ -1,10 +1,10 @@
#pragma once #pragma once
#include <variant>
#include <string>
#include <vector>
#include <string_view>
#include <optional> #include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <vector>
#include "file.hpp" #include "file.hpp"
@ -41,8 +41,11 @@ public:
class ShaderSource { class ShaderSource {
public: public:
ShaderSource() : source(std::monostate()) {} ShaderSource() : source(std::monostate()) {}
explicit ShaderSource(const std::string& source_string) : source(source_string) {} explicit ShaderSource(const std::string& source_string) : source(source_string) {}
explicit ShaderSource(const std::vector<uint32_t>& source_bytecode) : source(source_bytecode) {} explicit ShaderSource(const std::vector<uint32_t>& source_bytecode) : source(source_bytecode) {}
explicit ShaderSource(const prism::path& shader_path) : source(shader_path) {} explicit ShaderSource(const prism::path& shader_path) : source(shader_path) {}
std::variant<std::monostate, prism::path, std::string, std::vector<uint32_t>> source; std::variant<std::monostate, prism::path, std::string, std::vector<uint32_t>> source;
@ -92,7 +95,12 @@ public:
@param options Optional compilation parameters. @param options Optional compilation parameters.
@note Right now, only GLSL is supported as a source shader language. @note Right now, only GLSL is supported as a source shader language.
*/ */
std::optional<ShaderSource> compile(ShaderLanguage from_language, ShaderStage shader_stage, const ShaderSource& shader_source, ShaderLanguage to_language, CompileOptions options = CompileOptions()); std::optional<ShaderSource> compile(
ShaderLanguage from_language,
ShaderStage shader_stage,
const ShaderSource& shader_source,
ShaderLanguage to_language,
CompileOptions options = CompileOptions());
}; };
static inline ShaderCompiler shader_compiler; static inline ShaderCompiler shader_compiler;

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
const TBuiltInResource DefaultTBuiltInResource = { const TBuiltInResource DefaultTBuiltInResource = {
/* .MaxLights = */ 32, /* .MaxLights = */ 32,
/* .MaxClipPlanes = */ 6, /* .MaxClipPlanes = */ 6,
@ -96,7 +95,8 @@ const TBuiltInResource DefaultTBuiltInResource = {
/* .maxMeshViewCountNV = */ 4, /* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1, /* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ { /* .limits = */
{
/* .nonInductiveForLoops = */ 1, /* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1, /* .whileLoops = */ 1,
/* .doWhileLoops = */ 1, /* .doWhileLoops = */ 1,
@ -106,4 +106,4 @@ const TBuiltInResource DefaultTBuiltInResource = {
/* .generalSamplerIndexing = */ 1, /* .generalSamplerIndexing = */ 1,
/* .generalVariableIndexing = */ 1, /* .generalVariableIndexing = */ 1,
/* .generalConstantMatrixVectorIndexing = */ 1, /* .generalConstantMatrixVectorIndexing = */ 1,
}}; }};

View file

@ -36,10 +36,10 @@
#pragma once #pragma once
#include <vector>
#include <string>
#include <fstream>
#include <algorithm> #include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include <glslang/Public/ShaderLang.h> #include <glslang/Public/ShaderLang.h>
@ -48,19 +48,14 @@
// Can be overridden to customize. // Can be overridden to customize.
class DirStackFileIncluder : public glslang::TShader::Includer { class DirStackFileIncluder : public glslang::TShader::Includer {
public: public:
DirStackFileIncluder() : externalLocalDirectoryCount(0) { } DirStackFileIncluder() : externalLocalDirectoryCount(0) {}
IncludeResult* includeLocal(const char* headerName, IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override {
const char* includerName,
size_t inclusionDepth) override
{
return readLocalPath(headerName, includerName, (int)inclusionDepth); return readLocalPath(headerName, includerName, (int)inclusionDepth);
} }
IncludeResult* includeSystem(const char* headerName, IncludeResult*
const char* /*includerName*/, includeSystem(const char* headerName, const char* /*includerName*/, size_t /*inclusionDepth*/) override {
size_t /*inclusionDepth*/) override
{
return readSystemPath(headerName); return readSystemPath(headerName);
} }
@ -70,16 +65,14 @@ public:
// is checked. // is checked.
// - This only applies to the "local" form of #include. // - This only applies to the "local" form of #include.
// - Makes its own copy of the path. // - Makes its own copy of the path.
virtual void pushExternalLocalDirectory(const std::string& dir) virtual void pushExternalLocalDirectory(const std::string& dir) {
{
directoryStack.push_back(dir); directoryStack.push_back(dir);
externalLocalDirectoryCount = (int)directoryStack.size(); externalLocalDirectoryCount = (int)directoryStack.size();
} }
void releaseInclude(IncludeResult* result) override void releaseInclude(IncludeResult* result) override {
{
if (result != nullptr) { if (result != nullptr) {
delete [] static_cast<tUserDataElement*>(result->userData); delete[] static_cast<tUserDataElement*>(result->userData);
delete result; delete result;
} }
} }
@ -93,8 +86,7 @@ protected:
// Search for a valid "local" path based on combining the stack of include // Search for a valid "local" path based on combining the stack of include
// directories and the nominal name of the header. // directories and the nominal name of the header.
virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) {
{
// Discard popped include directories, and // Discard popped include directories, and
// initialize when at parse-time first level. // initialize when at parse-time first level.
directoryStack.resize(depth + externalLocalDirectoryCount); directoryStack.resize(depth + externalLocalDirectoryCount);
@ -117,15 +109,13 @@ protected:
// Search for a valid <system> path. // Search for a valid <system> path.
// Not implemented yet; returning nullptr signals failure to find. // Not implemented yet; returning nullptr signals failure to find.
virtual IncludeResult* readSystemPath(const char* /*headerName*/) const virtual IncludeResult* readSystemPath(const char* /*headerName*/) const {
{
return nullptr; return nullptr;
} }
// Do actual reading of the file, filling in a new include result. // Do actual reading of the file, filling in a new include result.
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const {
{ char* content = new tUserDataElement[length];
char* content = new tUserDataElement [length];
file.seekg(0, file.beg); file.seekg(0, file.beg);
file.read(content, length); file.read(content, length);
return new IncludeResult(path, content, length, content); return new IncludeResult(path, content, length, content);
@ -134,7 +124,7 @@ protected:
// If no path markers, return current working directory. // If no path markers, return current working directory.
// Otherwise, strip file name and return path leading up to it. // Otherwise, strip file name and return path leading up to it.
virtual std::string getDirectory(const std::string) const { virtual std::string getDirectory(const std::string) const {
//return file::get_domain_path(file::domain::Internal).string(); // return file::get_domain_path(file::domain::Internal).string();
return ""; return "";
} }
}; };

View file

@ -1,13 +1,13 @@
#include "shadercompiler.hpp" #include "shadercompiler.hpp"
#include <spirv_msl.hpp>
#include <SPIRV/GlslangToSpv.h> #include <SPIRV/GlslangToSpv.h>
#include <spirv_msl.hpp>
#include "log.hpp"
#include "string_utils.hpp"
#include "includer.hpp"
#include "defaultresources.hpp" #include "defaultresources.hpp"
#include "includer.hpp"
#include "log.hpp"
#include "spirv_hlsl.hpp" #include "spirv_hlsl.hpp"
#include "string_utils.hpp"
static inline std::vector<std::string> include_path; static inline std::vector<std::string> include_path;
@ -19,13 +19,16 @@ void ShaderCompiler::set_include_path(const std::string_view path) {
include_path.emplace_back(path.data()); include_path.emplace_back(path.data());
} }
std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string, const EShLanguage shader_language, const CompileOptions& options) { std::vector<uint32_t> compile_glsl_to_spv(
const std::string_view source_string,
const EShLanguage shader_language,
const CompileOptions& options) {
std::string newString = "#version 460 core\n"; std::string newString = "#version 460 core\n";
newString += "#extension GL_GOOGLE_include_directive : enable\n"; newString += "#extension GL_GOOGLE_include_directive : enable\n";
newString += "#extension GL_GOOGLE_cpp_style_line_directive : enable\n"; newString += "#extension GL_GOOGLE_cpp_style_line_directive : enable\n";
for(auto& definition : options.definitions) for (auto& definition : options.definitions)
newString += "#define " + definition + "\n"; newString += "#define " + definition + "\n";
newString += "#line 1\n"; newString += "#line 1\n";
@ -39,17 +42,14 @@ std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string,
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100 int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
shader.setEnvInput(glslang::EShSourceGlsl, shader.setEnvInput(glslang::EShSourceGlsl, shader_language, glslang::EShClientVulkan, ClientInputSemanticsVersion);
shader_language,
glslang::EShClientVulkan,
ClientInputSemanticsVersion);
// we are targeting vulkan 1.1, so that uses SPIR-V 1.3 // we are targeting vulkan 1.1, so that uses SPIR-V 1.3
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1); shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3); shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
DirStackFileIncluder file_includer; DirStackFileIncluder file_includer;
for(const auto& path : include_path) for (const auto& path : include_path)
file_includer.pushExternalLocalDirectory(path); file_includer.pushExternalLocalDirectory(path);
if (!shader.parse(&DefaultTBuiltInResource, 100, false, EShMsgDefault, file_includer)) { if (!shader.parse(&DefaultTBuiltInResource, 100, false, EShMsgDefault, file_includer)) {
prism::log("{}", shader.getInfoLog()); prism::log("{}", shader.getInfoLog());
@ -60,8 +60,9 @@ std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string,
glslang::TProgram Program; glslang::TProgram Program;
Program.addShader(&shader); Program.addShader(&shader);
if(!Program.link(EShMsgDefault)) { if (!Program.link(EShMsgDefault)) {
prism::log("Failed to link shader: {} {} {}", source_string.data(), shader.getInfoLog(), shader.getInfoDebugLog()); prism::log(
"Failed to link shader: {} {} {}", source_string.data(), shader.getInfoLog(), shader.getInfoDebugLog());
return {}; return {};
} }
@ -77,14 +78,19 @@ std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string,
return SpirV; return SpirV;
} }
std::optional<ShaderSource> ShaderCompiler::compile(const ShaderLanguage from_language, const ShaderStage shader_stage, const ShaderSource& shader_source, const ShaderLanguage to_language, CompileOptions options) { std::optional<ShaderSource> ShaderCompiler::compile(
if(from_language != ShaderLanguage::GLSL) { const ShaderLanguage from_language,
const ShaderStage shader_stage,
const ShaderSource& shader_source,
const ShaderLanguage to_language,
CompileOptions options) {
if (from_language != ShaderLanguage::GLSL) {
prism::log("Non-supported input language!"); prism::log("Non-supported input language!");
return std::nullopt; return std::nullopt;
} }
EShLanguage lang = EShLangMiss; EShLanguage lang = EShLangMiss;
switch(shader_stage) { switch (shader_stage) {
case ShaderStage::Vertex: case ShaderStage::Vertex:
lang = EShLangVertex; lang = EShLangVertex;
break; break;
@ -97,12 +103,12 @@ std::optional<ShaderSource> ShaderCompiler::compile(const ShaderLanguage from_la
} }
auto spirv = compile_glsl_to_spv(shader_source.as_string(), lang, options); auto spirv = compile_glsl_to_spv(shader_source.as_string(), lang, options);
if(spirv.empty()) { if (spirv.empty()) {
prism::log("SPIRV generation failed!"); prism::log("SPIRV generation failed!");
return std::nullopt; return std::nullopt;
} }
switch(to_language) { switch (to_language) {
case ShaderLanguage::GLSL: case ShaderLanguage::GLSL:
return ShaderSource(shader_source); return ShaderSource(shader_source);
case ShaderLanguage::SPIRV: case ShaderLanguage::SPIRV:
@ -111,7 +117,7 @@ std::optional<ShaderSource> ShaderCompiler::compile(const ShaderLanguage from_la
spirv_cross::CompilerMSL msl(std::move(spirv)); spirv_cross::CompilerMSL msl(std::move(spirv));
spirv_cross::CompilerMSL::Options opts; spirv_cross::CompilerMSL::Options opts;
if(options.is_apple_mobile) { if (options.is_apple_mobile) {
opts.platform = spirv_cross::CompilerMSL::Options::Platform::iOS; opts.platform = spirv_cross::CompilerMSL::Options::Platform::iOS;
} else { } else {
opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS; opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS;

View file

@ -6,6 +6,7 @@ namespace prism {
/// A 2D extent. /// A 2D extent.
struct Extent { struct Extent {
Extent() : width(0), height(0) {} Extent() : width(0), height(0) {}
Extent(const uint32_t width, const uint32_t height) : width(width), height(height) {} Extent(const uint32_t width, const uint32_t height) : width(width), height(height) {}
uint32_t width = 0, height = 0; uint32_t width = 0, height = 0;
@ -14,6 +15,7 @@ namespace prism {
/// A 2D offset. /// A 2D offset.
struct Offset { struct Offset {
Offset() : x(0), y(0) {} Offset() : x(0), y(0) {}
Offset(const int32_t x, const int32_t y) : x(x), y(y) {} Offset(const int32_t x, const int32_t y) : x(x), y(y) {}
int32_t x = 0, y = 0; int32_t x = 0, y = 0;
@ -22,10 +24,13 @@ namespace prism {
/// A 2D rectangle defined by a offset and an etent. /// A 2D rectangle defined by a offset and an etent.
struct Rectangle { struct Rectangle {
Rectangle() = default; Rectangle() = default;
Rectangle(const Offset offset, const Extent extent) : offset(offset), extent(extent) {} Rectangle(const Offset offset, const Extent extent) : offset(offset), extent(extent) {}
Rectangle(const int32_t x, const int32_t y, const uint32_t width, const uint32_t height) : offset(x, y), extent(width, height) {}
Rectangle(const int32_t x, const int32_t y, const uint32_t width, const uint32_t height)
: offset(x, y), extent(width, height) {}
Offset offset; Offset offset;
Extent extent; Extent extent;
}; };
} } // namespace prism

View file

@ -2,22 +2,22 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "vector.hpp"
#include "quaternion.hpp" #include "quaternion.hpp"
#include "vector.hpp"
namespace prism { namespace prism {
inline void to_json(nlohmann::json &j, const float3 &p) { inline void to_json(nlohmann::json& j, const float3& p) {
j["x"] = p.x; j["x"] = p.x;
j["y"] = p.y; j["y"] = p.y;
j["z"] = p.z; j["z"] = p.z;
} }
inline void from_json(const nlohmann::json &j, float3 &p) { inline void from_json(const nlohmann::json& j, float3& p) {
p.x = j["x"]; p.x = j["x"];
p.y = j["y"]; p.y = j["y"];
p.z = j["z"]; p.z = j["z"];
} }
} } // namespace prism
inline void to_json(nlohmann::json& j, const Quaternion& p) { inline void to_json(nlohmann::json& j, const Quaternion& p) {
j["x"] = p.x; j["x"] = p.x;

View file

@ -9,10 +9,9 @@ namespace prism {
// some stdlibs such as apple's clang fail to provide this :-/ // some stdlibs such as apple's clang fail to provide this :-/
namespace std { namespace std {
template <> template<> struct hash<prism::path> {
struct hash<prism::path> {
std::size_t operator()(const prism::path& k) const { std::size_t operator()(const prism::path& k) const {
return (std::hash<std::string>()(k.string())); return (std::hash<std::string>()(k.string()));
} }
}; };
} } // namespace std

View file

@ -3,34 +3,30 @@
#include <magic_enum.hpp> #include <magic_enum.hpp>
#include <algorithm> #include <algorithm>
#include <vector> #include <cmath>
#include <random> #include <random>
#include <unordered_map> #include <unordered_map>
#include <cmath> #include <vector>
#include "vector.hpp" #include "vector.hpp"
namespace utility { namespace utility {
template<class Enum> template<class Enum> std::string enum_to_string(const Enum e) {
std::string enum_to_string(const Enum e) {
const std::string_view name = magic_enum::enum_name(e); const std::string_view name = magic_enum::enum_name(e);
std::string s = name.data(); std::string s = name.data();
return s.substr(0, name.length()); return s.substr(0, name.length());
} }
template<class T, class F> template<class T, class F> void erase_if(std::vector<T>& vec, const F& f) {
void erase_if(std::vector<T>& vec, const F& f) {
vec.erase(std::remove_if(vec.begin(), vec.end(), f), vec.end()); vec.erase(std::remove_if(vec.begin(), vec.end(), f), vec.end());
} }
template<class T, class V> template<class T, class V> void erase(T& vec, const V& t) {
void erase(T& vec, const V& t) {
vec.erase(std::remove(vec.begin(), vec.end(), t), vec.end()); vec.erase(std::remove(vec.begin(), vec.end(), t), vec.end());
} }
template<class T> template<class T> void erase_at(std::vector<T>& vec, const int index) {
void erase_at(std::vector<T>& vec, const int index) {
vec.erase(vec.begin() + index); vec.erase(vec.begin() + index);
} }
@ -46,46 +42,60 @@ namespace utility {
return get_random(0, max); return get_random(0, max);
} }
template<class T> template<class T> inline auto get_random(const std::vector<T>& vec) {
inline auto get_random(const std::vector<T>& vec) {
return vec[get_random(static_cast<int>(vec.size() - 1))]; return vec[get_random(static_cast<int>(vec.size() - 1))];
} }
template<class T, size_t S> template<class T, size_t S> inline auto get_random(const std::array<T, S>& vec) {
inline auto get_random(const std::array<T, S>& vec) {
return vec[get_random(static_cast<int>(vec.size() - 1))]; return vec[get_random(static_cast<int>(vec.size() - 1))];
} }
template<class T, class V> template<class T, class V> inline auto get_random(const std::unordered_map<T, V>& map) {
inline auto get_random(const std::unordered_map<T, V>& map) {
const auto item = map.begin(); const auto item = map.begin();
std::advance(item, get_random(static_cast<int>(map.size() - 1))); std::advance(item, get_random(static_cast<int>(map.size() - 1)));
return item; return item;
} }
template<class T, class TIter = decltype(std::begin(std::declval<T>())), class = decltype(std::end(std::declval<T>()))> template<
constexpr auto enumerate(T&& iterable) class T,
{ class TIter = decltype(std::begin(std::declval<T>())),
class = decltype(std::end(std::declval<T>()))>
constexpr auto enumerate(T&& iterable) {
struct iterator { struct iterator {
size_t i; size_t i;
TIter iter; TIter iter;
bool operator != (const iterator & other) const { return iter != other.iter; }
void operator ++ () { ++i; ++iter; } bool operator!=(const iterator& other) const {
auto operator * () const { return std::tie(i, *iter); } return iter != other.iter;
}
void operator++() {
++i;
++iter;
}
auto operator*() const {
return std::tie(i, *iter);
}
}; };
struct iterable_wrapper { struct iterable_wrapper {
T iterable; T iterable;
auto begin() { return iterator{ 0, std::begin(iterable) }; }
auto end() { return iterator{ 0, std::end(iterable) }; }
};
return iterable_wrapper{ std::forward<T>(iterable) }; auto begin() {
return iterator{0, std::begin(iterable)};
} }
template<class T, class V> auto end() {
inline bool contains(const std::vector<T>& vec, const V& val) { return iterator{0, std::end(iterable)};
}
};
return iterable_wrapper{std::forward<T>(iterable)};
}
template<class T, class V> inline bool contains(const std::vector<T>& vec, const V& val) {
return std::count(vec.begin(), vec.end(), val); return std::count(vec.begin(), vec.end(), val);
} }
@ -101,8 +111,8 @@ namespace utility {
inline prism::float3 from_srgb_to_linear(const prism::float3 sRGB) { inline prism::float3 from_srgb_to_linear(const prism::float3 sRGB) {
prism::float3 linear = sRGB; prism::float3 linear = sRGB;
for(auto& component : linear.data) { for (auto& component : linear.data) {
if(component > 0.04045f) { if (component > 0.04045f) {
component = std::pow((component + 0.055) / (1.055), 2.4f); component = std::pow((component + 0.055) / (1.055), 2.4f);
} else if (component <= 0.04045) { } else if (component <= 0.04045) {
component /= 12.92f; component /= 12.92f;
@ -112,8 +122,7 @@ namespace utility {
return linear; return linear;
} }
template<typename T, typename F> template<typename T, typename F> inline void move_to_front(std::vector<T>& vec, F func) {
inline void move_to_front(std::vector<T>& vec, F func) {
auto result = std::find_if(vec.begin(), vec.end(), func); auto result = std::find_if(vec.begin(), vec.end(), func);
if (result != vec.end()) { if (result != vec.end()) {
auto value = *result; auto value = *result;
@ -121,4 +130,4 @@ namespace utility {
vec.insert(vec.begin(), value); vec.insert(vec.begin(), value);
} }
} }
} } // namespace utility

View file

@ -6,18 +6,19 @@ std::string remove_substring(const std::string_view string, const std::string_vi
std::string result(string); std::string result(string);
const auto substring_length = substring.length(); const auto substring_length = substring.length();
for(auto i = result.find(substring); i != std::string::npos; i = result.find(substring)) for (auto i = result.find(substring); i != std::string::npos; i = result.find(substring))
result.erase(i, substring_length); result.erase(i, substring_length);
return result; return result;
} }
std::string replace_substring(const std::string_view string, const std::string_view substring, const std::string_view replacement) { std::string
replace_substring(const std::string_view string, const std::string_view substring, const std::string_view replacement) {
std::string result(string); std::string result(string);
const auto substring_length = substring.length(); const auto substring_length = substring.length();
size_t i = 0; size_t i = 0;
while((i = result.find(substring, i)) != std::string::npos) { while ((i = result.find(substring, i)) != std::string::npos) {
result.erase(i, substring_length); result.erase(i, substring_length);
result.insert(i, replacement); result.insert(i, replacement);
i += replacement.length(); i += replacement.length();
@ -31,12 +32,13 @@ bool string_contains(const std::string_view a, const std::string_view b) {
} }
bool string_starts_with(const std::string_view haystack, const std::string_view needle) { bool string_starts_with(const std::string_view haystack, const std::string_view needle) {
return needle.length() <= haystack.length() return needle.length() <= haystack.length() && std::equal(needle.begin(), needle.end(), haystack.begin());
&& std::equal(needle.begin(), needle.end(), haystack.begin());
} }
bool is_numeric(const std::string_view string) { bool is_numeric(const std::string_view string) {
return std::find_if(string.begin(), string.end(), [](unsigned char c) { return !std::isdigit(c); }) == string.end(); return std::find_if(string.begin(), string.end(), [](unsigned char c) {
return !std::isdigit(c);
}) == string.end();
} }
std::vector<std::string> tokenize(const std::string_view string, const std::string_view& delimiters) { std::vector<std::string> tokenize(const std::string_view string, const std::string_view& delimiters) {
@ -45,12 +47,12 @@ std::vector<std::string> tokenize(const std::string_view string, const std::stri
const size_t length = string.length(); const size_t length = string.length();
size_t lastPos = 0; size_t lastPos = 0;
while(lastPos < length + 1) { while (lastPos < length + 1) {
size_t pos = string.find_first_of(delimiters, lastPos); size_t pos = string.find_first_of(delimiters, lastPos);
if(pos == std::string_view::npos) if (pos == std::string_view::npos)
pos = length; pos = length;
if(pos != lastPos) if (pos != lastPos)
tokens.emplace_back(string.data() + lastPos, pos - lastPos); tokens.emplace_back(string.data() + lastPos, pos - lastPos);
lastPos = pos + 1; lastPos = pos + 1;