Okay, reformat the rest of the engine code!
This commit is contained in:
parent
100e1d7434
commit
b00a39c474
75 changed files with 3059 additions and 2975 deletions
|
@ -11,7 +11,7 @@ add_subdirectory(shadercompiler)
|
|||
add_subdirectory(platform)
|
||||
add_subdirectory(base)
|
||||
|
||||
if(NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
||||
if (NOT ENABLE_IOS AND NOT ENABLE_TVOS)
|
||||
add_subdirectory(audio)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
endif ()
|
|
@ -5,28 +5,28 @@ target_include_directories(GFX INTERFACE public)
|
|||
target_link_libraries(GFX INTERFACE Utility ShaderCompiler)
|
||||
|
||||
add_custom_target(GFXInterface SOURCES
|
||||
public/gfx.hpp
|
||||
public/gfx_buffer.hpp
|
||||
public/gfx_pipeline.hpp
|
||||
public/gfx_commandbuffer.hpp
|
||||
public/gfx_texture.hpp
|
||||
public/gfx_framebuffer.hpp
|
||||
public/gfx_renderpass.hpp
|
||||
public/gfx_object.hpp
|
||||
public/gfx_sampler.hpp
|
||||
public/gfx_context.hpp)
|
||||
public/gfx.hpp
|
||||
public/gfx_buffer.hpp
|
||||
public/gfx_pipeline.hpp
|
||||
public/gfx_commandbuffer.hpp
|
||||
public/gfx_texture.hpp
|
||||
public/gfx_framebuffer.hpp
|
||||
public/gfx_renderpass.hpp
|
||||
public/gfx_object.hpp
|
||||
public/gfx_sampler.hpp
|
||||
public/gfx_context.hpp)
|
||||
set_target_properties(GFXInterface PROPERTIES CMAKE_FOLDER "GFX")
|
||||
|
||||
add_subdirectory(dummy)
|
||||
|
||||
if(ENABLE_DX12)
|
||||
if (ENABLE_DX12)
|
||||
add_subdirectory(dx12)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(ENABLE_METAL)
|
||||
if (ENABLE_METAL)
|
||||
add_subdirectory(metal)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(ENABLE_VULKAN)
|
||||
add_subdirectory(vulkan)
|
||||
endif()
|
||||
if (ENABLE_VULKAN)
|
||||
add_subdirectory(vulkan)
|
||||
endif ()
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <wrl.h>
|
||||
|
||||
#include "gfx.hpp"
|
||||
|
@ -11,11 +11,20 @@ using namespace Microsoft::WRL;
|
|||
|
||||
class gfx_dx12 : public GFX {
|
||||
public:
|
||||
bool is_supported() override { return true; }
|
||||
ShaderLanguage accepted_shader_language() override { return ShaderLanguage::HLSL; }
|
||||
GFXContext required_context() override { return GFXContext::DirectX; }
|
||||
bool is_supported() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderLanguage accepted_shader_language() override {
|
||||
return ShaderLanguage::HLSL;
|
||||
}
|
||||
|
||||
GFXContext required_context() override {
|
||||
return GFXContext::DirectX;
|
||||
}
|
||||
|
||||
bool initialize(const GFXCreateInfo& info) override;
|
||||
|
||||
|
||||
const char* get_name() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "gfx_dx12.hpp"
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
#include <wrl.h>
|
||||
#include <codecvt>
|
||||
#include <wrl.h>
|
||||
|
||||
// from https://stackoverflow.com/a/18374698
|
||||
std::string ws2s(const std::wstring& wstr) {
|
||||
|
@ -18,7 +18,7 @@ std::string ws2s(const std::wstring& wstr) {
|
|||
bool gfx_dx12::initialize(const GFXCreateInfo& info) {
|
||||
get_device();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void gfx_dx12::get_device() {
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
set(SRC
|
||||
include/gfx_metal.hpp
|
||||
|
||||
src/gfx_metal.cpp
|
||||
src/gfx_metal_buffer.hpp
|
||||
src/gfx_metal_pipeline.hpp
|
||||
src/gfx_metal_texture.hpp
|
||||
src/gfx_metal_framebuffer.hpp
|
||||
src/gfx_metal_renderpass.hpp
|
||||
src/gfx_metal_sampler.hpp)
|
||||
include/gfx_metal.hpp
|
||||
|
||||
src/gfx_metal.cpp
|
||||
src/gfx_metal_buffer.hpp
|
||||
src/gfx_metal_pipeline.hpp
|
||||
src/gfx_metal_texture.hpp
|
||||
src/gfx_metal_framebuffer.hpp
|
||||
src/gfx_metal_renderpass.hpp
|
||||
src/gfx_metal_sampler.hpp)
|
||||
|
||||
add_library(GFXMetal STATIC
|
||||
${SRC})
|
||||
${SRC})
|
||||
|
||||
target_link_libraries(GFXMetal PUBLIC
|
||||
GFX
|
||||
Core
|
||||
Log
|
||||
metal-cpp)
|
||||
GFX
|
||||
Core
|
||||
Log
|
||||
metal-cpp)
|
||||
target_include_directories(GFXMetal PUBLIC
|
||||
include
|
||||
PRIVATE
|
||||
src)
|
||||
include
|
||||
PRIVATE
|
||||
src)
|
||||
set_engine_properties(GFXMetal)
|
||||
|
|
|
@ -8,38 +8,46 @@
|
|||
class GFXMetal : public GFX {
|
||||
public:
|
||||
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;
|
||||
|
||||
|
||||
bool supports_feature(GFXFeature feature) 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;
|
||||
|
||||
// buffer operations
|
||||
GFXBuffer* create_buffer(void* data, GFXSize size, bool is_dynamic, GFXBufferUsage usage) override;
|
||||
void copy_buffer(GFXBuffer* buffer, void* data, GFXSize offset, GFXSize size) override;
|
||||
|
||||
|
||||
void* get_buffer_contents(GFXBuffer* buffer) override;
|
||||
|
||||
|
||||
// texture operations
|
||||
GFXTexture* create_texture(const GFXTextureCreateInfo& info) override;
|
||||
void copy_texture(GFXTexture* texture, void* data, GFXSize size) override;
|
||||
void copy_texture(GFXTexture* from, GFXTexture* to) override;
|
||||
void copy_texture(GFXTexture* from, GFXBuffer* to) override;
|
||||
|
||||
|
||||
// sampler opeations
|
||||
GFXSampler* create_sampler(const GFXSamplerCreateInfo& info) override;
|
||||
|
||||
// framebuffer operations
|
||||
GFXFramebuffer* create_framebuffer(const GFXFramebufferCreateInfo& info) override;
|
||||
|
||||
|
||||
// render pass operations
|
||||
GFXRenderPass* create_render_pass(const GFXRenderPassCreateInfo& info) override;
|
||||
|
||||
|
||||
// pipeline operations
|
||||
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
||||
GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override;
|
||||
|
@ -47,23 +55,23 @@ public:
|
|||
GFXSize get_alignment(GFXSize size) override;
|
||||
|
||||
GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) override;
|
||||
|
||||
|
||||
void submit(GFXCommandBuffer* command_buffer, platform::window_ptr window) override;
|
||||
|
||||
|
||||
private:
|
||||
struct NativeMTLView {
|
||||
platform::window_ptr identifier = nullptr;
|
||||
MTL::PixelFormat format;
|
||||
};
|
||||
|
||||
|
||||
std::vector<NativeMTLView*> nativeViews;
|
||||
|
||||
|
||||
NativeMTLView* getNativeView(platform::window_ptr identifier) {
|
||||
for(auto& view : nativeViews) {
|
||||
if(view->identifier == identifier)
|
||||
for (auto& view : nativeViews) {
|
||||
if (view->identifier == identifier)
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,10 +7,10 @@
|
|||
class GFXMetalPipeline : public GFXPipeline {
|
||||
public:
|
||||
std::string label;
|
||||
|
||||
|
||||
MTL::RenderPipelineState* handle = nullptr;
|
||||
MTL::ComputePipelineState* compute_handle = nullptr;
|
||||
|
||||
|
||||
MTL::Size threadGroupSize;
|
||||
|
||||
MTL::DepthStencilState* depthStencil = nullptr;
|
||||
|
@ -22,11 +22,11 @@ public:
|
|||
struct VertexStride {
|
||||
int location, stride;
|
||||
};
|
||||
|
||||
|
||||
std::vector<VertexStride> vertexStrides;
|
||||
|
||||
|
||||
int pushConstantSize = 0;
|
||||
int pushConstantIndex = 0;
|
||||
|
||||
|
||||
bool renderWire = false;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ public:
|
|||
|
||||
int array_length = 1;
|
||||
bool is_cubemap = false;
|
||||
|
||||
|
||||
MTL::PixelFormat format;
|
||||
MTL::SamplerState* sampler;
|
||||
};
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "shadercompiler.hpp"
|
||||
#include "platform.hpp"
|
||||
#include "gfx_context.hpp"
|
||||
#include "platform.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
|
||||
class GFXBuffer;
|
||||
class GFXPipeline;
|
||||
|
@ -57,13 +57,13 @@ inline GFXTextureUsage operator&(const GFXTextureUsage a, const GFXTextureUsage
|
|||
}
|
||||
|
||||
enum class GFXBufferUsage : int {
|
||||
Storage,
|
||||
Vertex,
|
||||
Index
|
||||
Storage,
|
||||
Vertex,
|
||||
Index
|
||||
};
|
||||
|
||||
enum class GFXBlendFactor : int {
|
||||
One,
|
||||
One,
|
||||
Zero,
|
||||
SrcColor,
|
||||
DstColor,
|
||||
|
@ -149,7 +149,7 @@ struct GFXShaderConstant {
|
|||
enum class Type {
|
||||
Integer
|
||||
} type = Type::Integer;
|
||||
|
||||
|
||||
union {
|
||||
int value = 0;
|
||||
};
|
||||
|
@ -159,10 +159,10 @@ using GFXShaderConstants = std::vector<GFXShaderConstant>;
|
|||
|
||||
struct GFXGraphicsPipelineCreateInfo {
|
||||
std::string label; // only used for debug
|
||||
|
||||
|
||||
struct Shaders {
|
||||
ShaderSource vertex_src, fragment_src;
|
||||
|
||||
|
||||
GFXShaderConstants vertex_constants, fragment_constants;
|
||||
} shaders;
|
||||
|
||||
|
@ -209,10 +209,10 @@ struct GFXComputePipelineCreateInfo {
|
|||
|
||||
struct ShaderBindings {
|
||||
std::vector<GFXPushConstant> push_constants;
|
||||
|
||||
|
||||
std::vector<GFXShaderBinding> bindings;
|
||||
} shader_input;
|
||||
|
||||
|
||||
// TODO: extract this from the shader instead of hardcoding it twice (once in GLSL, and now here)
|
||||
int workgroup_size_x = 1, workgroup_size_y = 1, workgroup_size_z = 1;
|
||||
};
|
||||
|
@ -220,7 +220,7 @@ struct GFXComputePipelineCreateInfo {
|
|||
struct GFXFramebufferCreateInfo {
|
||||
std::string label;
|
||||
|
||||
GFXRenderPass* render_pass;
|
||||
GFXRenderPass* render_pass;
|
||||
std::vector<GFXTexture*> attachments;
|
||||
};
|
||||
|
||||
|
@ -228,7 +228,7 @@ struct GFXRenderPassCreateInfo {
|
|||
std::string label;
|
||||
|
||||
std::vector<GFXPixelFormat> attachments;
|
||||
|
||||
|
||||
bool will_use_in_shader = false;
|
||||
};
|
||||
|
||||
|
@ -263,7 +263,7 @@ struct GFXTextureCreateInfo {
|
|||
GFXTextureUsage usage;
|
||||
int array_length = 1;
|
||||
int mip_count = 1;
|
||||
|
||||
|
||||
// sampler
|
||||
GFXFilter min_filter = GFXFilter::Linear, mag_filter = GFXFilter::Linear;
|
||||
SamplingMode samplingMode = SamplingMode::Repeat;
|
||||
|
@ -292,70 +292,113 @@ enum class GFXFeature {
|
|||
|
||||
class GFX {
|
||||
public:
|
||||
// check for runtime support
|
||||
virtual bool is_supported() { 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; }
|
||||
// check for runtime support
|
||||
virtual bool is_supported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to initialize
|
||||
virtual bool initialize([[maybe_unused]] const GFXCreateInfo& createInfo) { 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
|
||||
virtual bool initialize([[maybe_unused]] const GFXCreateInfo& createInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void initialize_view(
|
||||
[[maybe_unused]] void* native_handle,
|
||||
[[maybe_unused]] const platform::window_ptr identifier,
|
||||
[[maybe_unused]] const uint32_t width,
|
||||
[[maybe_unused]] const uint32_t height) {}
|
||||
|
||||
virtual void recreate_view(
|
||||
[[maybe_unused]] const platform::window_ptr identifier,
|
||||
[[maybe_unused]] const uint32_t width,
|
||||
[[maybe_unused]] const uint32_t height) {}
|
||||
|
||||
virtual void initialize_view([[maybe_unused]] void* native_handle,
|
||||
[[maybe_unused]] const platform::window_ptr identifier,
|
||||
[[maybe_unused]] const uint32_t width,
|
||||
[[maybe_unused]] const uint32_t height) {}
|
||||
|
||||
virtual void recreate_view([[maybe_unused]] const platform::window_ptr identifier,
|
||||
[[maybe_unused]] const uint32_t width,
|
||||
[[maybe_unused]] const uint32_t height) {}
|
||||
|
||||
virtual void remove_view([[maybe_unused]] const platform::window_ptr identifier) {}
|
||||
|
||||
// buffer operations
|
||||
virtual GFXBuffer* create_buffer([[maybe_unused]] void* data,
|
||||
[[maybe_unused]] const GFXSize size,
|
||||
[[maybe_unused]] const bool is_dynamic,
|
||||
[[maybe_unused]] const GFXBufferUsage usage) { return nullptr; }
|
||||
virtual void copy_buffer([[maybe_unused]] GFXBuffer* buffer,
|
||||
[[maybe_unused]] void* data,
|
||||
[[maybe_unused]] const GFXSize offset,
|
||||
[[maybe_unused]] const GFXSize size) { }
|
||||
virtual GFXBuffer* create_buffer(
|
||||
[[maybe_unused]] void* data,
|
||||
[[maybe_unused]] const GFXSize size,
|
||||
[[maybe_unused]] const bool is_dynamic,
|
||||
[[maybe_unused]] const GFXBufferUsage usage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void* get_buffer_contents([[maybe_unused]] GFXBuffer* buffer) { return nullptr; }
|
||||
virtual void release_buffer_contents([[maybe_unused]] GFXBuffer* buffer,
|
||||
[[maybe_unused]] void* handle) {}
|
||||
virtual void copy_buffer(
|
||||
[[maybe_unused]] GFXBuffer* buffer,
|
||||
[[maybe_unused]] void* data,
|
||||
[[maybe_unused]] const GFXSize offset,
|
||||
[[maybe_unused]] const GFXSize size) {}
|
||||
|
||||
virtual void* get_buffer_contents([[maybe_unused]] GFXBuffer* buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void release_buffer_contents([[maybe_unused]] GFXBuffer* buffer, [[maybe_unused]] void* handle) {}
|
||||
|
||||
// texture operations
|
||||
virtual GFXTexture* create_texture([[maybe_unused]] const GFXTextureCreateInfo& info) { return nullptr; }
|
||||
virtual void copy_texture([[maybe_unused]] GFXTexture* texture,
|
||||
[[maybe_unused]] void* data,
|
||||
[[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]] GFXBuffer* to) {}
|
||||
|
||||
virtual GFXTexture* create_texture([[maybe_unused]] const GFXTextureCreateInfo& info) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void copy_texture(
|
||||
[[maybe_unused]] GFXTexture* texture,
|
||||
[[maybe_unused]] void* data,
|
||||
[[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]] GFXBuffer* to) {}
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
virtual GFXPipeline* create_graphics_pipeline([[maybe_unused]] const GFXGraphicsPipelineCreateInfo& info) { return nullptr; }
|
||||
virtual GFXPipeline* create_compute_pipeline([[maybe_unused]] const GFXComputePipelineCreateInfo& info) { return nullptr; }
|
||||
virtual GFXPipeline* create_graphics_pipeline([[maybe_unused]] const GFXGraphicsPipelineCreateInfo& info) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual GFXPipeline* create_compute_pipeline([[maybe_unused]] const GFXComputePipelineCreateInfo& info) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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 void submit([[maybe_unused]] GFXCommandBuffer* command_buffer,
|
||||
[[maybe_unused]] const platform::window_ptr window) {}
|
||||
virtual GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void
|
||||
submit([[maybe_unused]] GFXCommandBuffer* command_buffer, [[maybe_unused]] const platform::window_ptr window) {}
|
||||
};
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
|
||||
class GFXBuffer : public GFXObject {
|
||||
public:
|
||||
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
|
@ -17,9 +17,9 @@ struct GFXRenderPassBeginInfo {
|
|||
struct ClearColor {
|
||||
float r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f;
|
||||
} clear_color;
|
||||
|
||||
|
||||
prism::Rectangle render_area;
|
||||
|
||||
|
||||
GFXRenderPass* render_pass = nullptr;
|
||||
GFXFramebuffer* framebuffer = nullptr;
|
||||
};
|
||||
|
@ -66,58 +66,58 @@ enum class GFXCommandType {
|
|||
|
||||
struct GFXDrawCommand {
|
||||
GFXCommandType type = GFXCommandType::Invalid;
|
||||
|
||||
|
||||
struct CommandData {
|
||||
GFXRenderPassBeginInfo set_render_pass;
|
||||
|
||||
|
||||
struct SetGraphicsPipelineData {
|
||||
GFXPipeline* pipeline = nullptr;
|
||||
} set_graphics_pipeline;
|
||||
|
||||
|
||||
struct SetComputePipelineData {
|
||||
GFXPipeline* pipeline = nullptr;
|
||||
} set_compute_pipeline;
|
||||
|
||||
|
||||
struct SetVertexData {
|
||||
GFXBuffer* buffer = nullptr;
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
} set_vertex_buffer;
|
||||
|
||||
|
||||
struct SetIndexData {
|
||||
GFXBuffer* buffer = nullptr;
|
||||
IndexType index_type = IndexType::UINT32;
|
||||
IndexType index_type = IndexType::UINT32;
|
||||
} set_index_buffer;
|
||||
|
||||
|
||||
struct SetPushData {
|
||||
std::vector<unsigned char> bytes;
|
||||
size_t size = 0;
|
||||
} set_push_constant;
|
||||
|
||||
|
||||
struct BindShaderData {
|
||||
GFXBuffer* buffer = nullptr;
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
int size = 0;
|
||||
} bind_shader_buffer;
|
||||
|
||||
|
||||
struct BindTextureData {
|
||||
GFXTexture* texture = nullptr;
|
||||
int index = 0;
|
||||
} bind_texture;
|
||||
|
||||
|
||||
struct BindSamplerData {
|
||||
GFXSampler* sampler = nullptr;
|
||||
int index = 0;
|
||||
} bind_sampler;
|
||||
|
||||
|
||||
struct DrawData {
|
||||
uint32_t vertex_offset = 0;
|
||||
uint32_t vertex_count = 0;
|
||||
uint32_t base_instance = 0;
|
||||
uint32_t instance_count = 0;
|
||||
} draw;
|
||||
|
||||
|
||||
struct DrawIndexedData {
|
||||
uint32_t index_count = 0;
|
||||
uint32_t first_index = 0;
|
||||
|
@ -126,40 +126,40 @@ struct GFXDrawCommand {
|
|||
} draw_indexed;
|
||||
|
||||
struct CopyTextureData {
|
||||
GFXTexture* src = nullptr, *dst = nullptr;
|
||||
GFXTexture *src = nullptr, *dst = nullptr;
|
||||
int width = 0, height = 0;
|
||||
int to_slice = 0;
|
||||
int to_layer = 0;
|
||||
int to_level = 0;
|
||||
} copy_texture;
|
||||
|
||||
|
||||
struct SetViewportData {
|
||||
Viewport viewport;
|
||||
} set_viewport;
|
||||
|
||||
|
||||
struct SetScissorData {
|
||||
prism::Rectangle rect;
|
||||
} set_scissor;
|
||||
|
||||
|
||||
struct GenerateMipmapData {
|
||||
GFXTexture* texture = nullptr;
|
||||
int mip_count = 0;
|
||||
} generate_mipmaps;
|
||||
|
||||
|
||||
struct SetDepthBiasData {
|
||||
float constant = 0.0f;
|
||||
float clamp = 0.0f;
|
||||
float slope_factor = 0.0f;
|
||||
} set_depth_bias;
|
||||
|
||||
|
||||
struct PushGroupData {
|
||||
std::string_view name;
|
||||
} push_group;
|
||||
|
||||
|
||||
struct InsertLabelData {
|
||||
std::string_view name;
|
||||
} insert_label;
|
||||
|
||||
|
||||
struct DispatchData {
|
||||
uint32_t group_count_x = 0, group_count_y = 0, group_count_z = 0;
|
||||
} dispatch;
|
||||
|
@ -172,56 +172,56 @@ public:
|
|||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetRenderPass;
|
||||
command.data.set_render_pass = info;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_graphics_pipeline(GFXPipeline* pipeline) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetGraphicsPipeline;
|
||||
command.data.set_graphics_pipeline.pipeline = pipeline;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_compute_pipeline(GFXPipeline* pipeline) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetComputePipeline;
|
||||
command.data.set_compute_pipeline.pipeline = pipeline;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_vertex_buffer(GFXBuffer* buffer, int offset, int index) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetVertexBuffer;
|
||||
command.data.set_vertex_buffer.buffer = buffer;
|
||||
command.data.set_vertex_buffer.offset = offset;
|
||||
command.data.set_vertex_buffer.index = index;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_index_buffer(GFXBuffer* buffer, IndexType indexType) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetIndexBuffer;
|
||||
command.data.set_index_buffer.buffer = buffer;
|
||||
command.data.set_index_buffer.index_type = indexType;
|
||||
|
||||
command.data.set_index_buffer.index_type = indexType;
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_push_constant(const void* data, const size_t size) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetPushConstant;
|
||||
command.data.set_push_constant.size = size;
|
||||
command.data.set_push_constant.bytes.resize(size);
|
||||
|
||||
|
||||
memcpy(command.data.set_push_constant.bytes.data(), data, size);
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void bind_shader_buffer(GFXBuffer* buffer, int offset, int index, int size) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::BindShaderBuffer;
|
||||
|
@ -230,58 +230,63 @@ public:
|
|||
command.data.bind_shader_buffer.index = index;
|
||||
command.data.bind_shader_buffer.size = size;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void bind_texture(GFXTexture* texture, int index) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::BindTexture;
|
||||
command.data.bind_texture.texture = texture;
|
||||
command.data.bind_texture.index = index;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void bind_sampler(GFXSampler* sampler, const int index) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::BindSampler;
|
||||
command.data.bind_sampler.sampler = sampler;
|
||||
command.data.bind_sampler.index = index;
|
||||
|
||||
|
||||
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;
|
||||
command.type = GFXCommandType::Draw;
|
||||
command.data.draw.vertex_offset = offset;
|
||||
command.data.draw.vertex_count = count;
|
||||
command.data.draw.base_instance = instance_base;
|
||||
command.data.draw.instance_count = instance_count;
|
||||
|
||||
|
||||
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;
|
||||
command.type = GFXCommandType::DrawIndexed;
|
||||
command.data.draw_indexed.vertex_offset = vertexOffset;
|
||||
command.data.draw_indexed.first_index = firstIndex;
|
||||
command.data.draw_indexed.index_count = indexCount;
|
||||
command.data.draw_indexed.base_instance = base_instance;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void memory_barrier() {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::MemoryBarrier;
|
||||
|
||||
|
||||
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;
|
||||
command.type = GFXCommandType::CopyTexture;
|
||||
command.data.copy_texture.src = src;
|
||||
|
@ -291,18 +296,18 @@ public:
|
|||
command.data.copy_texture.to_slice = to_slice;
|
||||
command.data.copy_texture.to_layer = to_layer;
|
||||
command.data.copy_texture.to_level = to_level;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_viewport(Viewport viewport) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetViewport;
|
||||
command.data.set_viewport.viewport = viewport;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_scissor(const prism::Rectangle rect) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetScissor;
|
||||
|
@ -310,65 +315,65 @@ public:
|
|||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void generate_mipmaps(GFXTexture* texture, int mip_count) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::GenerateMipmaps;
|
||||
command.data.generate_mipmaps.texture = texture;
|
||||
command.data.generate_mipmaps.mip_count = mip_count;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void set_depth_bias(const float constant, const float clamp, const float slope) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::SetDepthBias;
|
||||
command.data.set_depth_bias.constant = constant;
|
||||
command.data.set_depth_bias.clamp = clamp;
|
||||
command.data.set_depth_bias.slope_factor = slope;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void push_group(const std::string_view name) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::PushGroup;
|
||||
command.data.push_group.name = name;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void pop_group() {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::PopGroup;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void insert_label(const std::string_view name) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::InsertLabel;
|
||||
command.data.insert_label.name = name;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void dispatch(const uint32_t group_count_x, const uint32_t group_count_y, const uint32_t group_count_z) {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::Dispatch;
|
||||
command.data.dispatch.group_count_x = group_count_x;
|
||||
command.data.dispatch.group_count_y = group_count_y;
|
||||
command.data.dispatch.group_count_z = group_count_z;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
void end_render_pass() {
|
||||
GFXDrawCommand command;
|
||||
command.type = GFXCommandType::EndRenderPass;
|
||||
|
||||
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
|
||||
std::vector<GFXDrawCommand> commands;
|
||||
};
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
|
||||
class GFXFramebuffer : public GFXObject {
|
||||
public:
|
||||
|
||||
};
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
|
||||
class GFXRenderPass : public GFXObject {
|
||||
public:
|
||||
|
||||
};
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
|
||||
class GFXSampler : public GFXObject {
|
||||
public:
|
||||
|
||||
};
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
set(HEADERS
|
||||
include/gfx_vulkan.hpp
|
||||
src/gfx_vulkan_buffer.hpp
|
||||
src/gfx_vulkan_pipeline.hpp
|
||||
src/gfx_vulkan_texture.hpp
|
||||
src/gfx_vulkan_framebuffer.hpp
|
||||
src/gfx_vulkan_renderpass.hpp
|
||||
src/gfx_vulkan_commandbuffer.hpp)
|
||||
include/gfx_vulkan.hpp
|
||||
src/gfx_vulkan_buffer.hpp
|
||||
src/gfx_vulkan_pipeline.hpp
|
||||
src/gfx_vulkan_texture.hpp
|
||||
src/gfx_vulkan_framebuffer.hpp
|
||||
src/gfx_vulkan_renderpass.hpp
|
||||
src/gfx_vulkan_commandbuffer.hpp)
|
||||
|
||||
add_library(GFXVulkan STATIC
|
||||
src/gfx_vulkan.cpp
|
||||
${HEADERS})
|
||||
src/gfx_vulkan.cpp
|
||||
${HEADERS})
|
||||
|
||||
target_link_libraries(GFXVulkan PUBLIC
|
||||
GFX
|
||||
Vulkan::Vulkan
|
||||
Core
|
||||
Log)
|
||||
GFX
|
||||
Vulkan::Vulkan
|
||||
Core
|
||||
Log)
|
||||
target_include_directories(GFXVulkan PUBLIC
|
||||
include
|
||||
PRIVATE
|
||||
src)
|
||||
include
|
||||
PRIVATE
|
||||
src)
|
||||
set_target_properties(GFXVulkan PROPERTIES
|
||||
CXX_STANDARD 17)
|
||||
CXX_STANDARD 17)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <map>
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "gfx.hpp"
|
||||
#include "gfx_vulkan_constants.hpp"
|
||||
|
@ -12,23 +12,23 @@ class GFXVulkanCommandBuffer;
|
|||
|
||||
struct NativeSurface {
|
||||
platform::window_ptr identifier = nullptr;
|
||||
|
||||
|
||||
uint32_t surfaceWidth = -1, surfaceHeight = -1;
|
||||
|
||||
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
std::vector<VkFence> inFlightFences;
|
||||
size_t currentFrame = 0;
|
||||
|
||||
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
|
||||
VkExtent2D swapchainExtent = {};
|
||||
|
||||
|
||||
std::vector<VkImage> swapchainImages;
|
||||
std::vector<VkImageView> swapchainImageViews;
|
||||
|
||||
|
||||
VkRenderPass swapchainRenderPass = VK_NULL_HANDLE;
|
||||
|
||||
|
||||
std::vector<VkFramebuffer> swapchainFramebuffers;
|
||||
std::vector<GFXVulkanCommandBuffer*> gfx_command_buffers;
|
||||
};
|
||||
|
@ -37,17 +37,27 @@ class GFXVulkanPipeline;
|
|||
|
||||
class GFXVulkan : public GFX {
|
||||
public:
|
||||
bool is_supported() override { return true; }
|
||||
ShaderLanguage accepted_shader_language() override { return ShaderLanguage::SPIRV; }
|
||||
GFXContext required_context() override { return GFXContext::Vulkan; }
|
||||
const char* get_name() override;
|
||||
bool is_supported() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderLanguage accepted_shader_language() override {
|
||||
return ShaderLanguage::SPIRV;
|
||||
}
|
||||
|
||||
GFXContext required_context() override {
|
||||
return GFXContext::Vulkan;
|
||||
}
|
||||
|
||||
const char* get_name() override;
|
||||
|
||||
bool supports_feature(GFXFeature feature) 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 recreate_view(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;
|
||||
|
||||
// buffer operations
|
||||
GFXBuffer* create_buffer(void* data, GFXSize size, bool dynamic_data, GFXBufferUsage usage) override;
|
||||
|
@ -62,73 +72,80 @@ public:
|
|||
void copy_texture(GFXTexture* from, GFXTexture* to) override;
|
||||
void copy_texture(GFXTexture* from, GFXBuffer* to) override;
|
||||
|
||||
// sampler operations
|
||||
GFXSampler* create_sampler(const GFXSamplerCreateInfo& info) override;
|
||||
// sampler operations
|
||||
GFXSampler* create_sampler(const GFXSamplerCreateInfo& info) override;
|
||||
|
||||
// framebuffer operations
|
||||
GFXFramebuffer* create_framebuffer(const GFXFramebufferCreateInfo& info) override;
|
||||
|
||||
// render pass operations
|
||||
GFXRenderPass* create_render_pass(const GFXRenderPassCreateInfo& info) override;
|
||||
// render pass operations
|
||||
GFXRenderPass* create_render_pass(const GFXRenderPassCreateInfo& info) override;
|
||||
|
||||
// pipeline operations
|
||||
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
||||
GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override;
|
||||
|
||||
// misc operations
|
||||
GFXSize get_alignment(GFXSize size) override;
|
||||
GFXSize get_alignment(GFXSize size) override;
|
||||
|
||||
GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use) override;
|
||||
|
||||
void submit(GFXCommandBuffer* command_buffer, platform::window_ptr identifier) override;
|
||||
|
||||
private:
|
||||
void createInstance(std::vector<const char*> layers, std::vector<const char*> extensions);
|
||||
void createLogicalDevice(std::vector<const char*> extensions);
|
||||
void createSwapchain(NativeSurface* native_surface, VkSwapchainKHR oldSwapchain = VK_NULL_HANDLE);
|
||||
void createDescriptorPool();
|
||||
void createInstance(std::vector<const char*> layers, std::vector<const char*> extensions);
|
||||
void createLogicalDevice(std::vector<const char*> extensions);
|
||||
void createSwapchain(NativeSurface* native_surface, VkSwapchainKHR oldSwapchain = VK_NULL_HANDLE);
|
||||
void createDescriptorPool();
|
||||
void createSyncPrimitives(NativeSurface* native_surface);
|
||||
|
||||
// dynamic descriptor sets
|
||||
void resetDescriptorState();
|
||||
void cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSetLayout layout);
|
||||
// dynamic descriptor sets
|
||||
void resetDescriptorState();
|
||||
void cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSetLayout layout);
|
||||
uint64_t getDescriptorHash(GFXVulkanPipeline* pipeline);
|
||||
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
void transitionImageLayout(VkImage image, VkFormat format, VkImageAspectFlags aspect, VkImageSubresourceRange range, VkImageLayout oldLayout, VkImageLayout newLayout);
|
||||
void inlineTransitionImageLayout(VkCommandBuffer command_buffer,
|
||||
VkImage image,
|
||||
VkFormat format,
|
||||
VkImageAspectFlags aspect,
|
||||
VkImageSubresourceRange range,
|
||||
VkImageLayout oldLayout,
|
||||
VkImageLayout newLayout,
|
||||
VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
VkShaderModule createShaderModule(const uint32_t* code, int length);
|
||||
VkCommandBuffer beginSingleTimeCommands();
|
||||
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
void transitionImageLayout(
|
||||
VkImage image,
|
||||
VkFormat format,
|
||||
VkImageAspectFlags aspect,
|
||||
VkImageSubresourceRange range,
|
||||
VkImageLayout oldLayout,
|
||||
VkImageLayout newLayout);
|
||||
void inlineTransitionImageLayout(
|
||||
VkCommandBuffer command_buffer,
|
||||
VkImage image,
|
||||
VkFormat format,
|
||||
VkImageAspectFlags aspect,
|
||||
VkImageSubresourceRange range,
|
||||
VkImageLayout oldLayout,
|
||||
VkImageLayout newLayout,
|
||||
VkPipelineStageFlags src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
VkShaderModule createShaderModule(const uint32_t* code, int length);
|
||||
VkCommandBuffer beginSingleTimeCommands();
|
||||
void endSingleTimeCommands(VkCommandBuffer commandBuffer);
|
||||
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
|
||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<NativeSurface*> native_surfaces;
|
||||
|
||||
struct BoundShaderBuffer {
|
||||
GFXBuffer* buffer = nullptr;
|
||||
VkDeviceSize size = 0, offset = 0;
|
||||
};
|
||||
struct BoundShaderBuffer {
|
||||
GFXBuffer* buffer = nullptr;
|
||||
VkDeviceSize size = 0, offset = 0;
|
||||
};
|
||||
|
||||
std::array<BoundShaderBuffer, 25> boundShaderBuffers;
|
||||
std::array<GFXTexture*, 25> boundTextures;
|
||||
std::array<GFXSampler*, 25> boundSamplers;
|
||||
std::array<BoundShaderBuffer, 25> boundShaderBuffers;
|
||||
std::array<GFXTexture*, 25> boundTextures;
|
||||
std::array<GFXSampler*, 25> boundSamplers;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@ class GFXVulkanBuffer : public GFXBuffer {
|
|||
public:
|
||||
VkBuffer handle = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
|
||||
VkDeviceSize size = 0;
|
||||
|
||||
VkDeviceSize size = 0;
|
||||
uint32_t frame_index = 0;
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
class GFXVulkanFramebuffer : public GFXFramebuffer {
|
||||
public:
|
||||
VkFramebuffer handle = VK_NULL_HANDLE;
|
||||
|
||||
VkFramebuffer handle = VK_NULL_HANDLE;
|
||||
|
||||
int width = 0, height = 0;
|
||||
};
|
||||
|
|
|
@ -8,16 +8,16 @@ class GFXVulkanTexture;
|
|||
|
||||
class GFXVulkanPipeline : public GFXPipeline {
|
||||
public:
|
||||
std::string label;
|
||||
std::string label;
|
||||
|
||||
VkPipeline handle = VK_NULL_HANDLE;
|
||||
VkPipelineLayout layout = VK_NULL_HANDLE;
|
||||
VkPipeline handle = VK_NULL_HANDLE;
|
||||
VkPipelineLayout layout = VK_NULL_HANDLE;
|
||||
|
||||
VkDescriptorSetLayout descriptorLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout descriptorLayout = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<int> bindings_marked_as_normal_images;
|
||||
std::vector<int> bindings_marked_as_storage_images;
|
||||
std::vector<int> bindings_marked_as_sampled_images;
|
||||
std::vector<int> bindings_marked_as_sampled_images;
|
||||
|
||||
// dynamic descriptor sets
|
||||
std::map<uint64_t, VkDescriptorSet> cachedDescriptorSets;
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
class GFXVulkanRenderPass : public GFXRenderPass {
|
||||
public:
|
||||
VkRenderPass handle = VK_NULL_HANDLE;
|
||||
VkRenderPass handle = VK_NULL_HANDLE;
|
||||
|
||||
unsigned int numAttachments = 0;
|
||||
unsigned int numAttachments = 0;
|
||||
int depth_attachment = -1;
|
||||
|
||||
bool hasDepthAttachment = false;
|
||||
|
||||
bool hasDepthAttachment = false;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "gfx_sampler.hpp"
|
||||
|
||||
class GFXVulkanSampler: public GFXSampler {
|
||||
class GFXVulkanSampler : public GFXSampler {
|
||||
public:
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
};
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
|
||||
class GFXVulkanTexture : public GFXTexture {
|
||||
public:
|
||||
VkImage handle = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
VkImage handle = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
|
||||
int width = 0, height = 0;
|
||||
int width = 0, height = 0;
|
||||
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageLayout current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageAspectFlagBits aspect;
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageLayout current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageAspectFlagBits aspect;
|
||||
VkImageSubresourceRange range;
|
||||
|
||||
GFXTextureUsage usage;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(SRC
|
||||
include/log.hpp
|
||||
src/log.cpp)
|
||||
include/log.hpp
|
||||
src/log.cpp)
|
||||
|
||||
add_library(Log STATIC ${SRC})
|
||||
target_include_directories(Log PUBLIC include)
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace prism {
|
|||
log_output += str + "\n";
|
||||
}
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void log(const S& format, Args&&... args) {
|
||||
template<typename S, typename... Args> inline void log(const S& format, Args&&... args) {
|
||||
vlog(format, fmt::make_args_checked<Args...>(format, args...));
|
||||
}
|
||||
}
|
||||
} // namespace prism
|
|
@ -1,14 +1,14 @@
|
|||
set(SRC
|
||||
include/math.hpp
|
||||
include/matrix.hpp
|
||||
include/transform.hpp
|
||||
include/vector.hpp
|
||||
include/quaternion.hpp
|
||||
include/plane.hpp
|
||||
include/aabb.hpp
|
||||
include/math.hpp
|
||||
include/matrix.hpp
|
||||
include/transform.hpp
|
||||
include/vector.hpp
|
||||
include/quaternion.hpp
|
||||
include/plane.hpp
|
||||
include/aabb.hpp
|
||||
|
||||
src/transform.cpp
|
||||
src/math.cpp include/ray.hpp)
|
||||
src/transform.cpp
|
||||
src/math.cpp include/ray.hpp)
|
||||
|
||||
add_library(Math STATIC ${SRC})
|
||||
target_include_directories(Math PUBLIC include)
|
||||
|
|
|
@ -13,13 +13,13 @@ namespace prism {
|
|||
/// Creates an array of 8 points, each of these being one extreme of the bounding box..
|
||||
inline std::array<float3, 8> get_points(const aabb& aabb) {
|
||||
return {
|
||||
float3(aabb.min.x, aabb.min.y, aabb.min.z),
|
||||
float3(aabb.max.x, aabb.min.y, aabb.min.z),
|
||||
float3(aabb.min.x, aabb.max.y, aabb.min.z),
|
||||
float3(aabb.max.x, aabb.max.y, aabb.min.z),
|
||||
float3(aabb.min.x, aabb.min.y, aabb.max.z),
|
||||
float3(aabb.max.x, aabb.min.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.min.x, aabb.min.y, aabb.min.z),
|
||||
float3(aabb.max.x, aabb.min.y, aabb.min.z),
|
||||
float3(aabb.min.x, aabb.max.y, aabb.min.z),
|
||||
float3(aabb.max.x, aabb.max.y, aabb.min.z),
|
||||
float3(aabb.min.x, aabb.min.y, aabb.max.z),
|
||||
float3(aabb.max.x, aabb.min.y, aabb.max.z),
|
||||
float3(aabb.min.x, aabb.max.y, aabb.max.z),
|
||||
float3(aabb.max.x, aabb.max.y, aabb.max.z)};
|
||||
}
|
||||
}
|
||||
} // namespace prism
|
|
@ -1,26 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "matrix.hpp"
|
||||
#include "ray.hpp"
|
||||
#include "transform.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "ray.hpp"
|
||||
|
||||
constexpr double PI = 3.141592653589793;
|
||||
|
||||
template<typename T>
|
||||
constexpr inline T radians(const T degrees) {
|
||||
template<typename T> constexpr inline T radians(const T degrees) {
|
||||
return degrees / static_cast<T>(180) * static_cast<T>(PI);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr inline T degrees(const T radians) {
|
||||
template<typename T> constexpr inline T degrees(const T radians) {
|
||||
return radians / static_cast<T>(PI) * static_cast<T>(180);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr inline bool nearly_equal(const T a, const T b) {
|
||||
return std::nextafter(a, std::numeric_limits<T>::lowest()) <= b
|
||||
&& std::nextafter(a, std::numeric_limits<T>::max()) >= b;
|
||||
template<typename T> constexpr inline bool nearly_equal(const T a, const T b) {
|
||||
return std::nextafter(a, std::numeric_limits<T>::lowest()) <= b &&
|
||||
std::nextafter(a, std::numeric_limits<T>::max()) >= b;
|
||||
}
|
||||
|
||||
Matrix4x4 matrix_from_quat(Quaternion quat);
|
||||
|
|
|
@ -5,32 +5,40 @@
|
|||
// m = rows
|
||||
// n = columns
|
||||
// row major storage mode?
|
||||
template<class T, std::size_t M, std::size_t N>
|
||||
class Matrix {
|
||||
template<class T, std::size_t M, std::size_t N> class Matrix {
|
||||
public:
|
||||
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));
|
||||
}
|
||||
|
||||
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[1] = m2_;
|
||||
columns[2] = m3_;
|
||||
columns[3] = m4_;
|
||||
}
|
||||
|
||||
|
||||
constexpr inline void operator*=(Matrix rhs);
|
||||
|
||||
using VectorType = prism::Vector<N, T>;
|
||||
|
||||
constexpr VectorType& operator[](const size_t index) { return columns[index]; }
|
||||
constexpr VectorType operator[](const size_t index) const { return columns[index]; }
|
||||
|
||||
constexpr VectorType& operator[](const size_t index) {
|
||||
return columns[index];
|
||||
}
|
||||
|
||||
constexpr VectorType operator[](const size_t index) const {
|
||||
return columns[index];
|
||||
}
|
||||
|
||||
union {
|
||||
VectorType columns[M];
|
||||
T data[M][N];
|
||||
T unordered_data[M * N] = {};
|
||||
T data[M][N];
|
||||
T unordered_data[M * N] = {};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -39,20 +47,20 @@ using Matrix3x3 = Matrix<float, 3, 3>;
|
|||
|
||||
constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const Matrix4x4 rhs) {
|
||||
Matrix4x4 tmp(0.0f);
|
||||
for(int j = 0; j < 4; j++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
for(int k = 0; k < 4; k++)
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int k = 0; k < 4; k++)
|
||||
tmp.data[j][i] += lhs.data[k][i] * rhs.data[j][k];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
constexpr inline prism::float4 operator*(const Matrix4x4 lhs, const prism::float4 rhs) {
|
||||
prism::float4 tmp;
|
||||
for(int r = 0; r < 4; r++) {
|
||||
for(int c = 0; c < 4; c++)
|
||||
for (int r = 0; r < 4; r++) {
|
||||
for (int c = 0; c < 4; c++)
|
||||
tmp[r] += lhs.data[c][r] * rhs.data[c];
|
||||
}
|
||||
|
||||
|
@ -61,13 +69,13 @@ constexpr inline prism::float4 operator*(const Matrix4x4 lhs, const prism::float
|
|||
|
||||
constexpr inline Matrix4x4 operator/(const Matrix4x4 lhs, const float rhs) {
|
||||
Matrix4x4 tmp(0.0f);
|
||||
for(int j = 0; j < 4; j++) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
for(int k = 0; k < 4; k++)
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int k = 0; k < 4; k++)
|
||||
tmp.data[k][i] = lhs.data[k][i] / rhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
@ -79,9 +87,11 @@ constexpr inline Matrix4x4 operator*(const Matrix4x4 lhs, const float rhs) {
|
|||
tmp.data[k][i] = lhs.data[k][i] * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -9,22 +9,17 @@ struct Plane {
|
|||
};
|
||||
|
||||
inline Plane normalize(const Plane& plane) {
|
||||
const float magnitude = std::sqrt(plane.a * plane.a +
|
||||
plane.b * plane.b +
|
||||
plane.c * plane.c);
|
||||
|
||||
const float magnitude = std::sqrt(plane.a * plane.a + plane.b * plane.b + plane.c * plane.c);
|
||||
|
||||
Plane normalized_plane = plane;
|
||||
normalized_plane.a = plane.a / magnitude;
|
||||
normalized_plane.b = plane.b / magnitude;
|
||||
normalized_plane.c = plane.c / magnitude;
|
||||
normalized_plane.d = plane.d / magnitude;
|
||||
|
||||
|
||||
return normalized_plane;
|
||||
}
|
||||
|
||||
inline float distance_to_point(const Plane& plane, const prism::float3& point) {
|
||||
return plane.a * point.x +
|
||||
plane.b * point.y +
|
||||
plane.c * point.z +
|
||||
plane.d;
|
||||
return plane.a * point.x + plane.b * point.y + plane.c * point.z + plane.d;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
class Quaternion {
|
||||
public:
|
||||
constexpr Quaternion(const float v = 0.0f) : w(1.0f), x(v), y(v), z(v) {}
|
||||
|
||||
|
||||
constexpr Quaternion(const float x, const float y, const float z, const float w) : w(w), x(x), y(y), z(z) {}
|
||||
|
||||
|
||||
float w, x, y, z;
|
||||
};
|
||||
};
|
||||
|
||||
constexpr inline Quaternion operator*(const Quaternion lhs, const float rhs) {
|
||||
Quaternion tmp(lhs);
|
||||
|
@ -17,7 +17,7 @@ constexpr inline Quaternion operator*(const Quaternion lhs, const float rhs) {
|
|||
tmp.y *= rhs;
|
||||
tmp.z *= rhs;
|
||||
tmp.w *= rhs;
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ constexpr inline prism::float3 operator*(const Quaternion& lhs, const prism::flo
|
|||
const prism::float3 quatVector = prism::float3(lhs.x, lhs.y, lhs.z);
|
||||
const prism::float3 uv = cross(quatVector, rhs);
|
||||
const prism::float3 uuv = cross(quatVector, uv);
|
||||
|
||||
|
||||
return rhs + ((uv * lhs.w) + uuv) * 2.0f;
|
||||
}
|
||||
|
||||
|
@ -43,37 +43,34 @@ inline float length(const Quaternion& quat) {
|
|||
|
||||
inline Quaternion normalize(const Quaternion& quat) {
|
||||
const float l = length(quat);
|
||||
|
||||
|
||||
return quat * (1.0f / l);
|
||||
}
|
||||
|
||||
constexpr inline Quaternion lerp(const Quaternion& a, const Quaternion& b, const float time) {
|
||||
float cosom = dot(a, b);
|
||||
|
||||
|
||||
Quaternion end = b;
|
||||
if(cosom < 0.0f) {
|
||||
if (cosom < 0.0f) {
|
||||
cosom = -cosom;
|
||||
end.x = -end.x;
|
||||
end.y = -end.y;
|
||||
end.z = -end.z;
|
||||
end.w = -end.w;
|
||||
}
|
||||
|
||||
|
||||
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 sinom = std::sin(omega);
|
||||
sclp = std::sin((1.0f - time) * omega) / sinom;
|
||||
sclq = std::sin(time* omega) / sinom;
|
||||
sclp = std::sin((1.0f - time) * omega) / sinom;
|
||||
sclq = std::sin(time * omega) / sinom;
|
||||
} else {
|
||||
sclp = 1.0f - time;
|
||||
sclq = time;
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
constexpr inline Quaternion operator*(const Quaternion lhs, const Quaternion rhs) {
|
||||
|
@ -82,6 +79,6 @@ constexpr inline Quaternion operator*(const Quaternion lhs, const Quaternion rhs
|
|||
tmp.x = lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y;
|
||||
tmp.y = lhs.w * rhs.y + lhs.y * rhs.w + lhs.z * rhs.x - lhs.x * rhs.z;
|
||||
tmp.z = lhs.w * rhs.z + lhs.z * rhs.w + lhs.x * rhs.y - lhs.y * rhs.x;
|
||||
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
@ -9,4 +9,4 @@ namespace prism {
|
|||
};
|
||||
|
||||
float closest_distance_between_lines(ray& l1, ray& l2);
|
||||
}
|
||||
} // namespace prism
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "matrix.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "quaternion.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace prism {
|
||||
Matrix4x4 perspective(float field_of_view, float aspect, float z_near, float z_far);
|
||||
|
@ -15,5 +15,5 @@ namespace prism {
|
|||
|
||||
Matrix4x4 translate(Matrix4x4 matrix, float3 translation);
|
||||
Matrix4x4 rotate(Matrix4x4 matrix, float angle, float3 axis);
|
||||
Matrix4x4 scale(Matrix4x4 matrix, float3 scale);
|
||||
}
|
||||
Matrix4x4 scale(Matrix4x4 matrix, float3 scale);
|
||||
} // namespace prism
|
||||
|
|
|
@ -1,62 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <array>
|
||||
|
||||
namespace prism {
|
||||
#define DEFINE_OPERATORS(Size) \
|
||||
constexpr Vector(const T scalar = T(0)) { \
|
||||
for(std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] = scalar; \
|
||||
} \
|
||||
constexpr T& operator[](const size_t index) { \
|
||||
return data[index]; \
|
||||
} \
|
||||
constexpr T operator[](const size_t index) const { \
|
||||
return data[index]; \
|
||||
} \
|
||||
constexpr Vector& operator+=(const Vector rhs) { \
|
||||
for(std::size_t i = 0; i < (Size); i++)\
|
||||
data[i] += rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator-=(const Vector rhs) { \
|
||||
for(std::size_t i = 0; i < (Size); i++)\
|
||||
data[i] -= rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator*=(const Vector rhs) { \
|
||||
for(std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] *= rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator/=(const T scalar) { \
|
||||
for(std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] /= scalar; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr T* ptr() const { \
|
||||
return data.data(); \
|
||||
} \
|
||||
constexpr T* ptr() { \
|
||||
return data.data(); \
|
||||
} \
|
||||
constexpr Vector operator- () const { \
|
||||
Vector vec; \
|
||||
for(std::size_t i = 0; i < (Size); i++) \
|
||||
vec[i] = -data[i]; \
|
||||
return vec; \
|
||||
#define DEFINE_OPERATORS(Size) \
|
||||
constexpr Vector(const T scalar = T(0)) { \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] = scalar; \
|
||||
} \
|
||||
constexpr T& operator[](const size_t index) { return data[index]; } \
|
||||
constexpr T operator[](const size_t index) const { return data[index]; } \
|
||||
constexpr Vector& operator+=(const Vector rhs) { \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] += rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator-=(const Vector rhs) { \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] -= rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator*=(const Vector rhs) { \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] *= rhs[i]; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr Vector& operator/=(const T scalar) { \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
data[i] /= scalar; \
|
||||
return *this; \
|
||||
} \
|
||||
constexpr T* ptr() const { return data.data(); } \
|
||||
constexpr T* ptr() { return data.data(); } \
|
||||
constexpr Vector operator-() const { \
|
||||
Vector vec; \
|
||||
for (std::size_t i = 0; i < (Size); i++) \
|
||||
vec[i] = -data[i]; \
|
||||
return vec; \
|
||||
}
|
||||
|
||||
template<std::size_t N, class T>
|
||||
struct Vector {
|
||||
std::array<T, N> data;
|
||||
};
|
||||
template<std::size_t N, class T> struct Vector { std::array<T, N> data; };
|
||||
|
||||
template<class T>
|
||||
struct Vector<2, T> {
|
||||
template<class T> struct Vector<2, T> {
|
||||
constexpr Vector(const T x_, const T y_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
|
@ -73,8 +61,7 @@ namespace prism {
|
|||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct Vector<3, T> {
|
||||
template<class T> struct Vector<3, T> {
|
||||
constexpr Vector(const T x_, const T y_, const T z_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
|
@ -92,8 +79,7 @@ namespace prism {
|
|||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct alignas(16) Vector<4, T> {
|
||||
template<class T> struct alignas(16) Vector<4, T> {
|
||||
constexpr Vector(const T x_, const T y_, const T z_, const T w_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
|
@ -101,7 +87,7 @@ namespace prism {
|
|||
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)
|
||||
|
||||
|
@ -123,8 +109,7 @@ namespace prism {
|
|||
using float3 = Vector<3, float>;
|
||||
using float4 = Vector<4, float>;
|
||||
|
||||
template<std::size_t N, class T>
|
||||
constexpr inline T dot(const Vector<N, T> lhs, const Vector<N, T> rhs) {
|
||||
template<std::size_t N, class T> constexpr inline T dot(const Vector<N, T> lhs, const Vector<N, T> rhs) {
|
||||
T product = T(0.0);
|
||||
|
||||
for (std::size_t i = 0; i < N; i++)
|
||||
|
@ -133,8 +118,7 @@ namespace prism {
|
|||
return product;
|
||||
}
|
||||
|
||||
template<std::size_t N, class T>
|
||||
constexpr inline T length(const Vector<N, T> vec) {
|
||||
template<std::size_t N, class T> constexpr inline T length(const Vector<N, T> vec) {
|
||||
return sqrtf(dot(vec, vec));
|
||||
}
|
||||
|
||||
|
@ -147,8 +131,7 @@ namespace prism {
|
|||
return vec;
|
||||
}
|
||||
|
||||
template<std::size_t N, class T>
|
||||
constexpr inline Vector<N, T> normalize(const Vector<N, T> vec) {
|
||||
template<std::size_t N, class T> constexpr inline Vector<N, T> normalize(const Vector<N, T> vec) {
|
||||
Vector<N, T> result;
|
||||
|
||||
const float len = length(vec);
|
||||
|
@ -170,15 +153,14 @@ namespace prism {
|
|||
return std::sqrt((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ));
|
||||
}
|
||||
|
||||
template<std::size_t N, class T>
|
||||
constexpr inline T norm(const Vector<N, T> vec) {
|
||||
template<std::size_t N, class T> constexpr inline T norm(const Vector<N, T> vec) {
|
||||
T val = T(0);
|
||||
for (std::size_t i = 0; i < N; i++)
|
||||
val += abs(vec[i]);
|
||||
|
||||
return sqrtf(dot(vec, vec));
|
||||
}
|
||||
}
|
||||
} // namespace prism
|
||||
|
||||
template<std::size_t N, class T>
|
||||
constexpr inline bool operator==(const prism::Vector<N, T> lhs, const prism::Vector<N, T> rhs) {
|
||||
|
|
|
@ -10,20 +10,20 @@ Matrix4x4 matrix_from_quat(const Quaternion quat) {
|
|||
const float qwx = quat.w * quat.x;
|
||||
const float qwy = quat.w * quat.y;
|
||||
const float qwz = quat.w * quat.z;
|
||||
|
||||
|
||||
Matrix4x4 result(1.0f);
|
||||
result[0][0] = 1.0f - 2.0f * (qyy + qzz);
|
||||
result[0][1] = 2.0f * (qxy + qwz);
|
||||
result[0][2] = 2.0f * (qxz - qwy);
|
||||
|
||||
|
||||
result[1][0] = 2.0f * (qxy - qwz);
|
||||
result[1][1] = 1.0f - 2.0f * (qxx + qzz);
|
||||
result[1][2] = 2.0f * (qyz + qwx);
|
||||
|
||||
|
||||
result[2][0] = 2.0f * (qxz + qwy);
|
||||
result[2][1] = 2.0f * (qyz - qwx);
|
||||
result[2][2] = 1.0f - 2.0f * (qxx + qyy);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -32,28 +32,28 @@ Quaternion quat_from_matrix(const Matrix3x3 m) {
|
|||
const float fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
|
||||
const float fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
|
||||
const float fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
|
||||
|
||||
|
||||
int biggestIndex = 0;
|
||||
float fourBiggestSquaredMinus1 = fourWSquaredMinus1;
|
||||
if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
fourBiggestSquaredMinus1 = fourXSquaredMinus1;
|
||||
biggestIndex = 1;
|
||||
}
|
||||
|
||||
if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
|
||||
if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
fourBiggestSquaredMinus1 = fourYSquaredMinus1;
|
||||
biggestIndex = 2;
|
||||
}
|
||||
|
||||
if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
|
||||
if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) {
|
||||
fourBiggestSquaredMinus1 = fourZSquaredMinus1;
|
||||
biggestIndex = 3;
|
||||
}
|
||||
|
||||
|
||||
const float biggestVal = sqrt(fourBiggestSquaredMinus1 + 1.0f) * 0.5f;
|
||||
const float mult = 0.25f / biggestVal;
|
||||
|
||||
switch(biggestIndex) {
|
||||
|
||||
switch (biggestIndex) {
|
||||
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};
|
||||
case 1:
|
||||
|
@ -74,31 +74,31 @@ Quaternion euler_to_quat(const prism::float3 angle) {
|
|||
const float sr = sinf(angle.x * 0.5f);
|
||||
const float cp = cosf(angle.y * 0.5f);
|
||||
const float sp = sinf(angle.y * 0.5f);
|
||||
|
||||
|
||||
const float cpcy = cp * cy;
|
||||
const float spcy = sp * cy;
|
||||
const float cpsy = cp * sy;
|
||||
const float spsy = sp * sy;
|
||||
|
||||
|
||||
Quaternion result;
|
||||
result.w = cr * cpcy + sr * spsy;
|
||||
result.x = sr * cpcy - cr * spsy;
|
||||
result.y = cr * spcy + sr * cpsy;
|
||||
result.z = cr * cpsy - sr * spcy;
|
||||
|
||||
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
prism::float3 quat_to_euler(const Quaternion q) {
|
||||
const float roll = atan2(2.0f * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z);
|
||||
|
||||
|
||||
const float y = 2.0f * (q.y * q.z + q.w * q.x);
|
||||
const float x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
|
||||
|
||||
|
||||
const float pitch = atan2(y, x);
|
||||
|
||||
|
||||
const float yaw = asinf(-2.0f * (q.x * q.z - q.w * q.y));
|
||||
|
||||
|
||||
return {pitch, yaw, roll};
|
||||
}
|
||||
|
||||
|
@ -106,67 +106,67 @@ Matrix4x4 inverse(const Matrix4x4 m) {
|
|||
const float Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
const float Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
const float Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
|
||||
|
||||
const float Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
const float Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
const float Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
|
||||
|
||||
const float Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
const float Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
const float Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
|
||||
|
||||
const float Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
const float Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
const float Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
|
||||
|
||||
const float Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
const float Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
const float Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
|
||||
|
||||
const float Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
const float Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
const float Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
|
||||
|
||||
const prism::float4 Fac0(Coef00, Coef00, Coef02, Coef03);
|
||||
const prism::float4 Fac1(Coef04, Coef04, Coef06, Coef07);
|
||||
const prism::float4 Fac2(Coef08, Coef08, Coef10, Coef11);
|
||||
const prism::float4 Fac3(Coef12, Coef12, Coef14, Coef15);
|
||||
const prism::float4 Fac4(Coef16, Coef16, Coef18, Coef19);
|
||||
const prism::float4 Fac5(Coef20, Coef20, Coef22, Coef23);
|
||||
|
||||
|
||||
const prism::float4 Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
|
||||
const prism::float4 Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
|
||||
const prism::float4 Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
|
||||
const prism::float4 Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
|
||||
|
||||
|
||||
const prism::float4 Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
|
||||
const prism::float4 Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
|
||||
const prism::float4 Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
|
||||
const prism::float4 Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
|
||||
|
||||
|
||||
const prism::float4 SignA(+1, -1, +1, -1);
|
||||
const prism::float4 SignB(-1, +1, -1, +1);
|
||||
const Matrix4x4 Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
|
||||
|
||||
|
||||
const prism::float4 Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
|
||||
|
||||
|
||||
const prism::float4 Dot0(m[0] * Row0);
|
||||
const float Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
|
||||
|
||||
|
||||
const float OneOverDeterminant = 1.0f / Dot1;
|
||||
|
||||
|
||||
return Inverse * OneOverDeterminant;
|
||||
}
|
||||
|
||||
Quaternion angle_axis(const float angle, const prism::float3 axis) {
|
||||
const float s = sinf(angle * 0.5f);
|
||||
|
||||
|
||||
Quaternion result;
|
||||
result.w = cosf(angle * 0.5f);
|
||||
result.x = axis.x * s;
|
||||
result.y = axis.y * s;
|
||||
result.z = axis.z * s;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ Matrix4x4 prism::perspective(const float field_of_view, const float aspect, cons
|
|||
result[2][2] = z_far / (z_far - z_near);
|
||||
result[2][3] = 1.0f;
|
||||
result[3][2] = -(z_far * z_near) / (z_far - z_near);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ Matrix4x4 prism::infinite_perspective(const float field_of_view, const float asp
|
|||
result[2][2] = 1.0f - std::numeric_limits<float>::epsilon(); // prevent NaN
|
||||
result[2][3] = 1.0f;
|
||||
result[3][2] = -(2.0 - std::numeric_limits<float>::epsilon()) * z_near;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ Matrix4x4 prism::orthographic(float left, float right, float bottom, float top,
|
|||
result[2][2] = 1.0f / (zFar - zNear);
|
||||
result[3][0] = -(right + left) / (right - left);
|
||||
result[3][1] = -(top + bottom) / (top - bottom);
|
||||
result[3][2] = - zNear / (zFar - zNear);
|
||||
result[3][2] = -zNear / (zFar - zNear);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ Matrix4x4 prism::look_at(const float3 eye, const float3 center, const float3 up)
|
|||
const float3 f = normalize(center - eye);
|
||||
const float3 s = normalize(cross(up, f));
|
||||
const float3 u = cross(f, s);
|
||||
|
||||
|
||||
Matrix4x4 result(1.0f);
|
||||
result[0][0] = s.x;
|
||||
result[1][0] = s.y;
|
||||
|
@ -69,14 +69,14 @@ Matrix4x4 prism::look_at(const float3 eye, const float3 center, const float3 up)
|
|||
result[3][0] = -dot(s, eye);
|
||||
result[3][1] = -dot(u, eye);
|
||||
result[3][2] = -dot(f, eye);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Matrix4x4 prism::translate(const Matrix4x4 matrix, const float3 translation) {
|
||||
Matrix4x4 result(1.0f);
|
||||
result[3] = float4(translation, 1.0);
|
||||
|
||||
|
||||
return matrix * result;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ Matrix4x4 prism::rotate(const Matrix4x4 matrix, const float angle, const float3
|
|||
result[1] = matrix[0] * Rotate[1][0] + matrix[1] * Rotate[1][1] + matrix[2] * Rotate[1][2];
|
||||
result[2] = matrix[0] * Rotate[2][0] + matrix[1] * Rotate[2][1] + matrix[2] * Rotate[2][2];
|
||||
result[3] = matrix[3];
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -115,17 +115,17 @@ Matrix4x4 prism::scale(const Matrix4x4 matrix, const float3 scale) {
|
|||
result[0][0] = scale.x;
|
||||
result[1][1] = scale.y;
|
||||
result[2][2] = scale.z;
|
||||
|
||||
|
||||
return matrix * result;
|
||||
}
|
||||
|
||||
Quaternion prism::quat_look_at(const float3 eye, const float3 center, const float3 up) {
|
||||
const float3 direction = normalize(center - eye);
|
||||
|
||||
|
||||
Matrix3x3 result(1.0f);
|
||||
result[2] = direction;
|
||||
result[0] = normalize(cross(up, result[2]));
|
||||
result[1] = cross(result[2], result[0]);
|
||||
|
||||
|
||||
return quat_from_matrix(result);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
if(ENABLE_VULKAN)
|
||||
if (ENABLE_VULKAN)
|
||||
set(EXTRA_LIBRARIES Vulkan::Vulkan ${EXTRA_LIBRARIES})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if(ENABLE_METAL)
|
||||
if (ENABLE_METAL)
|
||||
set(EXTRA_LIBRARIES metal-cpp ${EXTRA_LIBRARIES})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
add_library(Platform INTERFACE)
|
||||
target_include_directories(Platform INTERFACE include)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "log.hpp"
|
||||
#include "path.hpp"
|
||||
|
@ -20,23 +20,20 @@ namespace prism {
|
|||
class file {
|
||||
public:
|
||||
explicit file(FILE* handle) : handle(handle) {}
|
||||
|
||||
file(file&& f) noexcept :
|
||||
mem(std::move(f.mem)),
|
||||
handle(std::exchange(f.handle, nullptr)),
|
||||
data(std::move(f.data)) {}
|
||||
|
||||
|
||||
file(file&& f) noexcept
|
||||
: mem(std::move(f.mem)), handle(std::exchange(f.handle, nullptr)), data(std::move(f.data)) {}
|
||||
|
||||
~file() {
|
||||
if(handle != nullptr)
|
||||
if (handle != nullptr)
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
|
||||
/** Loads a type.
|
||||
@param t The pointer to the type.
|
||||
@param s If not 0, the size to load is derived from sizeof(T).
|
||||
*/
|
||||
template<typename T>
|
||||
void read(T* t, const size_t s = 0) {
|
||||
template<typename T> void read(T* t, const size_t s = 0) {
|
||||
fread(t, s == 0 ? sizeof(T) : s, 1, handle);
|
||||
}
|
||||
|
||||
|
@ -49,7 +46,7 @@ namespace prism {
|
|||
unsigned int length = 0;
|
||||
read(&length);
|
||||
|
||||
if(length > 0) {
|
||||
if (length > 0) {
|
||||
str.resize(length);
|
||||
|
||||
read(str.data(), sizeof(char) * length);
|
||||
|
@ -65,10 +62,9 @@ namespace prism {
|
|||
data.resize(_size);
|
||||
fread(data.data(), _size, 1, handle);
|
||||
}
|
||||
|
||||
|
||||
/// If the file is loaded in memory, cast the underlying data.
|
||||
template<typename T>
|
||||
T* cast_data() {
|
||||
template<typename T> T* cast_data() {
|
||||
return reinterpret_cast<T*>(data.data());
|
||||
}
|
||||
|
||||
|
@ -91,18 +87,18 @@ namespace prism {
|
|||
mem = std::make_unique<membuf>(char_data, char_data + size());
|
||||
return std::istream(mem.get());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
struct membuf : std::streambuf {
|
||||
inline membuf(char* begin, char* end) {
|
||||
this->setg(begin, begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::unique_ptr<membuf> mem;
|
||||
|
||||
|
||||
FILE* handle = nullptr;
|
||||
|
||||
|
||||
std::vector<std::byte> data;
|
||||
};
|
||||
|
||||
|
@ -117,8 +113,8 @@ namespace prism {
|
|||
/// Converts an absolute path to a domain relative path.
|
||||
path get_relative_path(domain domain, const path& domain_relative_path);
|
||||
|
||||
/// Returns the path to a writeable directory.
|
||||
path get_writeable_directory();
|
||||
/// Returns the path to a writeable directory.
|
||||
path get_writeable_directory();
|
||||
|
||||
/**
|
||||
Opens a file handle.
|
||||
|
@ -128,11 +124,11 @@ namespace prism {
|
|||
@return An optional with a value if the file was loaded correctly, otherwise it's empty.
|
||||
*/
|
||||
std::optional<file> open_file(const path& file_path, bool binary_mode = false);
|
||||
|
||||
|
||||
path root_path(const path& path);
|
||||
path get_file_path(const path& path);
|
||||
|
||||
|
||||
inline path base_domain = "/base", game_domain = "/game";
|
||||
}
|
||||
} // namespace prism
|
||||
|
||||
inline std::array<std::string, 3> domain_data;
|
||||
|
|
|
@ -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)
|
||||
// this only determines it at build-time, not at runtime.
|
||||
#ifdef ENABLE_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
struct vulkan_information {
|
||||
std::vector<const char*> surface_extensions;
|
||||
|
@ -100,8 +100,8 @@ struct directx_surface_creation_info {
|
|||
#endif
|
||||
|
||||
#ifdef ENABLE_METAL
|
||||
#include <Metal/Metal.hpp>
|
||||
#include <QuartzCore/CAMetalDrawable.hpp>
|
||||
#include <Metal/Metal.hpp>
|
||||
#include <QuartzCore/CAMetalDrawable.hpp>
|
||||
|
||||
struct metal_surface_creation_info {
|
||||
MTL::Device* device;
|
||||
|
@ -140,9 +140,9 @@ namespace platform {
|
|||
void initialize_context(GFXContext context);
|
||||
|
||||
/*
|
||||
* This is used in specific cases where the gfx backend may need to know important information before window creation.
|
||||
* A good example is the surface extension required by a specific window backend, but this is between initialize_context
|
||||
* and create_surface calls.
|
||||
* This is used in specific cases where the gfx backend may need to know important information before window
|
||||
* creation. A good example is the surface extension required by a specific window backend, but this is between
|
||||
* initialize_context and create_surface calls.
|
||||
*
|
||||
* 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 rect The requested size and position of the window.
|
||||
@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 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.
|
||||
@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 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* This needs to be implemented under certain gfx contexts (such as metal) which calls [layer nextDrawable] underneath
|
||||
* can be no-op for contexts such as vulkan which can happen within it's own API.
|
||||
* This needs to be implemented under certain gfx contexts (such as metal) which calls [layer nextDrawable]
|
||||
* 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.
|
||||
*/
|
||||
|
@ -201,7 +203,8 @@ namespace platform {
|
|||
/// Get the window size, note that in hidpi scenarios this is the non-scaled resolution.
|
||||
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);
|
||||
|
||||
/// 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.
|
||||
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 end_text_input();
|
||||
}
|
||||
} // namespace platform
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
set(SRC
|
||||
include/renderer.hpp
|
||||
include/pass.hpp
|
||||
include/shadowpass.hpp
|
||||
include/imguipass.hpp
|
||||
include/smaapass.hpp
|
||||
include/scenecapture.hpp
|
||||
include/materialcompiler.hpp
|
||||
include/dofpass.hpp
|
||||
include/frustum.hpp
|
||||
include/render_options.hpp
|
||||
include/rendertarget.hpp
|
||||
include/renderer.hpp
|
||||
include/pass.hpp
|
||||
include/shadowpass.hpp
|
||||
include/imguipass.hpp
|
||||
include/smaapass.hpp
|
||||
include/scenecapture.hpp
|
||||
include/materialcompiler.hpp
|
||||
include/dofpass.hpp
|
||||
include/frustum.hpp
|
||||
include/render_options.hpp
|
||||
include/rendertarget.hpp
|
||||
|
||||
src/renderer.cpp
|
||||
src/shadowpass.cpp
|
||||
src/imguipass.cpp
|
||||
src/smaapass.cpp
|
||||
src/scenecapture.cpp
|
||||
src/materialcompiler.cpp
|
||||
src/dofpass.cpp
|
||||
src/frustum.cpp)
|
||||
src/renderer.cpp
|
||||
src/shadowpass.cpp
|
||||
src/imguipass.cpp
|
||||
src/smaapass.cpp
|
||||
src/scenecapture.cpp
|
||||
src/materialcompiler.cpp
|
||||
src/dofpass.cpp
|
||||
src/frustum.cpp)
|
||||
|
||||
add_library(Renderer STATIC ${SRC})
|
||||
target_link_libraries(Renderer
|
||||
PUBLIC
|
||||
GFX
|
||||
Math
|
||||
PRIVATE
|
||||
stb
|
||||
Math
|
||||
Utility
|
||||
imgui
|
||||
SMAA::SMAA
|
||||
ShaderCompiler
|
||||
Core)
|
||||
PUBLIC
|
||||
GFX
|
||||
Math
|
||||
PRIVATE
|
||||
stb
|
||||
Math
|
||||
Utility
|
||||
imgui
|
||||
SMAA::SMAA
|
||||
ShaderCompiler
|
||||
Core)
|
||||
target_include_directories(Renderer PUBLIC include)
|
||||
set_engine_properties(Renderer)
|
|
@ -15,17 +15,17 @@ namespace prism {
|
|||
class DoFPass {
|
||||
public:
|
||||
DoFPass(GFX* gfx);
|
||||
|
||||
|
||||
void render(GFXCommandBuffer* command_buffer, Scene& scene);
|
||||
|
||||
|
||||
GFXTexture* far_field = nullptr;
|
||||
GFXTexture* normal_field = nullptr;
|
||||
|
||||
|
||||
GFXFramebuffer* far_framebuffer = nullptr;
|
||||
GFXFramebuffer* normal_framebuffer = nullptr;
|
||||
|
||||
|
||||
GFXRenderPass* renderpass = nullptr;
|
||||
|
||||
|
||||
private:
|
||||
GFXPipeline* pipeline = nullptr;
|
||||
};
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include "aabb.hpp"
|
||||
#include "asset_types.hpp"
|
||||
#include "components.hpp"
|
||||
#include "frustum.hpp"
|
||||
#include "matrix.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "components.hpp"
|
||||
#include "aabb.hpp"
|
||||
#include "plane.hpp"
|
||||
#include "asset_types.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
class Scene;
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <string_view>
|
||||
|
||||
#include "pass.hpp"
|
||||
#include "file.hpp"
|
||||
#include "pass.hpp"
|
||||
|
||||
class GFXBuffer;
|
||||
class GFXCommandBuffer;
|
||||
|
@ -14,7 +14,7 @@ struct ImDrawData;
|
|||
class ImGuiPass : public Pass {
|
||||
public:
|
||||
void initialize() override;
|
||||
|
||||
|
||||
void create_render_target_resources(RenderTarget& target) override;
|
||||
|
||||
void render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, platform::window_ptr index) override;
|
||||
|
@ -25,7 +25,7 @@ private:
|
|||
void update_buffers(RenderTarget& target, const ImDrawData& draw_data);
|
||||
|
||||
std::unique_ptr<prism::file> font_file;
|
||||
|
||||
|
||||
GFXPipeline* pipeline = nullptr;
|
||||
GFXTexture* font_texture = nullptr;
|
||||
};
|
||||
|
|
|
@ -15,12 +15,14 @@ constexpr int bone_buffer_index = 10;
|
|||
|
||||
class MaterialCompiler {
|
||||
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);
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -16,16 +16,19 @@ class RenderTarget;
|
|||
class Pass {
|
||||
public:
|
||||
virtual ~Pass() = default;
|
||||
|
||||
|
||||
virtual void initialize() {}
|
||||
|
||||
|
||||
virtual void create_render_target_resources([[maybe_unused]] RenderTarget& target) {}
|
||||
|
||||
virtual void render_scene([[maybe_unused]] Scene& scene,
|
||||
[[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
|
||||
virtual void render_post([[maybe_unused]] GFXCommandBuffer* commandBuffer,
|
||||
[[maybe_unused]] RenderTarget& target,
|
||||
[[maybe_unused]] platform::window_ptr index) {}
|
||||
|
||||
virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) { return nullptr; }
|
||||
virtual void render_scene([[maybe_unused]] Scene& scene, [[maybe_unused]] GFXCommandBuffer* commandBuffer) {}
|
||||
|
||||
virtual void render_post(
|
||||
[[maybe_unused]] GFXCommandBuffer* commandBuffer,
|
||||
[[maybe_unused]] RenderTarget& target,
|
||||
[[maybe_unused]] platform::window_ptr index) {}
|
||||
|
||||
virtual GFXTexture* get_requested_texture([[maybe_unused]] PassTextureType type) {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,18 +23,18 @@ struct RenderOptions {
|
|||
DisplayColorSpace display_color_space = DisplayColorSpace::SRGB;
|
||||
TonemapOperator tonemapping = TonemapOperator::Linear;
|
||||
float exposure = 1.0f;
|
||||
|
||||
|
||||
float min_luminance = -8.0f;
|
||||
float max_luminance = 3.0f;
|
||||
|
||||
|
||||
bool enable_depth_of_field = false;
|
||||
float depth_of_field_strength = 3.0f;
|
||||
|
||||
|
||||
bool dynamic_resolution = false;
|
||||
double render_scale = 1.0f;
|
||||
|
||||
|
||||
int shadow_resolution = 2048;
|
||||
|
||||
|
||||
bool enable_aa = true;
|
||||
bool enable_ibl = true;
|
||||
bool enable_normal_mapping = true;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "pass.hpp"
|
||||
#include "common.hpp"
|
||||
#include "matrix.hpp"
|
||||
#include "object.hpp"
|
||||
#include "common.hpp"
|
||||
#include "render_options.hpp"
|
||||
#include "pass.hpp"
|
||||
#include "path.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
#include "rendertarget.hpp"
|
||||
#include "platform.hpp"
|
||||
#include "render_options.hpp"
|
||||
#include "rendertarget.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
|
||||
class GFX;
|
||||
class GFXBuffer;
|
||||
|
@ -58,14 +58,19 @@ namespace prism {
|
|||
|
||||
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,
|
||||
prism::Extent extent, RenderTarget& target, controller_continuity &continuity);
|
||||
void render_camera(
|
||||
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;
|
||||
|
||||
// passes
|
||||
template<class T, typename... Args>
|
||||
T* addPass(Args &&... args) {
|
||||
template<class T, typename... Args> T* addPass(Args&&... args) {
|
||||
auto t = std::make_unique<T>(args...);
|
||||
t->initialize();
|
||||
|
||||
|
@ -93,7 +98,7 @@ namespace prism {
|
|||
|
||||
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);
|
||||
|
||||
|
@ -142,7 +147,7 @@ namespace prism {
|
|||
GFXRenderPass* brdf_render_pass = nullptr;
|
||||
|
||||
// histogram compute
|
||||
GFXPipeline* histogram_pipeline = nullptr, *histogram_average_pipeline = nullptr;
|
||||
GFXPipeline *histogram_pipeline = nullptr, *histogram_average_pipeline = nullptr;
|
||||
GFXBuffer* histogram_buffer = nullptr;
|
||||
GFXTexture* average_luminance_texture = nullptr;
|
||||
|
||||
|
@ -151,4 +156,4 @@ namespace prism {
|
|||
|
||||
std::vector<std::unique_ptr<Pass>> passes;
|
||||
};
|
||||
}
|
||||
} // namespace prism
|
|
@ -12,21 +12,22 @@ constexpr int RT_MAX_FRAMES_IN_FLIGHT = 3;
|
|||
class RenderTarget {
|
||||
public:
|
||||
prism::Extent extent;
|
||||
|
||||
|
||||
[[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))};
|
||||
}
|
||||
|
||||
|
||||
// offscreen
|
||||
GFXTexture* offscreenColorTexture = nullptr;
|
||||
GFXTexture* offscreenDepthTexture = nullptr;
|
||||
|
||||
|
||||
GFXFramebuffer* offscreenFramebuffer = nullptr;
|
||||
|
||||
|
||||
// mesh
|
||||
GFXBuffer* sceneBuffer = nullptr;
|
||||
|
||||
|
||||
// smaa
|
||||
GFXTexture* edge_texture = nullptr;
|
||||
GFXTexture* blend_texture = nullptr;
|
||||
|
@ -37,13 +38,13 @@ public:
|
|||
// intermediary
|
||||
GFXTexture* mid_texture = nullptr;
|
||||
GFXFramebuffer* mid_framebuffer = nullptr;
|
||||
|
||||
|
||||
// imgui
|
||||
GFXBuffer* vertex_buffer[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
int current_vertex_size[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
|
||||
|
||||
GFXBuffer* index_buffer[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
int current_index_size[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
|
||||
|
||||
uint32_t current_frame = 0;
|
||||
};
|
||||
|
|
|
@ -17,22 +17,23 @@ const int irradiance_cubemap_resolution = 32;
|
|||
class SceneCapture {
|
||||
public:
|
||||
explicit SceneCapture(GFX* gfx);
|
||||
|
||||
|
||||
void create_scene_resources(Scene& scene);
|
||||
|
||||
|
||||
void render(GFXCommandBuffer* command_buffer, Scene* scene);
|
||||
|
||||
GFXPipeline* irradiancePipeline, *prefilterPipeline = nullptr, *skyPipeline = nullptr;
|
||||
GFXRenderPass* renderPass = nullptr, *irradianceRenderPass = nullptr;
|
||||
|
||||
|
||||
GFXPipeline *irradiancePipeline, *prefilterPipeline = nullptr, *skyPipeline = nullptr;
|
||||
GFXRenderPass *renderPass = nullptr, *irradianceRenderPass = nullptr;
|
||||
|
||||
GFXTexture* environmentCube = nullptr;
|
||||
|
||||
GFXTexture* offscreenTexture = nullptr, *irradianceOffscreenTexture = nullptr, *prefilteredOffscreenTexture = nullptr;
|
||||
GFXTexture *offscreenTexture = nullptr, *irradianceOffscreenTexture = nullptr,
|
||||
*prefilteredOffscreenTexture = nullptr;
|
||||
GFXTexture* offscreenDepth = nullptr;
|
||||
GFXFramebuffer* offscreenFramebuffer = nullptr, *irradianceFramebuffer = nullptr, *prefilteredFramebuffer = nullptr;
|
||||
|
||||
GFXFramebuffer *offscreenFramebuffer = nullptr, *irradianceFramebuffer = nullptr, *prefilteredFramebuffer = nullptr;
|
||||
|
||||
GFXBuffer* sceneBuffer = nullptr;
|
||||
|
||||
|
||||
void createSkyResources();
|
||||
void createIrradianceResources();
|
||||
void createPrefilterResources();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "components.hpp"
|
||||
#include "math.hpp"
|
||||
#include "object.hpp"
|
||||
#include "components.hpp"
|
||||
|
||||
class GFX;
|
||||
class GFXCommandBuffer;
|
||||
|
@ -18,39 +18,47 @@ struct CameraFrustum;
|
|||
class ShadowPass {
|
||||
public:
|
||||
explicit ShadowPass(GFX* gfx);
|
||||
|
||||
|
||||
void create_scene_resources(Scene& scene);
|
||||
|
||||
|
||||
void render(GFXCommandBuffer* command_buffer, Scene& scene);
|
||||
|
||||
|
||||
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_spot(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light);
|
||||
void render_point(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light);
|
||||
|
||||
|
||||
int last_point_light = 0;
|
||||
int last_spot_light = 0;
|
||||
|
||||
|
||||
void create_render_passes();
|
||||
void create_pipelines();
|
||||
void create_offscreen_resources();
|
||||
|
||||
|
||||
GFXRenderPass* render_pass = nullptr;
|
||||
GFXRenderPass* cube_render_pass = nullptr;
|
||||
|
||||
|
||||
GFXTexture* offscreen_color_texture = nullptr;
|
||||
GFXTexture* offscreen_depth = nullptr;
|
||||
GFXFramebuffer* offscreen_framebuffer = nullptr;
|
||||
|
||||
GFXBuffer* point_location_buffer = nullptr;
|
||||
prism::float4* point_location_map = nullptr;
|
||||
|
||||
|
||||
// sun
|
||||
GFXPipeline* static_sun_pipeline = nullptr;
|
||||
GFXPipeline* skinned_sun_pipeline = nullptr;
|
||||
|
||||
|
||||
// spot
|
||||
GFXPipeline* static_spot_pipeline = nullptr;
|
||||
GFXPipeline* skinned_spot_pipeline = nullptr;
|
||||
|
|
|
@ -18,9 +18,9 @@ namespace prism {
|
|||
class SMAAPass {
|
||||
public:
|
||||
explicit SMAAPass(GFX* gfx);
|
||||
|
||||
|
||||
void create_render_target_resources(RenderTarget& target);
|
||||
|
||||
|
||||
void render(GFXCommandBuffer* command_buffer, RenderTarget& target);
|
||||
|
||||
private:
|
||||
|
@ -30,9 +30,9 @@ private:
|
|||
|
||||
GFXTexture* area_image = nullptr;
|
||||
GFXTexture* search_image = nullptr;
|
||||
|
||||
|
||||
GFXRenderPass* render_pass = nullptr;
|
||||
|
||||
|
||||
GFXPipeline* edge_pipeline = nullptr;
|
||||
GFXPipeline* blend_pipeline = nullptr;
|
||||
};
|
||||
|
|
|
@ -1,50 +1,47 @@
|
|||
#include "dofpass.hpp"
|
||||
|
||||
#include "renderer.hpp"
|
||||
#include "asset.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "asset.hpp"
|
||||
#include "renderer.hpp"
|
||||
|
||||
AssetPtr<Texture> aperture_texture;
|
||||
|
||||
DoFPass::DoFPass(GFX* gfx) {
|
||||
aperture_texture = assetm->get<Texture>(prism::base_domain / "textures/aperture.png");
|
||||
|
||||
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.label = "Depth of Field";
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::RGBA_32F);
|
||||
|
||||
|
||||
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();
|
||||
|
||||
|
||||
GFXShaderConstant width_constant = {};
|
||||
width_constant.value = extent.width;
|
||||
|
||||
|
||||
GFXShaderConstant height_constant = {};
|
||||
height_constant.index = 1;
|
||||
height_constant.value = extent.height;
|
||||
|
||||
|
||||
GFXGraphicsPipelineCreateInfo create_info = {};
|
||||
create_info.shaders.vertex_src = ShaderSource(prism::path("shaders/dof.vert"));
|
||||
create_info.shaders.vertex_constants = {width_constant, height_constant};
|
||||
create_info.shaders.fragment_src = ShaderSource(prism::path("shaders/dof.frag"));
|
||||
|
||||
|
||||
create_info.shader_input.bindings = {
|
||||
{0, GFXBindingType::StorageImage},
|
||||
{1, GFXBindingType::Texture},
|
||||
{3, GFXBindingType::Texture},
|
||||
{2, GFXBindingType::PushConstant}
|
||||
};
|
||||
{2, GFXBindingType::PushConstant}};
|
||||
|
||||
create_info.shader_input.push_constants = {{sizeof(prism::float4), 0}};
|
||||
|
||||
create_info.shader_input.push_constants = {
|
||||
{sizeof(prism::float4), 0}
|
||||
};
|
||||
|
||||
create_info.render_pass = renderpass;
|
||||
|
||||
|
||||
create_info.blending.enable_blending = true;
|
||||
create_info.blending.src_rgb = GFXBlendFactor::SrcColor;
|
||||
create_info.blending.dst_rgb = GFXBlendFactor::One;
|
||||
|
@ -52,7 +49,7 @@ DoFPass::DoFPass(GFX* gfx) {
|
|||
create_info.blending.dst_alpha = GFXBlendFactor::One;
|
||||
|
||||
pipeline = gfx->create_graphics_pipeline(create_info);
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Normal Field";
|
||||
textureInfo.width = extent.width;
|
||||
|
@ -60,69 +57,69 @@ DoFPass::DoFPass(GFX* gfx) {
|
|||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
normal_field = gfx->create_texture(textureInfo);
|
||||
|
||||
textureInfo.label = "Far Field";
|
||||
far_field = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.render_pass = renderpass;
|
||||
framebufferInfo.attachments = { normal_field };
|
||||
|
||||
framebufferInfo.attachments = {normal_field};
|
||||
|
||||
normal_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
|
||||
framebufferInfo.attachments = { far_field };
|
||||
|
||||
|
||||
framebufferInfo.attachments = {far_field};
|
||||
|
||||
far_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
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 render_extent = prism::Extent();
|
||||
|
||||
|
||||
// render far field
|
||||
GFXRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.framebuffer = far_framebuffer;
|
||||
beginInfo.render_pass = renderpass;
|
||||
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = render_extent.width;
|
||||
viewport.height = render_extent.height;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(pipeline);
|
||||
|
||||
//command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
//command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
|
||||
|
||||
// command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
// command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
|
||||
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);
|
||||
|
||||
|
||||
command_buffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
|
||||
|
||||
command_buffer->draw(0, 4, 0, extent.width * extent.height);
|
||||
|
||||
|
||||
// render normal field
|
||||
beginInfo.framebuffer = normal_framebuffer;
|
||||
|
||||
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(pipeline);
|
||||
|
||||
//command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
//command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
|
||||
|
||||
// command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
// command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
|
||||
command_buffer->bind_texture(aperture_texture->handle, 2);
|
||||
|
||||
params.y = 1;
|
||||
|
||||
|
||||
command_buffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
|
||||
|
||||
command_buffer->draw(0, 4, 0, extent.width * extent.height);
|
||||
}
|
||||
|
|
|
@ -4,58 +4,58 @@
|
|||
|
||||
CameraFrustum extract_frustum(const Matrix4x4 combined) {
|
||||
CameraFrustum frustum;
|
||||
|
||||
|
||||
// left plane
|
||||
frustum.planes[0].a = combined.data[0][3] + combined.data[0][0];
|
||||
frustum.planes[0].b = combined.data[1][3] + combined.data[1][0];
|
||||
frustum.planes[0].c = combined.data[2][3] + combined.data[2][0];
|
||||
frustum.planes[0].d = combined.data[3][3] + combined.data[3][0];
|
||||
|
||||
|
||||
// right plane
|
||||
frustum.planes[1].a = combined.data[0][3] - combined.data[0][0];
|
||||
frustum.planes[1].b = combined.data[1][3] - combined.data[1][0];
|
||||
frustum.planes[1].c = combined.data[2][3] - combined.data[2][0];
|
||||
frustum.planes[1].d = combined.data[3][3] - combined.data[3][0];
|
||||
|
||||
|
||||
// top plane
|
||||
frustum.planes[2].a = combined.data[0][3] - combined.data[0][1];
|
||||
frustum.planes[2].b = combined.data[1][3] - combined.data[1][1];
|
||||
frustum.planes[2].c = combined.data[2][3] - combined.data[2][1];
|
||||
frustum.planes[2].d = combined.data[3][3] - combined.data[3][1];
|
||||
|
||||
|
||||
// bottom plane
|
||||
frustum.planes[3].a = combined.data[0][3] + combined.data[0][1];
|
||||
frustum.planes[3].b = combined.data[1][3] + combined.data[1][1];
|
||||
frustum.planes[3].c = combined.data[2][3] + combined.data[2][1];
|
||||
frustum.planes[3].d = combined.data[3][3] + combined.data[3][1];
|
||||
|
||||
|
||||
// near plane
|
||||
frustum.planes[4].a = combined.data[0][2];
|
||||
frustum.planes[4].b = combined.data[1][2];
|
||||
frustum.planes[4].c = combined.data[2][2];
|
||||
frustum.planes[4].d = combined.data[3][2];
|
||||
|
||||
|
||||
// far plane
|
||||
frustum.planes[5].a = combined.data[0][3] - combined.data[0][2];
|
||||
frustum.planes[5].b = combined.data[1][3] - combined.data[1][2];
|
||||
frustum.planes[5].c = combined.data[2][3] - combined.data[2][2];
|
||||
frustum.planes[5].d = combined.data[3][3] - combined.data[3][2];
|
||||
|
||||
|
||||
return frustum;
|
||||
}
|
||||
|
||||
CameraFrustum camera_extract_frustum(Scene& scene, prism::Object cam) {
|
||||
const auto camera_component = scene.get<Camera>(cam);
|
||||
const Matrix4x4 combined = camera_component.perspective * camera_component.view;
|
||||
|
||||
|
||||
return extract_frustum(combined);
|
||||
}
|
||||
|
||||
CameraFrustum normalize_frustum(const CameraFrustum& 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]);
|
||||
|
||||
|
||||
return normalized_frustum;
|
||||
}
|
||||
|
||||
|
@ -65,24 +65,24 @@ bool test_point_plane(const Plane& plane, const prism::float3& point) {
|
|||
|
||||
bool test_point_frustum(const CameraFrustum& frustum, const prism::float3& point) {
|
||||
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);
|
||||
|
||||
|
||||
return !inside_frustum;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
if(out == 8)
|
||||
|
||||
if (out == 8)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,6 @@ prism::aabb get_aabb_for_part(const Transform& transform, const Mesh::Part& part
|
|||
aabb.max = transform.get_world_position() + part.bounding_box.max;
|
||||
aabb.min *= transform.scale;
|
||||
aabb.max *= transform.scale;
|
||||
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "assertions.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "log.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "renderer.hpp"
|
||||
|
||||
void ImGuiPass::initialize() {
|
||||
|
@ -20,7 +20,7 @@ void ImGuiPass::initialize() {
|
|||
}
|
||||
|
||||
void ImGuiPass::create_render_target_resources(RenderTarget& target) {
|
||||
if(pipeline == nullptr) {
|
||||
if (pipeline == nullptr) {
|
||||
GFXGraphicsPipelineCreateInfo createInfo;
|
||||
createInfo.label = "ImGui";
|
||||
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.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_alpha = GFXBlendFactor::OneMinusSrcAlpha;
|
||||
|
||||
createInfo.shader_input.push_constants = {
|
||||
{sizeof(Matrix4x4), 0}
|
||||
};
|
||||
createInfo.shader_input.push_constants = {{sizeof(Matrix4x4), 0}};
|
||||
|
||||
createInfo.shader_input.bindings = {
|
||||
{1, GFXBindingType::PushConstant},
|
||||
{2, GFXBindingType::Texture}
|
||||
};
|
||||
createInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
|
||||
|
||||
pipeline = engine->get_gfx()->create_graphics_pipeline(createInfo);
|
||||
}
|
||||
|
@ -72,61 +67,74 @@ void ImGuiPass::create_render_target_resources(RenderTarget& target) {
|
|||
|
||||
void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& target, const platform::window_ptr index) {
|
||||
ImDrawData* draw_data = nullptr;
|
||||
if(!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) {
|
||||
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) {
|
||||
draw_data = ImGui::GetDrawData();
|
||||
} else {
|
||||
auto viewport = ImGui::FindViewportByPlatformHandle(index);
|
||||
if(viewport != nullptr)
|
||||
if (viewport != nullptr)
|
||||
draw_data = viewport->DrawData;
|
||||
}
|
||||
|
||||
if(draw_data == nullptr)
|
||||
|
||||
if (draw_data == nullptr)
|
||||
return;
|
||||
|
||||
|
||||
const int framebuffer_width = static_cast<int>(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
const int framebuffer_height = static_cast<int>(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
|
||||
|
||||
if (framebuffer_width <= 0 || framebuffer_height <= 0)
|
||||
return;
|
||||
|
||||
command_buffer->set_graphics_pipeline(pipeline);
|
||||
|
||||
if(draw_data->TotalVtxCount > 0)
|
||||
if (draw_data->TotalVtxCount > 0)
|
||||
update_buffers(target, *draw_data);
|
||||
|
||||
const Matrix4x4 projection = prism::orthographic(draw_data->DisplayPos.x,
|
||||
draw_data->DisplayPos.x + draw_data->DisplaySize.x,
|
||||
draw_data->DisplayPos.y + draw_data->DisplaySize.y,
|
||||
draw_data->DisplayPos.y,
|
||||
0.0f,
|
||||
1.0f);
|
||||
|
||||
const Matrix4x4 projection = prism::orthographic(
|
||||
draw_data->DisplayPos.x,
|
||||
draw_data->DisplayPos.x + draw_data->DisplaySize.x,
|
||||
draw_data->DisplayPos.y + draw_data->DisplaySize.y,
|
||||
draw_data->DisplayPos.y,
|
||||
0.0f,
|
||||
1.0f);
|
||||
|
||||
command_buffer->set_push_constant(&projection, sizeof(Matrix4x4));
|
||||
|
||||
|
||||
const ImVec2 clip_offset = draw_data->DisplayPos;
|
||||
const ImVec2 clip_scale = draw_data->FramebufferScale;
|
||||
|
||||
int vertex_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];
|
||||
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];
|
||||
|
||||
if(pcmd->TextureId != nullptr)
|
||||
if (pcmd->TextureId != nullptr)
|
||||
command_buffer->bind_texture((GFXTexture*)pcmd->TextureId, 2);
|
||||
|
||||
if(pcmd->UserCallback != nullptr) {
|
||||
|
||||
if (pcmd->UserCallback != nullptr) {
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
} else {
|
||||
ImVec2 clip_min((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);
|
||||
ImVec2 clip_min(
|
||||
(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
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
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_min.x < 0.0f) {
|
||||
clip_min.x = 0.0f;
|
||||
}
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
@ -138,14 +146,14 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ
|
|||
scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
|
||||
|
||||
command_buffer->set_scissor(scissor);
|
||||
|
||||
|
||||
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->draw_indexed(pcmd->ElemCount,
|
||||
(index_offset + pcmd->IdxOffset),
|
||||
(vertex_offset + pcmd->VtxOffset), 0);
|
||||
command_buffer->set_index_buffer(
|
||||
target.index_buffer[target.current_frame],
|
||||
sizeof(ImDrawIdx) == 2 ? IndexType::UINT16 : IndexType::UINT32);
|
||||
|
||||
command_buffer->draw_indexed(
|
||||
pcmd->ElemCount, (index_offset + pcmd->IdxOffset), (vertex_offset + pcmd->VtxOffset), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,17 +164,18 @@ void ImGuiPass::render_post(GFXCommandBuffer* command_buffer, RenderTarget& targ
|
|||
|
||||
void ImGuiPass::load_font(const std::string_view filename) {
|
||||
Expects(!filename.empty());
|
||||
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if(io.Fonts->Fonts.empty()) {
|
||||
if (io.Fonts->Fonts.empty()) {
|
||||
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->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();
|
||||
} else {
|
||||
prism::log("Failed to load font file for imgui!");
|
||||
|
@ -181,34 +190,38 @@ void ImGuiPass::create_font_texture() {
|
|||
unsigned char* pixels = nullptr;
|
||||
int width = -1, height = -1;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
|
||||
GFXTextureCreateInfo createInfo = {};
|
||||
createInfo.label = "ImGui Font";
|
||||
createInfo.width = width;
|
||||
createInfo.height = height;
|
||||
createInfo.format = GFXPixelFormat::RGBA8_UNORM;
|
||||
createInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
|
||||
|
||||
font_texture = engine->get_gfx()->create_texture(createInfo);
|
||||
engine->get_gfx()->copy_texture(font_texture, pixels, width * height * 4);
|
||||
|
||||
|
||||
io.Fonts->TexID = reinterpret_cast<void*>(font_texture);
|
||||
}
|
||||
|
||||
void ImGuiPass::update_buffers(RenderTarget& target, const ImDrawData& draw_data) {
|
||||
const int new_vertex_size = draw_data.TotalVtxCount * sizeof(ImDrawVert);
|
||||
const int new_index_size = draw_data.TotalIdxCount * sizeof(ImDrawIdx);
|
||||
|
||||
|
||||
Expects(new_vertex_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) {
|
||||
target.vertex_buffer[target.current_frame] = engine->get_gfx()->create_buffer(nullptr, new_vertex_size, true, GFXBufferUsage::Vertex);
|
||||
|
||||
if (target.vertex_buffer[target.current_frame] == nullptr ||
|
||||
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;
|
||||
}
|
||||
|
||||
if(target.index_buffer[target.current_frame] == nullptr || 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);
|
||||
|
||||
if (target.index_buffer[target.current_frame] == nullptr ||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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 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;
|
||||
|
||||
auto vtx_dst = (ImDrawVert*)vtx_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];
|
||||
|
||||
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
|
|
|
@ -1,37 +1,43 @@
|
|||
#include "materialcompiler.hpp"
|
||||
|
||||
#include "engine.hpp"
|
||||
#include "file.hpp"
|
||||
#include "log.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "string_utils.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
#include "string_utils.hpp"
|
||||
|
||||
ShaderSource get_shader(const std::string& filename, bool skinned, bool cubemap) {
|
||||
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);
|
||||
return {};
|
||||
}
|
||||
|
||||
ShaderStage stage;
|
||||
if(filename.find("vert") != std::string::npos) {
|
||||
if (filename.find("vert") != std::string::npos) {
|
||||
stage = ShaderStage::Vertex;
|
||||
} else {
|
||||
stage = ShaderStage::Fragment;
|
||||
}
|
||||
|
||||
CompileOptions options;
|
||||
if(skinned)
|
||||
if (skinned)
|
||||
options.add_definition("BONE");
|
||||
|
||||
if(cubemap)
|
||||
if (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
|
||||
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);
|
||||
|
||||
if(positions_only) {
|
||||
createInfo.vertex_input.inputs = {
|
||||
{position_buffer_index, sizeof(prism::float3)}
|
||||
};
|
||||
if (positions_only) {
|
||||
createInfo.vertex_input.inputs = {{position_buffer_index, sizeof(prism::float3)}};
|
||||
|
||||
createInfo.vertex_input.attributes = {
|
||||
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}
|
||||
};
|
||||
createInfo.vertex_input.attributes = {{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3}};
|
||||
} else {
|
||||
createInfo.vertex_input.inputs = {
|
||||
{position_buffer_index, sizeof(prism::float3)},
|
||||
{normal_buffer_index, sizeof(prism::float3)},
|
||||
{texcoord_buffer_index, sizeof(prism::float2)},
|
||||
{tangent_buffer_index, sizeof(prism::float3)},
|
||||
{bitangent_buffer_index, sizeof(prism::float3)}
|
||||
};
|
||||
{bitangent_buffer_index, sizeof(prism::float3)}};
|
||||
|
||||
createInfo.vertex_input.attributes = {
|
||||
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
|
||||
{normal_buffer_index, 1, 0, GFXVertexFormat::FLOAT3},
|
||||
{texcoord_buffer_index, 2, 0, GFXVertexFormat::FLOAT2},
|
||||
{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);
|
||||
|
@ -80,19 +80,16 @@ GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreate
|
|||
|
||||
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 = {
|
||||
{position_buffer_index, sizeof(prism::float3)},
|
||||
{bone_buffer_index, sizeof(BoneVertexData)}
|
||||
};
|
||||
{position_buffer_index, sizeof(prism::float3)}, {bone_buffer_index, sizeof(BoneVertexData)}};
|
||||
|
||||
createInfo.vertex_input.attributes = {
|
||||
{position_buffer_index, 0, 0, GFXVertexFormat::FLOAT3},
|
||||
{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 {
|
||||
createInfo.vertex_input.inputs = {
|
||||
{position_buffer_index, sizeof(prism::float3)},
|
||||
|
@ -100,8 +97,7 @@ GFXPipeline* MaterialCompiler::create_skinned_pipeline(GFXGraphicsPipelineCreate
|
|||
{texcoord_buffer_index, sizeof(prism::float2)},
|
||||
{tangent_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 = {
|
||||
{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);
|
||||
}
|
||||
|
||||
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 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 =
|
||||
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 = 2) const int max_spot_lights = 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) {
|
||||
if(!render_options.enable_ibl)
|
||||
if (!render_options.enable_ibl)
|
||||
use_ibl = false;
|
||||
|
||||
auto src = fmt::memory_buffer();
|
||||
|
||||
switch(render_options.shadow_filter) {
|
||||
switch (render_options.shadow_filter) {
|
||||
case ShadowFilter::None:
|
||||
format_to(std::back_inserter(src), "#define SHADOW_FILTER_NONE\n");
|
||||
break;
|
||||
|
@ -176,31 +173,35 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
|
|||
break;
|
||||
}
|
||||
|
||||
format_to(std::back_inserter(src),
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(layout (location = 0) in vec3 in_frag_pos;
|
||||
layout(location = 1) in vec3 in_normal;
|
||||
layout(location = 2) in vec2 in_uv;
|
||||
layout(location = 0) out vec4 frag_output;
|
||||
)");
|
||||
|
||||
if(render_options.enable_point_shadows) {
|
||||
format_to(std::back_inserter(src),
|
||||
R"(#define POINT_SHADOWS_SUPPORTED
|
||||
if (render_options.enable_point_shadows) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(#define POINT_SHADOWS_SUPPORTED
|
||||
layout (binding = 3) uniform samplerCubeArray point_shadow;
|
||||
)");
|
||||
}
|
||||
|
||||
format_to(std::back_inserter(src), struct_info);
|
||||
|
||||
if(use_ibl) {
|
||||
format_to(std::back_inserter(src),
|
||||
if (use_ibl) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(layout (binding = 7) uniform samplerCubeArray irrandianceSampler;
|
||||
layout (binding = 8) uniform samplerCubeArray prefilterSampler;
|
||||
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;
|
||||
layout(location = 5) in mat3 in_tbn;
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
format_to(std::back_inserter(src), "layout(binding = {}) uniform sampler2D normalTexture;\n", sampler_index++);
|
||||
}
|
||||
|
||||
if(use_ibl) {
|
||||
format_to(std::back_inserter(src),
|
||||
if (use_ibl) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(vec3 get_reflect(int i, vec3 final_normal) {{
|
||||
const vec3 direction = normalize(in_frag_pos - scene.camPos.xyz);
|
||||
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) {
|
||||
format_to(std::back_inserter(src),
|
||||
if (render_options.enable_normal_shadowing) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(float calculate_normal_lighting(in sampler2D normal_map, const vec3 normal, const vec3 light_dir) {{
|
||||
float height_scale = 0.8;
|
||||
float sample_count = 100.0;
|
||||
|
@ -278,8 +281,9 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
|
|||
)");
|
||||
}
|
||||
|
||||
if(use_ibl) {
|
||||
format_to(std::back_inserter(src),
|
||||
if (use_ibl) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
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 R = get_reflect(probe, surface_info.N);
|
||||
|
@ -293,25 +297,32 @@ 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) {
|
||||
format_to(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) {
|
||||
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);
|
||||
} else if (material.colorProperty.type == DataType::AssetTexture) {
|
||||
format_to(std::back_inserter(src), "vec3 Color = texture(colorTexture, in_uv).rgb;\n");
|
||||
} else if(material.colorProperty.type == DataType::Float) {
|
||||
format_to(std::back_inserter(src),"vec3 Color = vec3({}});\n", material.colorProperty.float_value);
|
||||
} 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),
|
||||
R"(vec3 final_diffuse_color = from_srgb_to_linear(Color);
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(vec3 final_diffuse_color = from_srgb_to_linear(Color);
|
||||
float final_roughness = scene.materials[inMaterialIndex].info.y;
|
||||
float final_metallic = scene.materials[inMaterialIndex].info.x;
|
||||
)");
|
||||
|
||||
if(material.normalProperty.type == DataType::AssetTexture) {
|
||||
format_to(std::back_inserter(src),
|
||||
R"(vec3 final_normal = texture(normalTexture, in_uv).rgb;
|
||||
if (material.normalProperty.type == DataType::AssetTexture) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(vec3 final_normal = texture(normalTexture, in_uv).rgb;
|
||||
final_normal = final_normal * 2.0 - 1.0;
|
||||
final_normal = in_tbn * final_normal;
|
||||
)");
|
||||
|
@ -319,8 +330,9 @@ 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),
|
||||
R"(ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness);
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(ComputedSurfaceInfo surface_info = compute_surface(final_diffuse_color.rgb, final_normal, final_metallic, final_roughness);
|
||||
vec3 Lo = vec3(0);
|
||||
for(int i = 0; i < scene.numLights; i++) {{
|
||||
const int type = int(scene.lights[i].positionType.w);
|
||||
|
@ -339,16 +351,22 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
|
|||
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) {
|
||||
format_to(std::back_inserter(src), "light_info.radiance *= calculate_normal_lighting(normalTexture, final_normal, light_info.direction);\n");
|
||||
if (render_options.enable_normal_mapping && material.normalProperty.type == DataType::AssetTexture &&
|
||||
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");
|
||||
|
||||
if(use_ibl) {
|
||||
format_to(std::back_inserter(src),
|
||||
R"(vec3 ambient = vec3(0.0);
|
||||
if (use_ibl) {
|
||||
format_to(
|
||||
std::back_inserter(src),
|
||||
R"(vec3 ambient = vec3(0.0);
|
||||
float sum = 0.0;
|
||||
for(int i = 0; i < max_probes; i++) {{
|
||||
if(scene.probes[i].position.w == 1) {{
|
||||
|
@ -376,5 +394,9 @@ ShaderSource MaterialCompiler::compile_material_fragment(Material& material, boo
|
|||
|
||||
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());
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
#include "renderer.hpp"
|
||||
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "math.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "dofpass.hpp"
|
||||
#include "file.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "imguipass.hpp"
|
||||
#include "frustum.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "imguipass.hpp"
|
||||
#include "materialcompiler.hpp"
|
||||
#include "math.hpp"
|
||||
#include "pass.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "scenecapture.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
#include "shadowpass.hpp"
|
||||
#include "smaapass.hpp"
|
||||
#include "scenecapture.hpp"
|
||||
#include "materialcompiler.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "dofpass.hpp"
|
||||
#include "frustum.hpp"
|
||||
#include "shadercompiler.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
using prism::renderer;
|
||||
|
||||
|
@ -59,7 +59,7 @@ struct SkyPushConstant {
|
|||
|
||||
renderer::renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
|
||||
Expects(gfx != nullptr);
|
||||
|
||||
|
||||
shader_compiler.set_include_path(prism::get_domain_path(prism::domain::base).string() + "/shaders");
|
||||
|
||||
create_dummy_texture();
|
||||
|
@ -68,12 +68,12 @@ renderer::renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) {
|
|||
shadow_pass = std::make_unique<ShadowPass>(gfx);
|
||||
scene_capture = std::make_unique<SceneCapture>(gfx);
|
||||
smaa_pass = std::make_unique<SMAAPass>(gfx);
|
||||
|
||||
if(enable_imgui)
|
||||
|
||||
if (enable_imgui)
|
||||
addPass<ImGuiPass>();
|
||||
|
||||
generate_brdf();
|
||||
|
||||
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.label = "Offscreen";
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::RGBA_32F);
|
||||
|
@ -94,28 +94,26 @@ renderer::~renderer() = default;
|
|||
|
||||
RenderTarget* renderer::allocate_render_target(const prism::Extent extent) {
|
||||
auto target = new RenderTarget();
|
||||
|
||||
|
||||
resize_render_target(*target, extent);
|
||||
|
||||
|
||||
render_targets.push_back(target);
|
||||
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
void renderer::resize_render_target(RenderTarget& target, const prism::Extent extent) {
|
||||
target.extent = extent;
|
||||
|
||||
|
||||
create_render_target_resources(target);
|
||||
smaa_pass->create_render_target_resources(target);
|
||||
create_post_pipelines();
|
||||
|
||||
for(auto& pass : passes)
|
||||
for (auto& pass : passes)
|
||||
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) {
|
||||
const auto extent = target.extent;
|
||||
|
@ -133,7 +131,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
|
||||
commandbuffer->set_viewport(viewport);
|
||||
|
||||
for (auto &pass: passes)
|
||||
for (auto& pass : passes)
|
||||
pass->render_post(commandbuffer, target, index);
|
||||
|
||||
return;
|
||||
|
@ -163,20 +161,20 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
|
||||
commandbuffer->set_render_pass(beginInfo);
|
||||
|
||||
const auto &cameras = scene->get_all<Camera>();
|
||||
for (auto&[obj, camera]: cameras) {
|
||||
const auto& cameras = scene->get_all<Camera>();
|
||||
for (auto& [obj, camera] : cameras) {
|
||||
const bool requires_limited_perspective = render_options.enable_depth_of_field;
|
||||
if (requires_limited_perspective) {
|
||||
camera.perspective = prism::perspective(radians(camera.fov),
|
||||
static_cast<float>(render_extent.width) /
|
||||
static_cast<float>(render_extent.height),
|
||||
camera.near,
|
||||
100.0f);
|
||||
camera.perspective = prism::perspective(
|
||||
radians(camera.fov),
|
||||
static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height),
|
||||
camera.near,
|
||||
100.0f);
|
||||
} else {
|
||||
camera.perspective = prism::infinite_perspective(radians(camera.fov),
|
||||
static_cast<float>(render_extent.width) /
|
||||
static_cast<float>(render_extent.height),
|
||||
camera.near);
|
||||
camera.perspective = prism::infinite_perspective(
|
||||
radians(camera.fov),
|
||||
static_cast<float>(render_extent.width) / static_cast<float>(render_extent.height),
|
||||
camera.near);
|
||||
}
|
||||
|
||||
camera.view = inverse(scene->get<Transform>(obj).model);
|
||||
|
@ -209,33 +207,30 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
||||
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 0);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1,
|
||||
sizeof(uint32_t) * 256);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
|
||||
|
||||
const float lum_range =
|
||||
render_options.max_luminance - render_options.min_luminance;
|
||||
const float lum_range = render_options.max_luminance - render_options.min_luminance;
|
||||
|
||||
prism::float4 params =
|
||||
prism::float4(render_options.min_luminance, 1.0f / lum_range,
|
||||
static_cast<float>(render_extent.width),
|
||||
static_cast<float>(render_extent.height));
|
||||
prism::float4 params = prism::float4(
|
||||
render_options.min_luminance,
|
||||
1.0f / lum_range,
|
||||
static_cast<float>(render_extent.width),
|
||||
static_cast<float>(render_extent.height));
|
||||
|
||||
commandbuffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
|
||||
commandbuffer->dispatch(
|
||||
static_cast<uint32_t>(
|
||||
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.width) / 16.0f)),
|
||||
static_cast<uint32_t>(std::ceil(static_cast<float>(render_extent.height) / 16.0f)),
|
||||
1);
|
||||
|
||||
commandbuffer->set_compute_pipeline(histogram_average_pipeline);
|
||||
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1,
|
||||
sizeof(uint32_t) * 256);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
|
||||
|
||||
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),
|
||||
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.z = render_options.exposure;
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
if (render_options.enable_depth_of_field)
|
||||
pc.options.w = 2;
|
||||
|
||||
pc.transform_ops.x = static_cast<float>(render_options.display_color_space);
|
||||
pc.transform_ops.y = static_cast<float>(render_options.tonemapping);
|
||||
|
||||
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
|
||||
// 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);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
if (render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dof_pass->far_field, 7);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 7);
|
||||
|
@ -325,7 +324,7 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
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);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 5);
|
||||
|
@ -338,113 +337,125 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
}
|
||||
|
||||
commandbuffer->push_group("Extra Passes");
|
||||
|
||||
for(auto& pass : passes)
|
||||
|
||||
for (auto& pass : passes)
|
||||
pass->render_post(commandbuffer, target, index);
|
||||
|
||||
|
||||
commandbuffer->pop_group();
|
||||
|
||||
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
|
||||
const auto frustum = normalize_frustum(camera_extract_frustum(scene, camera_object));
|
||||
|
||||
|
||||
SceneInformation sceneInfo = {};
|
||||
sceneInfo.lightspace = scene.lightSpace;
|
||||
sceneInfo.options = prism::float4(1, 0, 0, 0);
|
||||
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.vp = camera.perspective * camera.view;
|
||||
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;
|
||||
|
||||
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;
|
||||
sl.positionType = prism::float4(scene.get<Transform>(obj).get_world_position(), static_cast<float>(light.type));
|
||||
|
||||
prism::float3 front = prism::float3(0.0f, 0.0f, 1.0f) * scene.get<Transform>(obj).rotation;
|
||||
|
||||
|
||||
sl.directionPower = prism::float4(-front, light.power);
|
||||
sl.colorSize = prism::float4(utility::from_srgb_to_linear(light.color), radians(light.spot_size));
|
||||
|
||||
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++;
|
||||
|
||||
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];
|
||||
|
||||
|
||||
int last_probe = 0;
|
||||
for(const auto& [obj, probe] : scene.get_all<EnvironmentProbe>()) {
|
||||
for (const auto& [obj, probe] : scene.get_all<EnvironmentProbe>()) {
|
||||
SceneProbe p;
|
||||
p.position = prism::float4(scene.get<Transform>(obj).position, probe.is_sized ? 1.0f : 2.0f);
|
||||
p.size = prism::float4(probe.size, probe.intensity);
|
||||
|
||||
|
||||
sceneInfo.probes[last_probe++] = p;
|
||||
}
|
||||
|
||||
|
||||
int numMaterialsInBuffer = 0;
|
||||
std::map<Material*, int> material_indices;
|
||||
|
||||
|
||||
const auto& meshes = scene.get_all<Renderable>();
|
||||
for(const auto& [obj, mesh] : meshes) {
|
||||
if(!mesh.mesh)
|
||||
for (const auto& [obj, mesh] : meshes) {
|
||||
if (!mesh.mesh)
|
||||
continue;
|
||||
|
||||
if(mesh.materials.empty())
|
||||
|
||||
if (mesh.materials.empty())
|
||||
continue;
|
||||
|
||||
for(auto& material : mesh.materials) {
|
||||
if(!material)
|
||||
|
||||
for (auto& material : mesh.materials) {
|
||||
if (!material)
|
||||
continue;
|
||||
|
||||
if(material->static_pipeline == nullptr || material->skinned_pipeline == nullptr)
|
||||
|
||||
if (material->static_pipeline == nullptr || material->skinned_pipeline == nullptr)
|
||||
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.y = material->roughness;
|
||||
|
||||
material_indices[material.handle] = numMaterialsInBuffer++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct PushConstant {
|
||||
Matrix4x4 m;
|
||||
} pc;
|
||||
|
||||
|
||||
pc.m = scene.get<Transform>(obj).model;
|
||||
|
||||
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index);
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->normal_buffer, 0, normal_buffer_index);
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->texture_coord_buffer, 0, texcoord_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);
|
||||
|
||||
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_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;
|
||||
|
||||
if(material_index >= mesh.materials.size())
|
||||
|
||||
if (material_index >= mesh.materials.size())
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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_texture(scene.depthTexture, 2);
|
||||
|
@ -454,43 +465,47 @@ void renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
|
|||
command_buffer->bind_texture(scene.prefilteredCubeArray, 8);
|
||||
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->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;
|
||||
if(texture)
|
||||
if (texture)
|
||||
texture_to_bind = texture->handle;
|
||||
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SkyPushConstant pc;
|
||||
pc.view = matrix_from_quat(scene.get<Transform>(camera_object).rotation);
|
||||
pc.aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height);
|
||||
|
||||
for(const auto& [obj, light] : scene.get_all<Light>()) {
|
||||
if(light.type == Light::Type::Sun)
|
||||
|
||||
for (const auto& [obj, light] : scene.get_all<Light>()) {
|
||||
if (light.type == Light::Type::Sun)
|
||||
pc.sun_position_fov = prism::float4(scene.get<Transform>(obj).get_world_position(), radians(camera.fov));
|
||||
}
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(sky_pipeline);
|
||||
|
||||
|
||||
command_buffer->set_push_constant(&pc, sizeof(SkyPushConstant));
|
||||
|
||||
|
||||
command_buffer->draw(0, 4, 0, 1);
|
||||
|
||||
if(render_options.enable_extra_passes) {
|
||||
for(auto& pass : passes)
|
||||
|
||||
if (render_options.enable_extra_passes) {
|
||||
for (auto& pass : passes)
|
||||
pass->render_scene(scene, command_buffer);
|
||||
}
|
||||
|
||||
|
||||
gfx->copy_buffer(target.sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation));
|
||||
}
|
||||
|
||||
|
@ -498,34 +513,34 @@ void renderer::create_mesh_pipeline(Material& material) const {
|
|||
GFXShaderConstant materials_constant = {};
|
||||
materials_constant.type = GFXShaderConstant::Type::Integer;
|
||||
materials_constant.value = max_scene_materials;
|
||||
|
||||
|
||||
GFXShaderConstant lights_constant = {};
|
||||
lights_constant.index = 1;
|
||||
lights_constant.type = GFXShaderConstant::Type::Integer;
|
||||
lights_constant.value = max_scene_lights;
|
||||
|
||||
|
||||
GFXShaderConstant spot_lights_constant = {};
|
||||
spot_lights_constant.index = 2;
|
||||
spot_lights_constant.type = GFXShaderConstant::Type::Integer;
|
||||
spot_lights_constant.value = max_spot_shadows;
|
||||
|
||||
|
||||
GFXShaderConstant probes_constant = {};
|
||||
probes_constant.index = 3;
|
||||
probes_constant.type = GFXShaderConstant::Type::Integer;
|
||||
probes_constant.value = max_environment_probes;
|
||||
|
||||
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Mesh " + material.path;
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/mesh.vert"));
|
||||
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.fragment_constants = {materials_constant, lights_constant, spot_lights_constant, probes_constant};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(Matrix4x4), 0}
|
||||
};
|
||||
|
||||
|
||||
pipelineInfo.shaders.vertex_constants = {
|
||||
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 = {{sizeof(Matrix4x4), 0}};
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{1, GFXBindingType::StorageBuffer},
|
||||
{0, GFXBindingType::PushConstant},
|
||||
|
@ -534,15 +549,14 @@ void renderer::create_mesh_pipeline(Material& material) const {
|
|||
{6, GFXBindingType::Texture},
|
||||
{7, GFXBindingType::Texture},
|
||||
{8, GFXBindingType::Texture},
|
||||
{9, GFXBindingType::Texture}
|
||||
};
|
||||
|
||||
{9, GFXBindingType::Texture}};
|
||||
|
||||
pipelineInfo.render_pass = offscreen_render_pass;
|
||||
pipelineInfo.depth.depth_mode = GFXDepthMode::Less;
|
||||
pipelineInfo.rasterization.culling_mode = GFXCullingMode::Backface;
|
||||
pipelineInfo.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
||||
pipelineInfo.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
||||
|
||||
|
||||
pipelineInfo.shaders.fragment_src = material_compiler.compile_material_fragment(material);
|
||||
|
||||
for (auto [index, texture] : material.bound_textures) {
|
||||
|
@ -552,16 +566,17 @@ void renderer::create_mesh_pipeline(Material& material) const {
|
|||
|
||||
pipelineInfo.shader_input.bindings.push_back(binding);
|
||||
}
|
||||
|
||||
|
||||
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo);
|
||||
|
||||
|
||||
material.static_pipeline = static_pipeline;
|
||||
material.skinned_pipeline = skinned_pipeline;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
material.capture_pipeline = material_compiler.create_static_pipeline(pipelineInfo, false, true);
|
||||
|
@ -592,8 +607,7 @@ void renderer::create_render_target_resources(RenderTarget& target) {
|
|||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled |
|
||||
GFXTextureUsage::Storage;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::Storage;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
||||
|
@ -630,28 +644,26 @@ void renderer::create_render_target_resources(RenderTarget& target) {
|
|||
|
||||
target.mid_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
|
||||
target.sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage);
|
||||
}
|
||||
|
||||
void renderer::create_post_pipelines() {
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Post";
|
||||
|
||||
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/post.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/post.frag"));
|
||||
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{0, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::Texture}, // colorSampler
|
||||
{3, GFXBindingType::Texture}, // blendSampler
|
||||
{5, GFXBindingType::Texture} // sobelSampler
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(PostPushConstants), 0}
|
||||
{5, GFXBindingType::Texture} // sobelSampler
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(PostPushConstants), 0}};
|
||||
|
||||
post_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
|
||||
pipelineInfo.label = "Expose";
|
||||
|
@ -663,7 +675,7 @@ void renderer::create_post_pipelines() {
|
|||
{0, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::Texture}, // colorSampler
|
||||
{6, GFXBindingType::Texture}, // averageLuminanceSampler
|
||||
{7, GFXBindingType::Texture} // farFieldSampler
|
||||
{7, GFXBindingType::Texture} // farFieldSampler
|
||||
};
|
||||
|
||||
expose_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.fragment_src = register_shader("shaders/sky.frag");
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{0, GFXBindingType::PushConstant}
|
||||
};
|
||||
pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(SkyPushConstant), 0}
|
||||
};
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(SkyPushConstant), 0}};
|
||||
|
||||
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
|
||||
|
||||
|
@ -697,17 +705,17 @@ void renderer::generate_brdf() {
|
|||
renderPassInfo.will_use_in_shader = true;
|
||||
|
||||
brdf_render_pass = gfx->create_render_pass(renderPassInfo);
|
||||
|
||||
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "BRDF";
|
||||
|
||||
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/brdf.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/brdf.frag"));
|
||||
|
||||
|
||||
pipelineInfo.render_pass = brdf_render_pass;
|
||||
|
||||
brdf_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "BRDF LUT";
|
||||
textureInfo.format = GFXPixelFormat::R8G8_SFLOAT;
|
||||
|
@ -716,33 +724,33 @@ void renderer::generate_brdf() {
|
|||
textureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::Attachment;
|
||||
|
||||
brdf_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.attachments = {brdf_texture};
|
||||
framebufferInfo.render_pass = brdf_render_pass;
|
||||
|
||||
brdf_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
|
||||
|
||||
// render
|
||||
GFXCommandBuffer* command_buffer = gfx->acquire_command_buffer(false);
|
||||
|
||||
|
||||
GFXRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.render_pass = brdf_render_pass;
|
||||
beginInfo.framebuffer = brdf_framebuffer;
|
||||
beginInfo.render_area.extent = {brdf_resolution, brdf_resolution};
|
||||
|
||||
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(brdf_pipeline);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = brdf_resolution;
|
||||
viewport.height = brdf_resolution;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
command_buffer->draw(0, 4, 0, 1);
|
||||
|
||||
|
||||
gfx->submit(command_buffer, nullptr);
|
||||
}
|
||||
|
||||
|
@ -752,91 +760,93 @@ void renderer::create_histogram_resources() {
|
|||
create_info.compute_src = ShaderSource(prism::path("shaders/histogram.comp"));
|
||||
create_info.workgroup_size_x = 16;
|
||||
create_info.workgroup_size_y = 16;
|
||||
|
||||
create_info.shader_input.bindings = {
|
||||
{0, GFXBindingType::StorageImage},
|
||||
{1, GFXBindingType::StorageBuffer},
|
||||
{2, GFXBindingType::PushConstant}
|
||||
};
|
||||
|
||||
create_info.shader_input.push_constants = {
|
||||
{sizeof(prism::float4), 0}
|
||||
};
|
||||
|
||||
create_info.shader_input.bindings = {
|
||||
{0, GFXBindingType::StorageImage}, {1, GFXBindingType::StorageBuffer}, {2, GFXBindingType::PushConstant}};
|
||||
|
||||
create_info.shader_input.push_constants = {{sizeof(prism::float4), 0}};
|
||||
|
||||
histogram_pipeline = gfx->create_compute_pipeline(create_info);
|
||||
|
||||
create_info.label = "Histogram Average";
|
||||
create_info.compute_src = ShaderSource(prism::path("shaders/histogram-average.comp"));
|
||||
create_info.workgroup_size_x = 256;
|
||||
create_info.workgroup_size_y = 1;
|
||||
|
||||
|
||||
histogram_average_pipeline = gfx->create_compute_pipeline(create_info);
|
||||
|
||||
histogram_buffer = gfx->create_buffer(nullptr, sizeof(uint32_t) * 256, false, GFXBufferUsage::Storage);
|
||||
|
||||
|
||||
GFXTextureCreateInfo texture_info = {};
|
||||
texture_info.label = "Average Luminance Store";
|
||||
texture_info.width = 1;
|
||||
texture_info.height = 1;
|
||||
texture_info.format = GFXPixelFormat::R_16F;
|
||||
texture_info.usage = GFXTextureUsage::Sampled | GFXTextureUsage::ShaderWrite | GFXTextureUsage::Storage;
|
||||
|
||||
|
||||
average_luminance_texture = gfx->create_texture(texture_info);
|
||||
}
|
||||
|
||||
ShaderSource renderer::register_shader(const std::string_view shader_file) {
|
||||
if(!reloading_shader) {
|
||||
if (!reloading_shader) {
|
||||
RegisteredShader shader;
|
||||
shader.filename = shader_file;
|
||||
|
||||
|
||||
registered_shaders.push_back(shader);
|
||||
}
|
||||
|
||||
|
||||
std::string found_shader_source;
|
||||
for(auto& shader : registered_shaders) {
|
||||
if(shader.filename == shader_file) {
|
||||
for (auto& shader : registered_shaders) {
|
||||
if (shader.filename == shader_file) {
|
||||
found_shader_source = shader.injected_shader_source;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
prism::path base_shader_path = get_shader_source_directory();
|
||||
|
||||
|
||||
// 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));
|
||||
|
||||
|
||||
shader_compiler.set_include_path(base_shader_path.string());
|
||||
|
||||
|
||||
prism::path shader_path = prism::path(shader_file);
|
||||
|
||||
|
||||
ShaderStage stage = ShaderStage::Vertex;
|
||||
if(shader_path.extension() == ".vert")
|
||||
if (shader_path.extension() == ".vert")
|
||||
stage = ShaderStage::Vertex;
|
||||
else if(shader_path.extension() == ".frag")
|
||||
else if (shader_path.extension() == ".frag")
|
||||
stage = ShaderStage::Fragment;
|
||||
|
||||
if(found_shader_source.empty()) {
|
||||
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();
|
||||
if (found_shader_source.empty()) {
|
||||
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();
|
||||
} 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) {
|
||||
if(reloading_shader)
|
||||
void renderer::associate_shader_reload(
|
||||
const std::string_view shader_file,
|
||||
const std::function<void()>& reload_function) {
|
||||
if (reloading_shader)
|
||||
return;
|
||||
|
||||
for(auto& shader : registered_shaders) {
|
||||
if(shader.filename == shader_file)
|
||||
|
||||
for (auto& shader : registered_shaders) {
|
||||
if (shader.filename == shader_file)
|
||||
shader.reload_function = reload_function;
|
||||
}
|
||||
}
|
||||
|
||||
void renderer::reload_shader(const std::string_view shader_file, const std::string_view shader_source) {
|
||||
for(auto& shader : registered_shaders) {
|
||||
if(shader.filename == shader_file) {
|
||||
for (auto& shader : registered_shaders) {
|
||||
if (shader.filename == shader_file) {
|
||||
shader.injected_shader_source = shader_source;
|
||||
reloading_shader = true;
|
||||
shader.reload_function();
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#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 "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 {
|
||||
Matrix4x4 m, v;
|
||||
|
@ -56,19 +56,19 @@ struct FilterPushConstant {
|
|||
const int mipLevels = 5;
|
||||
|
||||
const std::array<Matrix4x4, 6> sceneTransforms = {
|
||||
prism::look_at(prism::float3(0), prism::float3(-1.0, 0.0, 0.0), prism::float3(0.0, -1.0, 0.0)), // right
|
||||
prism::look_at(prism::float3(0), prism::float3(1.0, 0.0, 0.0), prism::float3(0.0, -1.0, 0.0)), // left
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, -1.0, 0.0), prism::float3(0.0, 0.0, -1.0)), // top
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 1.0, 0.0), prism::float3(0.0, 0.0, 1.0)), // bottom
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, 1.0), prism::float3(0.0, -1.0, 0.0)), // back
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, -1.0), prism::float3(0.0, -1.0, 0.0)) // front
|
||||
prism::look_at(prism::float3(0), prism::float3(-1.0, 0.0, 0.0), prism::float3(0.0, -1.0, 0.0)), // right
|
||||
prism::look_at(prism::float3(0), prism::float3(1.0, 0.0, 0.0), prism::float3(0.0, -1.0, 0.0)), // left
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, -1.0, 0.0), prism::float3(0.0, 0.0, -1.0)), // top
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 1.0, 0.0), prism::float3(0.0, 0.0, 1.0)), // bottom
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, 1.0), prism::float3(0.0, -1.0, 0.0)), // back
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, -1.0), prism::float3(0.0, -1.0, 0.0)) // front
|
||||
};
|
||||
|
||||
inline AssetPtr<Mesh> cubeMesh;
|
||||
|
||||
SceneCapture::SceneCapture(GFX* gfx) {
|
||||
cubeMesh = assetm->get<Mesh>(prism::base_domain / "models/cube.model");
|
||||
|
||||
|
||||
// render pass
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.label = "Scene Capture Cube";
|
||||
|
@ -77,7 +77,7 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
|||
renderPassInfo.will_use_in_shader = true;
|
||||
|
||||
renderPass = gfx->create_render_pass(renderPassInfo);
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Scene Capture Color";
|
||||
textureInfo.width = scene_cubemap_resolution;
|
||||
|
@ -85,9 +85,9 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
|||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
offscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXTextureCreateInfo depthTextureInfo = {};
|
||||
depthTextureInfo.label = "Scene Capture Depth";
|
||||
depthTextureInfo.width = scene_cubemap_resolution;
|
||||
|
@ -95,29 +95,30 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
|||
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
depthTextureInfo.usage = GFXTextureUsage::Attachment;
|
||||
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
offscreenDepth = gfx->create_texture(depthTextureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo info;
|
||||
info.attachments = {offscreenTexture, offscreenDepth};
|
||||
info.render_pass = renderPass;
|
||||
|
||||
|
||||
offscreenFramebuffer = gfx->create_framebuffer(info);
|
||||
|
||||
|
||||
GFXTextureCreateInfo cubeTextureInfo = {};
|
||||
cubeTextureInfo.label = "Scene Capture Cubemap";
|
||||
cubeTextureInfo.type = GFXTextureType::Cubemap;
|
||||
cubeTextureInfo.width = scene_cubemap_resolution;
|
||||
cubeTextureInfo.height = scene_cubemap_resolution;
|
||||
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.mip_count = mipLevels;
|
||||
|
||||
|
||||
environmentCube = gfx->create_texture(cubeTextureInfo);
|
||||
|
||||
|
||||
sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage);
|
||||
|
||||
|
||||
createSkyResources();
|
||||
createIrradianceResources();
|
||||
createPrefilterResources();
|
||||
|
@ -125,8 +126,8 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
|||
|
||||
void SceneCapture::create_scene_resources(Scene& scene) {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
if(gfx->supports_feature(GFXFeature::CubemapArray)) {
|
||||
|
||||
if (gfx->supports_feature(GFXFeature::CubemapArray)) {
|
||||
GFXTextureCreateInfo cubeTextureInfo = {};
|
||||
cubeTextureInfo.label = "Irriadiance Cubemap";
|
||||
cubeTextureInfo.type = GFXTextureType::CubemapArray;
|
||||
|
@ -136,9 +137,9 @@ void SceneCapture::create_scene_resources(Scene& scene) {
|
|||
cubeTextureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
cubeTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
cubeTextureInfo.array_length = max_environment_probes;
|
||||
|
||||
|
||||
scene.irradianceCubeArray = gfx->create_texture(cubeTextureInfo);
|
||||
|
||||
|
||||
cubeTextureInfo = {};
|
||||
cubeTextureInfo.label = "Prefiltered Cubemap";
|
||||
cubeTextureInfo.type = GFXTextureType::CubemapArray;
|
||||
|
@ -149,143 +150,146 @@ void SceneCapture::create_scene_resources(Scene& scene) {
|
|||
cubeTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
cubeTextureInfo.array_length = max_environment_probes;
|
||||
cubeTextureInfo.mip_count = mipLevels;
|
||||
|
||||
|
||||
scene.prefilteredCubeArray = gfx->create_texture(cubeTextureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
|
||||
if(scene->probe_refresh_timer > 0) {
|
||||
if (scene->probe_refresh_timer > 0) {
|
||||
scene->probe_refresh_timer--;
|
||||
return;
|
||||
}
|
||||
|
||||
int last_probe = 0;
|
||||
auto probes = scene->get_all<EnvironmentProbe>();
|
||||
for(auto [obj, probe] : probes) {
|
||||
if(last_probe > max_environment_probes)
|
||||
for (auto [obj, probe] : probes) {
|
||||
if (last_probe > max_environment_probes)
|
||||
return;
|
||||
|
||||
if(scene->environment_dirty[last_probe]) {
|
||||
|
||||
if (scene->environment_dirty[last_probe]) {
|
||||
std::map<Material*, int> material_indices;
|
||||
int numMaterialsInBuffer = 0;
|
||||
|
||||
|
||||
const prism::float3 lightPos = scene->get<Transform>(obj).get_world_position();
|
||||
|
||||
|
||||
const Matrix4x4 projection = prism::infinite_perspective(radians(90.0f), 1.0f, 0.1f);
|
||||
const Matrix4x4 model = prism::translate(Matrix4x4(), prism::float3(-lightPos.x, -lightPos.y, -lightPos.z));
|
||||
|
||||
|
||||
SceneInformation sceneInfo = {};
|
||||
sceneInfo.lightspace = scene->lightSpace;
|
||||
sceneInfo.numLights = 0;
|
||||
sceneInfo.camPos = lightPos;
|
||||
sceneInfo.vp = projection;
|
||||
|
||||
for(const auto [obj, light] : scene->get_all<Light>()) {
|
||||
|
||||
for (const auto [obj, light] : scene->get_all<Light>()) {
|
||||
SceneLight sl;
|
||||
sl.positionType = prism::float4(scene->get<Transform>(obj).get_world_position(), (int)light.type);
|
||||
|
||||
prism::float3 front = prism::float3(0.0f, 0.0f, 1.0f) * scene->get<Transform>(obj).rotation;
|
||||
|
||||
|
||||
sl.directionPower = prism::float4(-front, light.power);
|
||||
sl.colorSize = prism::float4(utility::from_srgb_to_linear(light.color), radians(light.spot_size));
|
||||
sl.shadowsEnable = prism::float4(light.enable_shadows, radians(light.size), 0, 0);
|
||||
|
||||
|
||||
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];
|
||||
|
||||
|
||||
const auto& meshes = scene->get_all<Renderable>();
|
||||
|
||||
for(const auto [obj, mesh] : meshes) {
|
||||
if(!mesh.mesh)
|
||||
|
||||
for (const auto [obj, mesh] : meshes) {
|
||||
if (!mesh.mesh)
|
||||
continue;
|
||||
|
||||
if(mesh.materials.empty())
|
||||
|
||||
if (mesh.materials.empty())
|
||||
continue;
|
||||
|
||||
for(const auto& material : mesh.materials) {
|
||||
if(!material)
|
||||
|
||||
for (const auto& material : mesh.materials) {
|
||||
if (!material)
|
||||
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);
|
||||
|
||||
if(!material_indices.count(material.handle)) {
|
||||
if (!material_indices.count(material.handle)) {
|
||||
material_indices[material.handle] = numMaterialsInBuffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const auto render_face = [this, command_buffer, scene, &meshes, &model, &probe = probe](int face) {
|
||||
const auto frustum = normalize_frustum(extract_frustum(sceneTransforms[face]));
|
||||
|
||||
|
||||
GFXRenderPassBeginInfo info = {};
|
||||
info.framebuffer = offscreenFramebuffer;
|
||||
info.render_pass = renderPass;
|
||||
info.render_area.extent = {scene_cubemap_resolution, scene_cubemap_resolution};
|
||||
|
||||
|
||||
command_buffer->set_render_pass(info);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = scene_cubemap_resolution;
|
||||
viewport.height = scene_cubemap_resolution;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
if(probe.is_sized) {
|
||||
for(const auto [obj, mesh] : meshes) {
|
||||
if(!mesh.mesh)
|
||||
|
||||
if (probe.is_sized) {
|
||||
for (const auto [obj, mesh] : meshes) {
|
||||
if (!mesh.mesh)
|
||||
continue;
|
||||
|
||||
if(mesh.materials.empty())
|
||||
|
||||
if (mesh.materials.empty())
|
||||
continue;
|
||||
|
||||
|
||||
PushConstant pc;
|
||||
pc.m = scene->get<Transform>(obj).model;
|
||||
pc.v = sceneTransforms[face] * model;
|
||||
|
||||
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index);
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->normal_buffer, 0, normal_buffer_index);
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->texture_coord_buffer, 0, texcoord_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_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
|
||||
|
||||
if(mesh.mesh->bones.empty()) {
|
||||
if (mesh.mesh->bones.empty()) {
|
||||
for (auto& part : mesh.mesh->parts) {
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(mesh.materials[material_index]->capture_pipeline);
|
||||
|
||||
|
||||
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
|
||||
command_buffer->bind_texture(scene->depthTexture, 2);
|
||||
command_buffer->bind_texture(scene->pointLightArray, 3);
|
||||
command_buffer->bind_texture(scene->spotLightArray, 6);
|
||||
|
||||
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;
|
||||
if(texture)
|
||||
if (texture)
|
||||
texture_to_bind = texture->handle;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,30 +297,32 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
|
|||
|
||||
// render sky
|
||||
SkyPushConstant pc;
|
||||
|
||||
|
||||
pc.view = sceneTransforms[face];
|
||||
pc.aspect = 1.0f;
|
||||
|
||||
for(auto& [obj, light] : scene->get_all<Light>()) {
|
||||
if(light.type == Light::Type::Sun)
|
||||
pc.sun_position_fov = prism::float4(scene->get<Transform>(obj).get_world_position(), radians(90.0f));
|
||||
|
||||
for (auto& [obj, light] : scene->get_all<Light>()) {
|
||||
if (light.type == Light::Type::Sun)
|
||||
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_push_constant(&pc, sizeof(SkyPushConstant));
|
||||
|
||||
|
||||
command_buffer->draw(0, 4, 0, 1);
|
||||
|
||||
|
||||
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));
|
||||
|
||||
for (int face = 0; face < 6; face++)
|
||||
render_face(face);
|
||||
|
||||
|
||||
command_buffer->generate_mipmaps(environmentCube, mipLevels);
|
||||
|
||||
// calculate irradiance
|
||||
|
@ -325,15 +331,15 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
|
|||
info.framebuffer = irradianceFramebuffer;
|
||||
info.render_pass = irradianceRenderPass;
|
||||
info.render_area.extent = {irradiance_cubemap_resolution, irradiance_cubemap_resolution};
|
||||
|
||||
|
||||
command_buffer->set_render_pass(info);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = irradiance_cubemap_resolution;
|
||||
viewport.height = irradiance_cubemap_resolution;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
Matrix4x4 mvp = projection * sceneTransforms[face];
|
||||
|
||||
command_buffer->set_graphics_pipeline(irradiancePipeline);
|
||||
|
@ -343,42 +349,43 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
|
|||
|
||||
command_buffer->bind_texture(environmentCube, 2);
|
||||
command_buffer->set_push_constant(&mvp, sizeof(Matrix4x4));
|
||||
|
||||
|
||||
command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0);
|
||||
|
||||
|
||||
command_buffer->end_render_pass();
|
||||
command_buffer->copy_texture(irradianceOffscreenTexture,
|
||||
irradiance_cubemap_resolution,
|
||||
irradiance_cubemap_resolution,
|
||||
scene->irradianceCubeArray,
|
||||
face, // slice
|
||||
last_probe, // layer
|
||||
0); // level
|
||||
command_buffer->copy_texture(
|
||||
irradianceOffscreenTexture,
|
||||
irradiance_cubemap_resolution,
|
||||
irradiance_cubemap_resolution,
|
||||
scene->irradianceCubeArray,
|
||||
face, // slice
|
||||
last_probe, // layer
|
||||
0); // level
|
||||
};
|
||||
|
||||
|
||||
for (int face = 0; face < 6; face++)
|
||||
convulute_face(face);
|
||||
|
||||
|
||||
// prefilter
|
||||
const auto prefilter_face = [this, scene, command_buffer, &last_probe, projection](int face, int mip) {
|
||||
GFXRenderPassBeginInfo info = {};
|
||||
info.framebuffer = prefilteredFramebuffer;
|
||||
info.render_pass = irradianceRenderPass;
|
||||
|
||||
|
||||
const uint32_t resolution = scene_cubemap_resolution * std::pow(0.5, mip);
|
||||
info.render_area.extent = {resolution, resolution};
|
||||
|
||||
|
||||
command_buffer->set_render_pass(info);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = resolution;
|
||||
viewport.height = resolution;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
command_buffer->set_vertex_buffer(cubeMesh->position_buffer, 0, 0);
|
||||
command_buffer->set_index_buffer(cubeMesh->index_buffer, IndexType::UINT32);
|
||||
|
||||
|
||||
FilterPushConstant pc;
|
||||
pc.mvp = projection * sceneTransforms[face];
|
||||
pc.roughness = ((float)mip) / (float)(mipLevels - 1);
|
||||
|
@ -386,23 +393,28 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
|
|||
command_buffer->set_graphics_pipeline(prefilterPipeline);
|
||||
command_buffer->bind_texture(environmentCube, 2);
|
||||
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||
|
||||
|
||||
command_buffer->draw_indexed(cubeMesh->num_indices, 0, 0, 0);
|
||||
|
||||
|
||||
command_buffer->end_render_pass();
|
||||
command_buffer->copy_texture(prefilteredOffscreenTexture,
|
||||
resolution, resolution,
|
||||
scene->prefilteredCubeArray, face, last_probe, mip);
|
||||
command_buffer->copy_texture(
|
||||
prefilteredOffscreenTexture,
|
||||
resolution,
|
||||
resolution,
|
||||
scene->prefilteredCubeArray,
|
||||
face,
|
||||
last_probe,
|
||||
mip);
|
||||
};
|
||||
|
||||
for(int mip = 0; mip < mipLevels; mip++) {
|
||||
for(int i = 0; i < 6; i++)
|
||||
|
||||
for (int mip = 0; mip < mipLevels; mip++) {
|
||||
for (int i = 0; i < 6; i++)
|
||||
prefilter_face(i, mip);
|
||||
}
|
||||
|
||||
|
||||
scene->environment_dirty[last_probe] = false;
|
||||
}
|
||||
|
||||
|
||||
last_probe++;
|
||||
}
|
||||
}
|
||||
|
@ -411,26 +423,22 @@ void SceneCapture::createSkyResources() {
|
|||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Sky Scene Capture";
|
||||
pipelineInfo.render_pass = renderPass;
|
||||
|
||||
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/sky.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/sky.frag"));
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{0, GFXBindingType::PushConstant}
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(SkyPushConstant), 0}
|
||||
};
|
||||
|
||||
|
||||
pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(SkyPushConstant), 0}};
|
||||
|
||||
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
|
||||
|
||||
|
||||
skyPipeline = engine->get_gfx()->create_graphics_pipeline(pipelineInfo);
|
||||
}
|
||||
|
||||
void SceneCapture::createIrradianceResources() {
|
||||
GFX* gfx = engine->get_gfx();
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Irradiance Offscreen";
|
||||
textureInfo.width = irradiance_cubemap_resolution;
|
||||
|
@ -438,9 +446,9 @@ void SceneCapture::createIrradianceResources() {
|
|||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
irradianceOffscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.label = "Irradiance";
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::R8G8B8A8_UNORM);
|
||||
|
@ -451,41 +459,36 @@ void SceneCapture::createIrradianceResources() {
|
|||
GFXFramebufferCreateInfo info;
|
||||
info.attachments = {irradianceOffscreenTexture};
|
||||
info.render_pass = irradianceRenderPass;
|
||||
|
||||
|
||||
irradianceFramebuffer = gfx->create_framebuffer(info);
|
||||
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Irradiance Convolution";
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/irradiance.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/irradiance.frag"));
|
||||
|
||||
|
||||
GFXVertexInput input = {};
|
||||
input.stride = sizeof(prism::float3);
|
||||
|
||||
|
||||
pipelineInfo.vertex_input.inputs.push_back(input);
|
||||
|
||||
|
||||
GFXVertexAttribute positionAttribute = {};
|
||||
positionAttribute.format = GFXVertexFormat::FLOAT3;
|
||||
|
||||
pipelineInfo.vertex_input.attributes.push_back(positionAttribute);
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(Matrix4x4), 0}
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{1, GFXBindingType::PushConstant},
|
||||
{2, GFXBindingType::Texture}
|
||||
};
|
||||
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(Matrix4x4), 0}};
|
||||
|
||||
pipelineInfo.shader_input.bindings = {{1, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
|
||||
|
||||
pipelineInfo.render_pass = irradianceRenderPass;
|
||||
|
||||
|
||||
irradiancePipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
}
|
||||
|
||||
void SceneCapture::createPrefilterResources() {
|
||||
GFX* gfx = engine->get_gfx();
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Prefiltered Offscreen";
|
||||
textureInfo.width = scene_cubemap_resolution;
|
||||
|
@ -493,46 +496,41 @@ void SceneCapture::createPrefilterResources() {
|
|||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
prefilteredOffscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo info;
|
||||
info.attachments = {prefilteredOffscreenTexture};
|
||||
info.render_pass = irradianceRenderPass;
|
||||
|
||||
|
||||
prefilteredFramebuffer = gfx->create_framebuffer(info);
|
||||
|
||||
|
||||
GFXShaderConstant size_constant = {};
|
||||
size_constant.type = GFXShaderConstant::Type::Integer;
|
||||
size_constant.value = scene_cubemap_resolution;
|
||||
|
||||
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Prefilter";
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/filter.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/filter.frag"));
|
||||
|
||||
|
||||
pipelineInfo.shaders.fragment_constants = {size_constant};
|
||||
|
||||
|
||||
GFXVertexInput input;
|
||||
input.stride = sizeof(prism::float3);
|
||||
|
||||
|
||||
pipelineInfo.vertex_input.inputs.push_back(input);
|
||||
|
||||
|
||||
GFXVertexAttribute positionAttribute;
|
||||
positionAttribute.format = GFXVertexFormat::FLOAT3;
|
||||
|
||||
|
||||
pipelineInfo.vertex_input.attributes.push_back(positionAttribute);
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(FilterPushConstant), 0}
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{0, GFXBindingType::PushConstant},
|
||||
{2, GFXBindingType::Texture}
|
||||
};
|
||||
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(FilterPushConstant), 0}};
|
||||
|
||||
pipelineInfo.shader_input.bindings = {{0, GFXBindingType::PushConstant}, {2, GFXBindingType::Texture}};
|
||||
|
||||
pipelineInfo.render_pass = irradianceRenderPass;
|
||||
|
||||
|
||||
prefilterPipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
#include "shadowpass.hpp"
|
||||
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "materialcompiler.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "frustum.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "materialcompiler.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "scene.hpp"
|
||||
|
||||
struct PushConstant {
|
||||
Matrix4x4 mvp, model;
|
||||
};
|
||||
|
||||
const std::array<Matrix4x4, 6> shadowTransforms = {
|
||||
prism::look_at(prism::float3(0), prism::float3(1.0, 0.0, 0.0), prism::float3(0.0, 1.0, 0.0)), // right
|
||||
prism::look_at(prism::float3(0), prism::float3(-1.0, 0.0, 0.0), prism::float3(0.0, 1.0, 0.0)), // left
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 1.0, 0.0), prism::float3(0.0, 0.0, -1.0)), // top
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, -1.0, 0.0), prism::float3(0.0, 0.0, 1.0)), // bottom
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, 1.0), prism::float3(0.0, 1.0, 0.0)), // back
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, -1.0), prism::float3(0.0, 1.0, 0.0)) // front
|
||||
prism::look_at(prism::float3(0), prism::float3(1.0, 0.0, 0.0), prism::float3(0.0, 1.0, 0.0)), // right
|
||||
prism::look_at(prism::float3(0), prism::float3(-1.0, 0.0, 0.0), prism::float3(0.0, 1.0, 0.0)), // left
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 1.0, 0.0), prism::float3(0.0, 0.0, -1.0)), // top
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, -1.0, 0.0), prism::float3(0.0, 0.0, 1.0)), // bottom
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, 1.0), prism::float3(0.0, 1.0, 0.0)), // back
|
||||
prism::look_at(prism::float3(0), prism::float3(0.0, 0.0, -1.0), prism::float3(0.0, 1.0, 0.0)) // front
|
||||
};
|
||||
|
||||
ShadowPass::ShadowPass(GFX* gfx) {
|
||||
Expects(gfx != nullptr);
|
||||
Expects(render_options.shadow_resolution > 0);
|
||||
|
||||
|
||||
create_render_passes();
|
||||
create_pipelines();
|
||||
create_offscreen_resources();
|
||||
|
@ -33,7 +33,7 @@ ShadowPass::ShadowPass(GFX* gfx) {
|
|||
|
||||
void ShadowPass::create_scene_resources(Scene& scene) {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
|
||||
// sun light
|
||||
{
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
|
@ -46,16 +46,16 @@ void ShadowPass::create_scene_resources(Scene& scene) {
|
|||
textureInfo.border_color = GFXBorderColor::OpaqueWhite;
|
||||
|
||||
scene.depthTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo info;
|
||||
info.attachments = {scene.depthTexture};
|
||||
info.render_pass = render_pass;
|
||||
|
||||
|
||||
scene.framebuffer = gfx->create_framebuffer(info);
|
||||
}
|
||||
|
||||
|
||||
// point lights
|
||||
if(gfx->supports_feature(GFXFeature::CubemapArray)) {
|
||||
if (gfx->supports_feature(GFXFeature::CubemapArray)) {
|
||||
GFXTextureCreateInfo cubeTextureInfo = {};
|
||||
cubeTextureInfo.label = "Point Light Array";
|
||||
cubeTextureInfo.type = GFXTextureType::CubemapArray;
|
||||
|
@ -69,7 +69,7 @@ void ShadowPass::create_scene_resources(Scene& scene) {
|
|||
|
||||
scene.pointLightArray = gfx->create_texture(cubeTextureInfo);
|
||||
}
|
||||
|
||||
|
||||
// spot lights
|
||||
{
|
||||
GFXTextureCreateInfo spotTextureInfo = {};
|
||||
|
@ -91,17 +91,17 @@ void ShadowPass::render(GFXCommandBuffer* command_buffer, Scene& scene) {
|
|||
last_spot_light = 0;
|
||||
last_point_light = 0;
|
||||
|
||||
if(scene.shadow_refresh_timer > 0) {
|
||||
if (scene.shadow_refresh_timer > 0) {
|
||||
scene.shadow_refresh_timer--;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto lights = scene.get_all<Light>();
|
||||
for(auto [obj, light] : lights) {
|
||||
if(!light.enable_shadows)
|
||||
for (auto [obj, light] : lights) {
|
||||
if (!light.enable_shadows)
|
||||
continue;
|
||||
|
||||
switch(light.type) {
|
||||
switch (light.type) {
|
||||
case Light::Type::Sun:
|
||||
render_sun(command_buffer, scene, obj, light);
|
||||
break;
|
||||
|
@ -115,21 +115,29 @@ 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) {
|
||||
for(auto [obj, mesh] : scene.get_all<Renderable>()) {
|
||||
if(!mesh.mesh)
|
||||
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) {
|
||||
for (auto [obj, mesh] : scene.get_all<Renderable>()) {
|
||||
if (!mesh.mesh)
|
||||
continue;
|
||||
|
||||
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->position_buffer, 0, position_buffer_index);
|
||||
|
||||
|
||||
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
|
||||
|
||||
|
||||
PushConstant pc;
|
||||
pc.mvp = light_matrix * model * scene.get<Transform>(obj).model;
|
||||
pc.model = scene.get<Transform>(obj).model;
|
||||
|
||||
if(mesh.mesh->bones.empty()) {
|
||||
switch(type) {
|
||||
|
||||
if (mesh.mesh->bones.empty()) {
|
||||
switch (type) {
|
||||
case Light::Type::Sun:
|
||||
command_buffer->set_graphics_pipeline(static_sun_pipeline);
|
||||
break;
|
||||
|
@ -140,20 +148,21 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
|
|||
command_buffer->set_graphics_pipeline(static_point_pipeline);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float4) * max_point_shadows);
|
||||
|
||||
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance);
|
||||
}
|
||||
} else {
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case Light::Type::Sun:
|
||||
command_buffer->set_graphics_pipeline(skinned_sun_pipeline);
|
||||
break;
|
||||
|
@ -166,16 +175,17 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
|
|||
}
|
||||
|
||||
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(prism::float4) * max_point_shadows);
|
||||
|
||||
|
||||
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||
|
||||
|
||||
command_buffer->set_vertex_buffer(mesh.mesh->bone_buffer, 0, bone_buffer_index);
|
||||
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128);
|
||||
command_buffer->draw_indexed(part.index_count, part.index_offset, part.vertex_offset, base_instance);
|
||||
}
|
||||
|
@ -184,36 +194,38 @@ 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) {
|
||||
if(scene.sun_light_dirty || light.use_dynamic_shadows) {
|
||||
if (scene.sun_light_dirty || light.use_dynamic_shadows) {
|
||||
GFXRenderPassBeginInfo info = {};
|
||||
info.framebuffer = scene.framebuffer;
|
||||
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);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_options.shadow_resolution);
|
||||
viewport.height = static_cast<float>(render_options.shadow_resolution);
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
const prism::float3 lightPos = scene.get<Transform>(light_object).position;
|
||||
|
||||
|
||||
const Matrix4x4 projection = prism::orthographic(-25.0f, 25.0f, -25.0f, 25.0f, 0.1f, 100.0f);
|
||||
const Matrix4x4 view = prism::look_at(lightPos, prism::float3(0), prism::float3(0, 1, 0));
|
||||
|
||||
|
||||
const Matrix4x4 realMVP = projection * view;
|
||||
|
||||
|
||||
scene.lightSpace = projection;
|
||||
scene.lightSpace[1][1] *= -1;
|
||||
scene.lightSpace = scene.lightSpace * 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);
|
||||
|
||||
|
||||
scene.sun_light_dirty = false;
|
||||
|
||||
command_buffer->end_render_pass();
|
||||
|
@ -221,96 +233,136 @@ 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) {
|
||||
if((last_spot_light + 1) == max_spot_shadows)
|
||||
if ((last_spot_light + 1) == max_spot_shadows)
|
||||
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 = {};
|
||||
info.framebuffer = offscreen_framebuffer;
|
||||
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);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_options.shadow_resolution);
|
||||
viewport.height = static_cast<float>(render_options.shadow_resolution);
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
const Matrix4x4 perspective = prism::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f);
|
||||
|
||||
|
||||
const Matrix4x4 realMVP = perspective * inverse(scene.get<Transform>(light_object).model);
|
||||
|
||||
|
||||
scene.spotLightSpaces[last_spot_light] = perspective;
|
||||
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);
|
||||
|
||||
const auto frustum = normalize_frustum(extract_frustum(perspective * inverse(scene.get<Transform>(light_object).model)));
|
||||
|
||||
if(light.enable_shadows)
|
||||
render_meshes(command_buffer, scene, realMVP, Matrix4x4(), scene.get<Transform>(light_object).get_world_position(), Light::Type::Spot, frustum, 0);
|
||||
|
||||
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)));
|
||||
|
||||
if (light.enable_shadows)
|
||||
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->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;
|
||||
}
|
||||
|
||||
|
||||
last_spot_light++;
|
||||
}
|
||||
|
||||
void ShadowPass::render_point(GFXCommandBuffer* command_buffer, Scene& scene, prism::Object light_object, Light& light) {
|
||||
if(!render_options.enable_point_shadows)
|
||||
return;
|
||||
|
||||
if((last_point_light + 1) == max_point_shadows)
|
||||
void ShadowPass::render_point(
|
||||
GFXCommandBuffer* command_buffer,
|
||||
Scene& scene,
|
||||
prism::Object light_object,
|
||||
Light& light) {
|
||||
if (!render_options.enable_point_shadows)
|
||||
return;
|
||||
|
||||
if(point_location_map == nullptr)
|
||||
if ((last_point_light + 1) == max_point_shadows)
|
||||
return;
|
||||
|
||||
if(scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) {
|
||||
|
||||
if (point_location_map == nullptr)
|
||||
return;
|
||||
|
||||
if (scene.point_light_dirty[last_point_light] || light.use_dynamic_shadows) {
|
||||
const prism::float3 lightPos = scene.get<Transform>(light_object).get_world_position();
|
||||
|
||||
(point_location_map + last_point_light)->xyz = lightPos;
|
||||
|
||||
for(int face = 0; face < 6; face++) {
|
||||
for (int face = 0; face < 6; face++) {
|
||||
GFXRenderPassBeginInfo info = {};
|
||||
info.framebuffer = offscreen_framebuffer;
|
||||
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);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_options.shadow_resolution);
|
||||
viewport.height = static_cast<float>(render_options.shadow_resolution);
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
const Matrix4x4 projection = prism::perspective(radians(90.0f), 1.0f, 0.1f, 100.0f);
|
||||
const Matrix4x4 model = inverse(scene.get<Transform>(light_object).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->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;
|
||||
}
|
||||
|
||||
|
||||
last_point_light++;
|
||||
}
|
||||
|
||||
void ShadowPass::create_render_passes() {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
|
||||
// render pass
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.label = "Shadow";
|
||||
|
@ -318,12 +370,12 @@ void ShadowPass::create_render_passes() {
|
|||
renderPassInfo.will_use_in_shader = true;
|
||||
|
||||
render_pass = gfx->create_render_pass(renderPassInfo);
|
||||
|
||||
|
||||
renderPassInfo.label = "Shadow Cube";
|
||||
renderPassInfo.attachments.clear();
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::R_32F);
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::DEPTH_32F);
|
||||
|
||||
|
||||
cube_render_pass = gfx->create_render_pass(renderPassInfo);
|
||||
}
|
||||
|
||||
|
@ -335,20 +387,15 @@ void ShadowPass::create_pipelines() {
|
|||
pipelineInfo.shaders.vertex_constants = {point_light_max_constant};
|
||||
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 = {
|
||||
{0, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::StorageBuffer},
|
||||
{2, GFXBindingType::StorageBuffer}
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(PushConstant), 0}
|
||||
};
|
||||
|
||||
{0, GFXBindingType::PushConstant}, {1, GFXBindingType::StorageBuffer}, {2, GFXBindingType::StorageBuffer}};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {{sizeof(PushConstant), 0}};
|
||||
|
||||
pipelineInfo.render_pass = render_pass;
|
||||
|
||||
|
||||
pipelineInfo.depth.depth_mode = GFXDepthMode::LessOrEqual;
|
||||
|
||||
// sun
|
||||
|
@ -356,31 +403,31 @@ void ShadowPass::create_pipelines() {
|
|||
pipelineInfo.label = "Sun Shadow";
|
||||
|
||||
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||
|
||||
|
||||
static_sun_pipeline = static_pipeline;
|
||||
skinned_sun_pipeline = skinned_pipeline;
|
||||
}
|
||||
|
||||
|
||||
// spot
|
||||
{
|
||||
pipelineInfo.label = "Spot Shadow";
|
||||
|
||||
pipelineInfo.render_pass = cube_render_pass;
|
||||
|
||||
|
||||
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||
|
||||
|
||||
static_spot_pipeline = static_pipeline;
|
||||
skinned_spot_pipeline = skinned_pipeline;
|
||||
}
|
||||
|
||||
|
||||
// point
|
||||
{
|
||||
pipelineInfo.label = "Point Shadow";
|
||||
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/omnishadow.frag"));
|
||||
|
||||
|
||||
auto [static_pipeline, skinned_pipeline] = material_compiler.create_pipeline_permutations(pipelineInfo, true);
|
||||
|
||||
|
||||
static_point_pipeline = static_pipeline;
|
||||
skinned_point_pipeline = skinned_pipeline;
|
||||
}
|
||||
|
@ -388,7 +435,7 @@ void ShadowPass::create_pipelines() {
|
|||
|
||||
void ShadowPass::create_offscreen_resources() {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Shadow Color";
|
||||
textureInfo.width = render_options.shadow_resolution;
|
||||
|
@ -398,7 +445,7 @@ void ShadowPass::create_offscreen_resources() {
|
|||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
offscreen_color_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXTextureCreateInfo depthTextureInfo = {};
|
||||
depthTextureInfo.label = "Shadow Depth";
|
||||
depthTextureInfo.width = render_options.shadow_resolution;
|
||||
|
@ -406,15 +453,16 @@ void ShadowPass::create_offscreen_resources() {
|
|||
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
depthTextureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
|
||||
offscreen_depth = gfx->create_texture(depthTextureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo info;
|
||||
info.attachments = {offscreen_color_texture, offscreen_depth};
|
||||
info.render_pass = cube_render_pass;
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "smaapass.hpp"
|
||||
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "renderer.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "gfx.hpp"
|
||||
#include "assertions.hpp"
|
||||
#include "gfx_commandbuffer.hpp"
|
||||
#include "renderer.hpp"
|
||||
|
||||
#include <AreaTex.h>
|
||||
#include <SearchTex.h>
|
||||
|
@ -19,27 +19,27 @@ SMAAPass::SMAAPass(GFX* gfx) {
|
|||
|
||||
void SMAAPass::create_render_target_resources(RenderTarget& target) {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "SMAA Edge";
|
||||
textureInfo.width = target.extent.width;
|
||||
textureInfo.height = target.extent.height;
|
||||
textureInfo.format = GFXPixelFormat::R16G16B16A16_SFLOAT;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
|
||||
|
||||
target.edge_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
textureInfo.label = "SMAA Blend";
|
||||
target.blend_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.attachments = {target.edge_texture};
|
||||
framebufferInfo.render_pass = render_pass;
|
||||
|
||||
|
||||
target.edge_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
|
||||
|
||||
framebufferInfo.attachments = {target.blend_texture};
|
||||
|
||||
|
||||
target.blend_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
|
@ -47,28 +47,32 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) {
|
|||
GFXRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.render_area.extent = target.extent;
|
||||
beginInfo.render_pass = render_pass;
|
||||
|
||||
|
||||
struct PushConstant {
|
||||
prism::float4 viewport;
|
||||
} 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
|
||||
{
|
||||
beginInfo.framebuffer = target.edge_framebuffer;
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = target.extent.width;
|
||||
viewport.height = target.extent.height;
|
||||
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
|
||||
command_buffer->set_graphics_pipeline(edge_pipeline);
|
||||
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||
|
||||
command_buffer->bind_texture(target.mid_texture, 0); // color
|
||||
command_buffer->bind_texture(target.mid_texture, 0); // color
|
||||
command_buffer->bind_texture(target.offscreenDepthTexture, 1); // depth
|
||||
|
||||
command_buffer->draw(0, 3, 0, 1);
|
||||
|
@ -96,8 +100,8 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) {
|
|||
|
||||
void SMAAPass::create_textures() {
|
||||
auto gfx = engine->get_gfx();
|
||||
|
||||
//load area image
|
||||
|
||||
// load area image
|
||||
GFXTextureCreateInfo areaInfo = {};
|
||||
areaInfo.label = "SMAA Area";
|
||||
areaInfo.width = AREATEX_WIDTH;
|
||||
|
@ -108,9 +112,9 @@ void SMAAPass::create_textures() {
|
|||
areaInfo.border_color = GFXBorderColor::OpaqueWhite;
|
||||
|
||||
area_image = gfx->create_texture(areaInfo);
|
||||
|
||||
|
||||
gfx->copy_texture(area_image, (void*)areaTexBytes, AREATEX_SIZE);
|
||||
|
||||
|
||||
// load search image
|
||||
GFXTextureCreateInfo searchInfo = {};
|
||||
searchInfo.label = "SMAA Search";
|
||||
|
@ -124,7 +128,7 @@ void SMAAPass::create_textures() {
|
|||
searchInfo.mag_filter = GFXFilter::Nearest;
|
||||
|
||||
search_image = gfx->create_texture(searchInfo);
|
||||
|
||||
|
||||
gfx->copy_texture(search_image, (void*)searchTexBytes, SEARCHTEX_SIZE);
|
||||
}
|
||||
|
||||
|
@ -133,7 +137,7 @@ void SMAAPass::create_render_pass() {
|
|||
createInfo.label = "SMAA";
|
||||
createInfo.attachments = {GFXPixelFormat::R16G16B16A16_SFLOAT};
|
||||
createInfo.will_use_in_shader = true;
|
||||
|
||||
|
||||
render_pass = engine->get_gfx()->create_render_pass(createInfo);
|
||||
}
|
||||
|
||||
|
@ -144,25 +148,20 @@ void SMAAPass::create_pipelines() {
|
|||
createInfo.label = "SMAA Edge";
|
||||
createInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/edge.vert"));
|
||||
createInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/edge.frag"));
|
||||
|
||||
|
||||
createInfo.render_pass = render_pass;
|
||||
|
||||
createInfo.shader_input.push_constants = {
|
||||
{sizeof(prism::float4), 0}
|
||||
};
|
||||
|
||||
|
||||
createInfo.shader_input.push_constants = {{sizeof(prism::float4), 0}};
|
||||
|
||||
createInfo.shader_input.bindings = {
|
||||
{0, GFXBindingType::Texture},
|
||||
{1, GFXBindingType::Texture},
|
||||
{2, GFXBindingType::PushConstant}
|
||||
};
|
||||
|
||||
{0, GFXBindingType::Texture}, {1, GFXBindingType::Texture}, {2, GFXBindingType::PushConstant}};
|
||||
|
||||
edge_pipeline = gfx->create_graphics_pipeline(createInfo);
|
||||
|
||||
|
||||
createInfo.label = "SMAA Blend";
|
||||
createInfo.shaders.vertex_src = ShaderSource(prism::path("shaders/blend.vert"));
|
||||
createInfo.shaders.fragment_src = ShaderSource(prism::path("shaders/blend.frag"));
|
||||
createInfo.shader_input.bindings.push_back({3, GFXBindingType::Texture});
|
||||
|
||||
|
||||
blend_pipeline = gfx->create_graphics_pipeline(createInfo);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
set(SRC
|
||||
include/shadercompiler.hpp
|
||||
include/shadercompiler.hpp
|
||||
|
||||
src/shadercompiler.cpp
|
||||
src/includer.hpp
|
||||
src/defaultresources.hpp)
|
||||
src/shadercompiler.cpp
|
||||
src/includer.hpp
|
||||
src/defaultresources.hpp)
|
||||
|
||||
add_library(ShaderCompiler STATIC ${SRC})
|
||||
target_link_libraries(ShaderCompiler
|
||||
PUBLIC
|
||||
Platform
|
||||
PRIVATE
|
||||
Utility
|
||||
Log
|
||||
spirv-cross-core
|
||||
spirv-cross-glsl
|
||||
spirv-cross-msl
|
||||
spirv-cross-hlsl
|
||||
glslang
|
||||
SPIRV)
|
||||
PUBLIC
|
||||
Platform
|
||||
PRIVATE
|
||||
Utility
|
||||
Log
|
||||
spirv-cross-core
|
||||
spirv-cross-glsl
|
||||
spirv-cross-msl
|
||||
spirv-cross-hlsl
|
||||
glslang
|
||||
SPIRV)
|
||||
target_include_directories(ShaderCompiler PUBLIC include PRIVATE src)
|
||||
set_engine_properties(ShaderCompiler)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "file.hpp"
|
||||
|
||||
|
@ -30,9 +30,9 @@ public:
|
|||
void add_definition(const std::string_view name) {
|
||||
definitions.emplace_back(name);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> definitions;
|
||||
|
||||
|
||||
/// When compiling MSL, the result may differ whether or not we're targetting non-Mac Metal platforms.
|
||||
bool is_apple_mobile = false;
|
||||
};
|
||||
|
@ -41,22 +41,25 @@ public:
|
|||
class ShaderSource {
|
||||
public:
|
||||
ShaderSource() : source(std::monostate()) {}
|
||||
|
||||
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 prism::path& shader_path) : source(shader_path) {}
|
||||
|
||||
std::variant<std::monostate, prism::path, std::string, std::vector<uint32_t>> source;
|
||||
|
||||
|
||||
/// Returns a view of the shader source as a path.
|
||||
[[nodiscard]] prism::path as_path() const {
|
||||
return std::get<prism::path>(source);
|
||||
}
|
||||
|
||||
|
||||
/// Returns a view of the shader source as plaintext.
|
||||
[[nodiscard]] std::string_view as_string() const {
|
||||
return std::get<std::string>(source);
|
||||
}
|
||||
|
||||
|
||||
/// Returns a copy of the shader source as bytecode.
|
||||
[[nodiscard]] std::vector<uint32_t> as_bytecode() const {
|
||||
return std::get<std::vector<uint32_t>>(source);
|
||||
|
@ -65,11 +68,11 @@ public:
|
|||
[[nodiscard]] bool empty() const {
|
||||
return std::holds_alternative<std::monostate>(source);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] bool is_path() const {
|
||||
return std::holds_alternative<prism::path>(source);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] bool is_string() const {
|
||||
return std::holds_alternative<std::string>(source);
|
||||
}
|
||||
|
@ -79,10 +82,10 @@ public:
|
|||
class ShaderCompiler {
|
||||
public:
|
||||
ShaderCompiler();
|
||||
|
||||
|
||||
/// Sets the include directory used to search for files inside of #include directives.
|
||||
void set_include_path(std::string_view path);
|
||||
|
||||
|
||||
/**
|
||||
Compiles from one shader language to another shader language.
|
||||
@param from_language The language the shader passed by shader_source is written in.
|
||||
|
@ -92,7 +95,12 @@ public:
|
|||
@param options Optional compilation parameters.
|
||||
@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;
|
||||
|
|
|
@ -1,109 +1,109 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
const TBuiltInResource DefaultTBuiltInResource = {
|
||||
/* .MaxLights = */ 32,
|
||||
/* .MaxClipPlanes = */ 6,
|
||||
/* .MaxTextureUnits = */ 32,
|
||||
/* .MaxTextureCoords = */ 32,
|
||||
/* .MaxVertexAttribs = */ 64,
|
||||
/* .MaxVertexUniformComponents = */ 4096,
|
||||
/* .MaxVaryingFloats = */ 64,
|
||||
/* .MaxVertexTextureImageUnits = */ 32,
|
||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
||||
/* .MaxTextureImageUnits = */ 32,
|
||||
/* .MaxFragmentUniformComponents = */ 4096,
|
||||
/* .MaxDrawBuffers = */ 32,
|
||||
/* .MaxVertexUniformVectors = */ 128,
|
||||
/* .MaxVaryingVectors = */ 8,
|
||||
/* .MaxFragmentUniformVectors = */ 16,
|
||||
/* .MaxVertexOutputVectors = */ 16,
|
||||
/* .MaxFragmentInputVectors = */ 15,
|
||||
/* .MinProgramTexelOffset = */ -8,
|
||||
/* .MaxProgramTexelOffset = */ 7,
|
||||
/* .MaxClipDistances = */ 8,
|
||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
||||
/* .MaxComputeUniformComponents = */ 1024,
|
||||
/* .MaxComputeTextureImageUnits = */ 16,
|
||||
/* .MaxComputeImageUniforms = */ 8,
|
||||
/* .MaxComputeAtomicCounters = */ 8,
|
||||
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
||||
/* .MaxVaryingComponents = */ 60,
|
||||
/* .MaxVertexOutputComponents = */ 64,
|
||||
/* .MaxGeometryInputComponents = */ 64,
|
||||
/* .MaxGeometryOutputComponents = */ 128,
|
||||
/* .MaxFragmentInputComponents = */ 128,
|
||||
/* .MaxImageUnits = */ 8,
|
||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
||||
/* .MaxCombinedShaderOutputResources = */ 8,
|
||||
/* .MaxImageSamples = */ 0,
|
||||
/* .MaxVertexImageUniforms = */ 0,
|
||||
/* .MaxTessControlImageUniforms = */ 0,
|
||||
/* .MaxTessEvaluationImageUniforms = */ 0,
|
||||
/* .MaxGeometryImageUniforms = */ 0,
|
||||
/* .MaxFragmentImageUniforms = */ 8,
|
||||
/* .MaxCombinedImageUniforms = */ 8,
|
||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
||||
/* .MaxGeometryOutputVertices = */ 256,
|
||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
||||
/* .MaxGeometryUniformComponents = */ 1024,
|
||||
/* .MaxGeometryVaryingComponents = */ 64,
|
||||
/* .MaxTessControlInputComponents = */ 128,
|
||||
/* .MaxTessControlOutputComponents = */ 128,
|
||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
||||
/* .MaxTessControlUniformComponents = */ 1024,
|
||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
||||
/* .MaxTessPatchComponents = */ 120,
|
||||
/* .MaxPatchVertices = */ 32,
|
||||
/* .MaxTessGenLevel = */ 64,
|
||||
/* .MaxViewports = */ 16,
|
||||
/* .MaxVertexAtomicCounters = */ 0,
|
||||
/* .MaxTessControlAtomicCounters = */ 0,
|
||||
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
||||
/* .MaxGeometryAtomicCounters = */ 0,
|
||||
/* .MaxFragmentAtomicCounters = */ 8,
|
||||
/* .MaxCombinedAtomicCounters = */ 8,
|
||||
/* .MaxAtomicCounterBindings = */ 1,
|
||||
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
||||
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
||||
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
||||
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
||||
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
||||
/* .MaxCullDistances = */ 8,
|
||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
||||
/* .MaxSamples = */ 4,
|
||||
/* .maxMeshOutputVerticesNV = */ 256,
|
||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxMeshViewCountNV = */ 4,
|
||||
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||
/* .MaxLights = */ 32,
|
||||
/* .MaxClipPlanes = */ 6,
|
||||
/* .MaxTextureUnits = */ 32,
|
||||
/* .MaxTextureCoords = */ 32,
|
||||
/* .MaxVertexAttribs = */ 64,
|
||||
/* .MaxVertexUniformComponents = */ 4096,
|
||||
/* .MaxVaryingFloats = */ 64,
|
||||
/* .MaxVertexTextureImageUnits = */ 32,
|
||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
||||
/* .MaxTextureImageUnits = */ 32,
|
||||
/* .MaxFragmentUniformComponents = */ 4096,
|
||||
/* .MaxDrawBuffers = */ 32,
|
||||
/* .MaxVertexUniformVectors = */ 128,
|
||||
/* .MaxVaryingVectors = */ 8,
|
||||
/* .MaxFragmentUniformVectors = */ 16,
|
||||
/* .MaxVertexOutputVectors = */ 16,
|
||||
/* .MaxFragmentInputVectors = */ 15,
|
||||
/* .MinProgramTexelOffset = */ -8,
|
||||
/* .MaxProgramTexelOffset = */ 7,
|
||||
/* .MaxClipDistances = */ 8,
|
||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
||||
/* .MaxComputeUniformComponents = */ 1024,
|
||||
/* .MaxComputeTextureImageUnits = */ 16,
|
||||
/* .MaxComputeImageUniforms = */ 8,
|
||||
/* .MaxComputeAtomicCounters = */ 8,
|
||||
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
||||
/* .MaxVaryingComponents = */ 60,
|
||||
/* .MaxVertexOutputComponents = */ 64,
|
||||
/* .MaxGeometryInputComponents = */ 64,
|
||||
/* .MaxGeometryOutputComponents = */ 128,
|
||||
/* .MaxFragmentInputComponents = */ 128,
|
||||
/* .MaxImageUnits = */ 8,
|
||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
||||
/* .MaxCombinedShaderOutputResources = */ 8,
|
||||
/* .MaxImageSamples = */ 0,
|
||||
/* .MaxVertexImageUniforms = */ 0,
|
||||
/* .MaxTessControlImageUniforms = */ 0,
|
||||
/* .MaxTessEvaluationImageUniforms = */ 0,
|
||||
/* .MaxGeometryImageUniforms = */ 0,
|
||||
/* .MaxFragmentImageUniforms = */ 8,
|
||||
/* .MaxCombinedImageUniforms = */ 8,
|
||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
||||
/* .MaxGeometryOutputVertices = */ 256,
|
||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
||||
/* .MaxGeometryUniformComponents = */ 1024,
|
||||
/* .MaxGeometryVaryingComponents = */ 64,
|
||||
/* .MaxTessControlInputComponents = */ 128,
|
||||
/* .MaxTessControlOutputComponents = */ 128,
|
||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
||||
/* .MaxTessControlUniformComponents = */ 1024,
|
||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
||||
/* .MaxTessPatchComponents = */ 120,
|
||||
/* .MaxPatchVertices = */ 32,
|
||||
/* .MaxTessGenLevel = */ 64,
|
||||
/* .MaxViewports = */ 16,
|
||||
/* .MaxVertexAtomicCounters = */ 0,
|
||||
/* .MaxTessControlAtomicCounters = */ 0,
|
||||
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
||||
/* .MaxGeometryAtomicCounters = */ 0,
|
||||
/* .MaxFragmentAtomicCounters = */ 8,
|
||||
/* .MaxCombinedAtomicCounters = */ 8,
|
||||
/* .MaxAtomicCounterBindings = */ 1,
|
||||
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
||||
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
||||
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
||||
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
||||
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
||||
/* .MaxCullDistances = */ 8,
|
||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
||||
/* .MaxSamples = */ 4,
|
||||
/* .maxMeshOutputVerticesNV = */ 256,
|
||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxMeshViewCountNV = */ 4,
|
||||
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||
|
||||
/* .limits = */ {
|
||||
/* .nonInductiveForLoops = */ 1,
|
||||
/* .whileLoops = */ 1,
|
||||
/* .doWhileLoops = */ 1,
|
||||
/* .generalUniformIndexing = */ 1,
|
||||
/* .generalAttributeMatrixVectorIndexing = */ 1,
|
||||
/* .generalVaryingIndexing = */ 1,
|
||||
/* .generalSamplerIndexing = */ 1,
|
||||
/* .generalVariableIndexing = */ 1,
|
||||
/* .generalConstantMatrixVectorIndexing = */ 1,
|
||||
}};
|
||||
/* .limits = */
|
||||
{
|
||||
/* .nonInductiveForLoops = */ 1,
|
||||
/* .whileLoops = */ 1,
|
||||
/* .doWhileLoops = */ 1,
|
||||
/* .generalUniformIndexing = */ 1,
|
||||
/* .generalAttributeMatrixVectorIndexing = */ 1,
|
||||
/* .generalVaryingIndexing = */ 1,
|
||||
/* .generalSamplerIndexing = */ 1,
|
||||
/* .generalVariableIndexing = */ 1,
|
||||
/* .generalConstantMatrixVectorIndexing = */ 1,
|
||||
}};
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glslang/Public/ShaderLang.h>
|
||||
|
||||
|
@ -48,19 +48,14 @@
|
|||
// Can be overridden to customize.
|
||||
class DirStackFileIncluder : public glslang::TShader::Includer {
|
||||
public:
|
||||
DirStackFileIncluder() : externalLocalDirectoryCount(0) { }
|
||||
DirStackFileIncluder() : externalLocalDirectoryCount(0) {}
|
||||
|
||||
IncludeResult* includeLocal(const char* headerName,
|
||||
const char* includerName,
|
||||
size_t inclusionDepth) override
|
||||
{
|
||||
IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override {
|
||||
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
||||
}
|
||||
|
||||
IncludeResult* includeSystem(const char* headerName,
|
||||
const char* /*includerName*/,
|
||||
size_t /*inclusionDepth*/) override
|
||||
{
|
||||
IncludeResult*
|
||||
includeSystem(const char* headerName, const char* /*includerName*/, size_t /*inclusionDepth*/) override {
|
||||
return readSystemPath(headerName);
|
||||
}
|
||||
|
||||
|
@ -70,16 +65,14 @@ public:
|
|||
// is checked.
|
||||
// - This only applies to the "local" form of #include.
|
||||
// - 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);
|
||||
externalLocalDirectoryCount = (int)directoryStack.size();
|
||||
}
|
||||
|
||||
void releaseInclude(IncludeResult* result) override
|
||||
{
|
||||
void releaseInclude(IncludeResult* result) override {
|
||||
if (result != nullptr) {
|
||||
delete [] static_cast<tUserDataElement*>(result->userData);
|
||||
delete[] static_cast<tUserDataElement*>(result->userData);
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +86,7 @@ protected:
|
|||
|
||||
// Search for a valid "local" path based on combining the stack of include
|
||||
// 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
|
||||
// initialize when at parse-time first level.
|
||||
directoryStack.resize(depth + externalLocalDirectoryCount);
|
||||
|
@ -117,15 +109,13 @@ protected:
|
|||
|
||||
// Search for a valid <system> path.
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
char* content = new tUserDataElement [length];
|
||||
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const {
|
||||
char* content = new tUserDataElement[length];
|
||||
file.seekg(0, file.beg);
|
||||
file.read(content, length);
|
||||
return new IncludeResult(path, content, length, content);
|
||||
|
@ -134,7 +124,7 @@ protected:
|
|||
// If no path markers, return current working directory.
|
||||
// Otherwise, strip file name and return path leading up to it.
|
||||
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 "";
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#include "shadercompiler.hpp"
|
||||
|
||||
#include <spirv_msl.hpp>
|
||||
#include <SPIRV/GlslangToSpv.h>
|
||||
#include <spirv_msl.hpp>
|
||||
|
||||
#include "log.hpp"
|
||||
#include "string_utils.hpp"
|
||||
#include "includer.hpp"
|
||||
#include "defaultresources.hpp"
|
||||
#include "includer.hpp"
|
||||
#include "log.hpp"
|
||||
#include "spirv_hlsl.hpp"
|
||||
#include "string_utils.hpp"
|
||||
|
||||
static inline std::vector<std::string> include_path;
|
||||
|
||||
|
@ -19,50 +19,51 @@ void ShaderCompiler::set_include_path(const std::string_view path) {
|
|||
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";
|
||||
|
||||
|
||||
newString += "#extension GL_GOOGLE_include_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 += "#line 1\n";
|
||||
|
||||
|
||||
newString += source_string;
|
||||
|
||||
const char* InputCString = newString.c_str();
|
||||
|
||||
|
||||
glslang::TShader shader(shader_language);
|
||||
shader.setStrings(&InputCString, 1);
|
||||
|
||||
int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
|
||||
|
||||
shader.setEnvInput(glslang::EShSourceGlsl,
|
||||
shader_language,
|
||||
glslang::EShClientVulkan,
|
||||
ClientInputSemanticsVersion);
|
||||
shader.setEnvInput(glslang::EShSourceGlsl, shader_language, glslang::EShClientVulkan, ClientInputSemanticsVersion);
|
||||
|
||||
// we are targeting vulkan 1.1, so that uses SPIR-V 1.3
|
||||
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;
|
||||
for(const auto& path : include_path)
|
||||
for (const auto& path : include_path)
|
||||
file_includer.pushExternalLocalDirectory(path);
|
||||
if (!shader.parse(&DefaultTBuiltInResource, 100, false, EShMsgDefault, file_includer)) {
|
||||
prism::log("{}", shader.getInfoLog());
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
glslang::TProgram Program;
|
||||
Program.addShader(&shader);
|
||||
|
||||
if(!Program.link(EShMsgDefault)) {
|
||||
prism::log("Failed to link shader: {} {} {}", source_string.data(), shader.getInfoLog(), shader.getInfoDebugLog());
|
||||
|
||||
|
||||
if (!Program.link(EShMsgDefault)) {
|
||||
prism::log(
|
||||
"Failed to link shader: {} {} {}", source_string.data(), shader.getInfoLog(), shader.getInfoDebugLog());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -73,18 +74,23 @@ std::vector<uint32_t> compile_glsl_to_spv(const std::string_view source_string,
|
|||
spvOptions.generateDebugInfo = true;
|
||||
|
||||
glslang::GlslangToSpv(*Program.getIntermediate(shader_language), SpirV, &logger, &spvOptions);
|
||||
|
||||
|
||||
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) {
|
||||
if(from_language != ShaderLanguage::GLSL) {
|
||||
std::optional<ShaderSource> ShaderCompiler::compile(
|
||||
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!");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
EShLanguage lang = EShLangMiss;
|
||||
switch(shader_stage) {
|
||||
switch (shader_stage) {
|
||||
case ShaderStage::Vertex:
|
||||
lang = EShLangVertex;
|
||||
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);
|
||||
if(spirv.empty()) {
|
||||
if (spirv.empty()) {
|
||||
prism::log("SPIRV generation failed!");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
switch(to_language) {
|
||||
|
||||
switch (to_language) {
|
||||
case ShaderLanguage::GLSL:
|
||||
return ShaderSource(shader_source);
|
||||
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::Options opts;
|
||||
if(options.is_apple_mobile) {
|
||||
if (options.is_apple_mobile) {
|
||||
opts.platform = spirv_cross::CompilerMSL::Options::Platform::iOS;
|
||||
} else {
|
||||
opts.platform = spirv_cross::CompilerMSL::Options::Platform::macOS;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
add_executable(Tests
|
||||
tests.cpp
|
||||
string_tests.cpp
|
||||
utility_tests.cpp)
|
||||
add_executable(Tests
|
||||
tests.cpp
|
||||
string_tests.cpp
|
||||
utility_tests.cpp)
|
||||
target_link_libraries(Tests PUBLIC doctest Utility)
|
||||
set_output_dir(Tests)
|
||||
set_engine_properties(Tests)
|
||||
|
|
|
@ -6,21 +6,21 @@ TEST_SUITE_BEGIN("String Utilities");
|
|||
|
||||
TEST_CASE("Remove substring") {
|
||||
std::string str = "foobar";
|
||||
|
||||
|
||||
CHECK(remove_substring(str, "foo") == "bar");
|
||||
CHECK(remove_substring(str, "bar") == "foo");
|
||||
}
|
||||
|
||||
TEST_CASE("Replace substring") {
|
||||
std::string str = "foobar";
|
||||
|
||||
|
||||
CHECK(replace_substring(str, "foo", "bar") == "barbar");
|
||||
CHECK(replace_substring(str, "bar", "foo") == "foofoo");
|
||||
}
|
||||
|
||||
TEST_CASE("String contains") {
|
||||
std::string str = "foobar";
|
||||
|
||||
|
||||
CHECK(string_contains(str, "foo") == true);
|
||||
CHECK(string_contains(str, "bar") == true);
|
||||
CHECK(string_contains(str, "farboo") == false);
|
||||
|
@ -28,7 +28,7 @@ TEST_CASE("String contains") {
|
|||
|
||||
TEST_CASE("String starts with") {
|
||||
std::string str = "(win)and(lose)";
|
||||
|
||||
|
||||
CHECK(string_starts_with(str, "(") == true);
|
||||
CHECK(string_starts_with(str, "(win)") == true);
|
||||
CHECK(string_starts_with(str, "(lose)") == false);
|
||||
|
@ -36,12 +36,12 @@ TEST_CASE("String starts with") {
|
|||
|
||||
TEST_CASE("Tokenize") {
|
||||
std::string first_case = "1,2,3";
|
||||
|
||||
|
||||
CHECK(tokenize(first_case) == std::vector<std::string>({"1", "2", "3"}));
|
||||
|
||||
|
||||
SUBCASE("Alternative delimiters") {
|
||||
std::string second_case = "1-2-3";
|
||||
|
||||
|
||||
CHECK(tokenize(second_case, "-") == std::vector<std::string>({"1", "2", "3"}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ TEST_CASE("Enum to string") {
|
|||
A,
|
||||
B
|
||||
};
|
||||
|
||||
|
||||
CHECK(utility::enum_to_string(TestEnum::A) == "A");
|
||||
CHECK(utility::enum_to_string(TestEnum::B) == "B");
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
set(SRC
|
||||
include/utility.hpp
|
||||
include/json_conversions.hpp
|
||||
include/string_utils.hpp
|
||||
include/timer.hpp
|
||||
include/common.hpp
|
||||
include/assertions.hpp
|
||||
include/path.hpp
|
||||
|
||||
src/string_utils.cpp)
|
||||
include/utility.hpp
|
||||
include/json_conversions.hpp
|
||||
include/string_utils.hpp
|
||||
include/timer.hpp
|
||||
include/common.hpp
|
||||
include/assertions.hpp
|
||||
include/path.hpp
|
||||
|
||||
src/string_utils.cpp)
|
||||
|
||||
add_library(Utility ${SRC})
|
||||
target_link_libraries(Utility PUBLIC Math magic_enum)
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace prism {
|
|||
/// A 2D extent.
|
||||
struct Extent {
|
||||
Extent() : width(0), height(0) {}
|
||||
|
||||
Extent(const uint32_t width, const uint32_t height) : width(width), height(height) {}
|
||||
|
||||
uint32_t width = 0, height = 0;
|
||||
|
@ -14,6 +15,7 @@ namespace prism {
|
|||
/// A 2D offset.
|
||||
struct Offset {
|
||||
Offset() : x(0), y(0) {}
|
||||
|
||||
Offset(const int32_t x, const int32_t y) : x(x), y(y) {}
|
||||
|
||||
int32_t x = 0, y = 0;
|
||||
|
@ -22,10 +24,13 @@ namespace prism {
|
|||
/// A 2D rectangle defined by a offset and an etent.
|
||||
struct Rectangle {
|
||||
Rectangle() = default;
|
||||
|
||||
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;
|
||||
Extent extent;
|
||||
};
|
||||
}
|
||||
} // namespace prism
|
||||
|
|
|
@ -2,22 +2,22 @@
|
|||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "vector.hpp"
|
||||
#include "quaternion.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
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["y"] = p.y;
|
||||
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.y = j["y"];
|
||||
p.z = j["z"];
|
||||
}
|
||||
}
|
||||
} // namespace prism
|
||||
|
||||
inline void to_json(nlohmann::json& j, const Quaternion& p) {
|
||||
j["x"] = p.x;
|
||||
|
|
|
@ -9,10 +9,9 @@ namespace prism {
|
|||
|
||||
// some stdlibs such as apple's clang fail to provide this :-/
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<prism::path> {
|
||||
template<> struct hash<prism::path> {
|
||||
std::size_t operator()(const prism::path& k) const {
|
||||
return (std::hash<std::string>()(k.string()));
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace std
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
struct Timer {
|
||||
std::function<void()> callback;
|
||||
|
||||
|
||||
float duration = 0.0f;
|
||||
|
||||
|
||||
float current_time = 0.0f;
|
||||
|
||||
|
||||
bool remove_on_trigger = true;
|
||||
bool continue_during_pause = true;
|
||||
};
|
||||
|
|
|
@ -3,34 +3,30 @@
|
|||
#include <magic_enum.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <random>
|
||||
#include <unordered_map>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace utility {
|
||||
template<class Enum>
|
||||
std::string enum_to_string(const Enum e) {
|
||||
template<class Enum> std::string enum_to_string(const Enum e) {
|
||||
const std::string_view name = magic_enum::enum_name(e);
|
||||
|
||||
|
||||
std::string s = name.data();
|
||||
return s.substr(0, name.length());
|
||||
}
|
||||
|
||||
template<class T, class F>
|
||||
void erase_if(std::vector<T>& vec, const F& f) {
|
||||
vec.erase(std::remove_if(vec.begin(), vec.end(), f), vec.end());
|
||||
template<class T, class F> void erase_if(std::vector<T>& vec, const F& f) {
|
||||
vec.erase(std::remove_if(vec.begin(), vec.end(), f), vec.end());
|
||||
}
|
||||
|
||||
template<class T, class V>
|
||||
void erase(T& vec, const V& t) {
|
||||
template<class T, class V> void erase(T& vec, const V& t) {
|
||||
vec.erase(std::remove(vec.begin(), vec.end(), t), vec.end());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void erase_at(std::vector<T>& vec, const int index) {
|
||||
template<class T> void erase_at(std::vector<T>& vec, const int index) {
|
||||
vec.erase(vec.begin() + index);
|
||||
}
|
||||
|
||||
|
@ -46,46 +42,60 @@ namespace utility {
|
|||
return get_random(0, max);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline auto get_random(const std::vector<T>& vec) {
|
||||
template<class T> inline auto get_random(const std::vector<T>& vec) {
|
||||
return vec[get_random(static_cast<int>(vec.size() - 1))];
|
||||
}
|
||||
|
||||
template<class T, size_t S>
|
||||
inline auto get_random(const std::array<T, S>& vec) {
|
||||
template<class T, size_t S> inline auto get_random(const std::array<T, S>& vec) {
|
||||
return vec[get_random(static_cast<int>(vec.size() - 1))];
|
||||
}
|
||||
|
||||
template<class T, class V>
|
||||
inline auto get_random(const std::unordered_map<T, V>& map) {
|
||||
template<class T, class V> inline auto get_random(const std::unordered_map<T, V>& map) {
|
||||
const auto item = map.begin();
|
||||
std::advance(item, get_random(static_cast<int>(map.size() - 1)));
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
template<class T, class TIter = decltype(std::begin(std::declval<T>())), class = decltype(std::end(std::declval<T>()))>
|
||||
constexpr auto enumerate(T&& iterable)
|
||||
{
|
||||
template<
|
||||
class T,
|
||||
class TIter = decltype(std::begin(std::declval<T>())),
|
||||
class = decltype(std::end(std::declval<T>()))>
|
||||
constexpr auto enumerate(T&& iterable) {
|
||||
struct iterator {
|
||||
size_t i;
|
||||
TIter iter;
|
||||
bool operator != (const iterator & other) const { return iter != other.iter; }
|
||||
void operator ++ () { ++i; ++iter; }
|
||||
auto operator * () const { return std::tie(i, *iter); }
|
||||
|
||||
bool operator!=(const iterator& other) const {
|
||||
return iter != other.iter;
|
||||
}
|
||||
|
||||
void operator++() {
|
||||
++i;
|
||||
++iter;
|
||||
}
|
||||
|
||||
auto operator*() const {
|
||||
return std::tie(i, *iter);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct iterable_wrapper {
|
||||
T iterable;
|
||||
auto begin() { return iterator{ 0, std::begin(iterable) }; }
|
||||
auto end() { return iterator{ 0, std::end(iterable) }; }
|
||||
|
||||
auto begin() {
|
||||
return iterator{0, std::begin(iterable)};
|
||||
}
|
||||
|
||||
auto end() {
|
||||
return iterator{0, std::end(iterable)};
|
||||
}
|
||||
};
|
||||
|
||||
return iterable_wrapper{ std::forward<T>(iterable) };
|
||||
|
||||
return iterable_wrapper{std::forward<T>(iterable)};
|
||||
}
|
||||
|
||||
template<class T, class V>
|
||||
inline bool contains(const std::vector<T>& vec, const V& val) {
|
||||
|
||||
template<class T, class V> inline bool contains(const std::vector<T>& vec, const V& val) {
|
||||
return std::count(vec.begin(), vec.end(), val);
|
||||
}
|
||||
|
||||
|
@ -93,7 +103,7 @@ namespace utility {
|
|||
inline uint32_t pack_u32(const uint16_t a, const uint16_t b) {
|
||||
return (b << 16) | a;
|
||||
}
|
||||
|
||||
|
||||
/// Converts a floating-point to a fixed 16-bit unsigned integer.
|
||||
inline uint16_t to_fixed(const float f) {
|
||||
return static_cast<uint16_t>(32.0f * f + 0.5f);
|
||||
|
@ -101,8 +111,8 @@ namespace utility {
|
|||
|
||||
inline prism::float3 from_srgb_to_linear(const prism::float3 sRGB) {
|
||||
prism::float3 linear = sRGB;
|
||||
for(auto& component : linear.data) {
|
||||
if(component > 0.04045f) {
|
||||
for (auto& component : linear.data) {
|
||||
if (component > 0.04045f) {
|
||||
component = std::pow((component + 0.055) / (1.055), 2.4f);
|
||||
} else if (component <= 0.04045) {
|
||||
component /= 12.92f;
|
||||
|
@ -112,8 +122,7 @@ namespace utility {
|
|||
return linear;
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
inline void move_to_front(std::vector<T>& vec, F func) {
|
||||
template<typename T, typename F> inline void move_to_front(std::vector<T>& vec, F func) {
|
||||
auto result = std::find_if(vec.begin(), vec.end(), func);
|
||||
if (result != vec.end()) {
|
||||
auto value = *result;
|
||||
|
@ -121,4 +130,4 @@ namespace utility {
|
|||
vec.insert(vec.begin(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace utility
|
||||
|
|
|
@ -4,25 +4,26 @@
|
|||
|
||||
std::string remove_substring(const std::string_view string, const std::string_view substring) {
|
||||
std::string result(string);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
const auto substring_length = substring.length();
|
||||
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.insert(i, replacement);
|
||||
i += replacement.length();
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -31,30 +32,31 @@ 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) {
|
||||
return needle.length() <= haystack.length()
|
||||
&& std::equal(needle.begin(), needle.end(), haystack.begin());
|
||||
return needle.length() <= haystack.length() && std::equal(needle.begin(), needle.end(), haystack.begin());
|
||||
}
|
||||
|
||||
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> tokens;
|
||||
|
||||
|
||||
const size_t length = string.length();
|
||||
size_t lastPos = 0;
|
||||
|
||||
while(lastPos < length + 1) {
|
||||
|
||||
while (lastPos < length + 1) {
|
||||
size_t pos = string.find_first_of(delimiters, lastPos);
|
||||
if(pos == std::string_view::npos)
|
||||
if (pos == std::string_view::npos)
|
||||
pos = length;
|
||||
|
||||
if(pos != lastPos)
|
||||
|
||||
if (pos != lastPos)
|
||||
tokens.emplace_back(string.data() + lastPos, pos - lastPos);
|
||||
|
||||
|
||||
lastPos = pos + 1;
|
||||
}
|
||||
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
|
Reference in a new issue