From 9dfc4f2fed39e86b724f9b43de4d084d78da21e6 Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Wed, 6 Nov 2024 21:56:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9B=BE=E7=89=87=E7=BB=98?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/CMakeLists.txt | 2 + src/renderer/backend/dx/dx_renderer.cpp | 165 +----------------- src/renderer/backend/dx/dx_renderer.h | 142 ++++++++++++++- src/renderer/backend/dx/dx_texture.cpp | 61 +++++-- src/renderer/backend/dx/dx_texture.h | 12 +- src/renderer/backend/dx/dx_window.cpp | 58 ++---- src/renderer/backend/dx/dx_window.h | 3 + .../dx/pipeline/dx_pipeline_loader.cpp | 41 +++++ .../backend/dx/pipeline/dx_pipeline_loader.h | 12 ++ .../backend/dx/pipeline/dx_rect_pipeline.cpp | 33 +--- .../backend/dx/pipeline/dx_rect_pipeline.h | 5 +- .../dx/pipeline/dx_rounded_rect_pipeline.cpp | 34 +--- .../dx/pipeline/dx_rounded_rect_pipeline.h | 5 +- .../dx/pipeline/dx_texture_pipeline.cpp | 53 ++++++ .../backend/dx/pipeline/dx_texture_pipeline.h | 19 ++ .../core/pipeline/texture_pipeline.cpp | 16 ++ src/renderer/core/pipeline/texture_pipeline.h | 18 ++ src/renderer/core/renderer/renderer.cpp | 58 ++++++ src/renderer/core/renderer/renderer.h | 114 +++++++++++- .../core/renderer/renderer_context.cpp | 110 +++++++----- src/renderer/core/renderer/renderer_context.h | 38 ++-- src/renderer/core/renderer/renderer_texture.h | 32 +++- src/renderer/misc/color.cpp | 3 + src/renderer/misc/color.h | 8 + src/renderer/shader/aorii_texture.slang | 35 ++++ 25 files changed, 708 insertions(+), 369 deletions(-) create mode 100644 src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp create mode 100644 src/renderer/backend/dx/pipeline/dx_pipeline_loader.h create mode 100644 src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp create mode 100644 src/renderer/backend/dx/pipeline/dx_texture_pipeline.h create mode 100644 src/renderer/core/pipeline/texture_pipeline.cpp create mode 100644 src/renderer/core/pipeline/texture_pipeline.h create mode 100644 src/renderer/misc/color.cpp create mode 100644 src/renderer/shader/aorii_texture.slang diff --git a/src/renderer/CMakeLists.txt b/src/renderer/CMakeLists.txt index ab51178..d20b11b 100644 --- a/src/renderer/CMakeLists.txt +++ b/src/renderer/CMakeLists.txt @@ -63,6 +63,8 @@ compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "ver compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "pixel" "pixel_main") compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "vertex" "vertex_main") compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "pixel" "pixel_main") +compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "vertex" "vertex_main") +compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "pixel" "pixel_main") add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME}) # 如果需要编译example, 添加自定义命令用于拷贝shader文件 diff --git a/src/renderer/backend/dx/dx_renderer.cpp b/src/renderer/backend/dx/dx_renderer.cpp index 4371ff1..5359ea9 100644 --- a/src/renderer/backend/dx/dx_renderer.cpp +++ b/src/renderer/backend/dx/dx_renderer.cpp @@ -9,145 +9,6 @@ #include "core/window/window_manager.h" #include "spdlog/spdlog.h" -DXGI_FORMAT get_dxgi_format(texture_format format) { - switch (format) { - // 8-bit formats - case texture_format::R8_UNORM: - return DXGI_FORMAT_R8_UNORM; - case texture_format::R8_SNORM: - return DXGI_FORMAT_R8_SNORM; - case texture_format::R8_UINT: - return DXGI_FORMAT_R8_UINT; - case texture_format::R8_SINT: - return DXGI_FORMAT_R8_SINT; - - // 16-bit formats - case texture_format::RG8_UNORM: - return DXGI_FORMAT_R8G8_UNORM; - case texture_format::RG8_SNORM: - return DXGI_FORMAT_R8G8_SNORM; - case texture_format::RG8_UINT: - return DXGI_FORMAT_R8G8_UINT; - case texture_format::RG8_SINT: - return DXGI_FORMAT_R8G8_SINT; - - // 24-bit formats - case texture_format::RGB8_UNORM: - return DXGI_FORMAT_B8G8R8X8_UNORM; // Note: DXGI doesn't have a direct RGB8 format - case texture_format::RGB8_SNORM: - return DXGI_FORMAT_UNKNOWN; // No direct equivalent - case texture_format::RGB8_UINT: - return DXGI_FORMAT_UNKNOWN; // No direct equivalent - case texture_format::RGB8_SINT: - return DXGI_FORMAT_UNKNOWN; // No direct equivalent - - // 32-bit formats - case texture_format::RGBA8_UNORM: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case texture_format::RGBA8_SNORM: - return DXGI_FORMAT_R8G8B8A8_SNORM; - case texture_format::RGBA8_UINT: - return DXGI_FORMAT_R8G8B8A8_UINT; - case texture_format::RGBA8_SINT: - return DXGI_FORMAT_R8G8B8A8_SINT; - - // SRGB formats - case texture_format::SRGB8: - return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; // Note: Approximation - case texture_format::SRGB8_ALPHA8: - return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - - // 16-bit float formats - case texture_format::R16_FLOAT: - return DXGI_FORMAT_R16_FLOAT; - case texture_format::RG16_FLOAT: - return DXGI_FORMAT_R16G16_FLOAT; - case texture_format::RGB16_FLOAT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; // Note: No direct RGB16 format - case texture_format::RGBA16_FLOAT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - - // 32-bit float formats - case texture_format::R32_FLOAT: - return DXGI_FORMAT_R32_FLOAT; - case texture_format::RG32_FLOAT: - return DXGI_FORMAT_R32G32_FLOAT; - case texture_format::RGB32_FLOAT: - return DXGI_FORMAT_R32G32B32_FLOAT; - case texture_format::RGBA32_FLOAT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - - // Integer formats - case texture_format::R16_UINT: - return DXGI_FORMAT_R16_UINT; - case texture_format::R16_SINT: - return DXGI_FORMAT_R16_SINT; - case texture_format::RG16_UINT: - return DXGI_FORMAT_R16G16_UINT; - case texture_format::RG16_SINT: - return DXGI_FORMAT_R16G16_SINT; - case texture_format::RGBA16_UINT: - return DXGI_FORMAT_R16G16B16A16_UINT; - case texture_format::RGBA16_SINT: - return DXGI_FORMAT_R16G16B16A16_SINT; - case texture_format::R32_UINT: - return DXGI_FORMAT_R32_UINT; - case texture_format::R32_SINT: - return DXGI_FORMAT_R32_SINT; - case texture_format::RG32_UINT: - return DXGI_FORMAT_R32G32_UINT; - case texture_format::RG32_SINT: - return DXGI_FORMAT_R32G32_SINT; - case texture_format::RGBA32_UINT: - return DXGI_FORMAT_R32G32B32A32_UINT; - case texture_format::RGBA32_SINT: - return DXGI_FORMAT_R32G32B32A32_SINT; - - // Depth/stencil formats - case texture_format::D16_UNORM: - return DXGI_FORMAT_D16_UNORM; - case texture_format::D24_UNORM_S8_UINT: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - case texture_format::D32_FLOAT: - return DXGI_FORMAT_D32_FLOAT; - case texture_format::D32_FLOAT_S8X24_UINT: - return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; - - // Compressed formats - case texture_format::BC1_UNORM: - return DXGI_FORMAT_BC1_UNORM; - case texture_format::BC1_UNORM_SRGB: - return DXGI_FORMAT_BC1_UNORM_SRGB; - case texture_format::BC2_UNORM: - return DXGI_FORMAT_BC2_UNORM; - case texture_format::BC2_UNORM_SRGB: - return DXGI_FORMAT_BC2_UNORM_SRGB; - case texture_format::BC3_UNORM: - return DXGI_FORMAT_BC3_UNORM; - case texture_format::BC3_UNORM_SRGB: - return DXGI_FORMAT_BC3_UNORM_SRGB; - case texture_format::BC4_UNORM: - return DXGI_FORMAT_BC4_UNORM; - case texture_format::BC4_SNORM: - return DXGI_FORMAT_BC4_SNORM; - case texture_format::BC5_UNORM: - return DXGI_FORMAT_BC5_UNORM; - case texture_format::BC5_SNORM: - return DXGI_FORMAT_BC5_SNORM; - case texture_format::BC6H_UF16: - return DXGI_FORMAT_BC6H_UF16; - case texture_format::BC6H_SF16: - return DXGI_FORMAT_BC6H_SF16; - case texture_format::BC7_UNORM: - return DXGI_FORMAT_BC7_UNORM; - case texture_format::BC7_UNORM_SRGB: - return DXGI_FORMAT_BC7_UNORM_SRGB; - - default: - return DXGI_FORMAT_UNKNOWN; - } -} - bool dx_renderer::init() { if (!glfwInit()) return false; glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); @@ -172,6 +33,7 @@ bool dx_renderer::init() { rect_p.init(); rounded_rect_p.init(); + texture_p.init(); return true; } @@ -180,6 +42,7 @@ void dx_renderer::destroy() { if (blend_state) blend_state->Release(); rect_p.destroy(); rounded_rect_p.destroy(); + texture_p.destroy(); glfwTerminate(); } @@ -192,30 +55,8 @@ bool dx_renderer::render() { return true; } -void dx_renderer::destroy_texture(renderer_texture* texture) { -#ifdef DEBUG - spdlog::info("Destroying texture"); -#endif -} - renderer_texture* dx_renderer::create_texture(const Eigen::Vector2i& size, texture_format in_format) { - D3D11_TEXTURE2D_DESC desc = {}; - desc.Width = size.x(); - desc.Height = size.y(); - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = get_dxgi_format(in_format); - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - ID3D11Texture2D* texture = nullptr; - if (FAILED(device->CreateTexture2D(&desc, nullptr, &texture))) { return nullptr; } - - return new dx_texture(texture); + return new dx_texture(size, in_format); } std::vector<char> dx_renderer::load_shader(const std::string& shader_name) { diff --git a/src/renderer/backend/dx/dx_renderer.h b/src/renderer/backend/dx/dx_renderer.h index 394bda9..10f090f 100644 --- a/src/renderer/backend/dx/dx_renderer.h +++ b/src/renderer/backend/dx/dx_renderer.h @@ -4,6 +4,7 @@ #include "core/renderer/renderer.h" #include "pipeline/dx_rect_pipeline.h" #include "pipeline/dx_rounded_rect_pipeline.h" +#include "pipeline/dx_texture_pipeline.h" class dx_window; @@ -14,13 +15,13 @@ public: bool render() override; renderer_texture* create_texture(const Eigen::Vector2i& size, texture_format in_format) override; - void destroy_texture(renderer_texture* texture) override; [[nodiscard]] ID3D11Device* get_d3d_device() const { return device; } [[nodiscard]] ID3D11DeviceContext* get_d3d_context() const { return context; } rect_pipeline* get_rect_pipeline() override { return &rect_p; } rounded_rect_pipeline* get_rounded_rect_pipeline() override { return &rounded_rect_p; } + texture_pipeline* get_texture_pipeline() override { return &texture_p; } [[nodiscard]] ID3D11BlendState* get_blend_state() const { return blend_state; } std::vector<char> load_shader(const std::string& shader_name) override; @@ -37,5 +38,144 @@ private: dx_rect_pipeline rect_p; dx_rounded_rect_pipeline rounded_rect_p; + dx_texture_pipeline texture_p; }; +inline DXGI_FORMAT get_dxgi_format(texture_format format) { + switch (format) { + // 8-bit formats + case texture_format::R8_UNORM: + return DXGI_FORMAT_R8_UNORM; + case texture_format::R8_SNORM: + return DXGI_FORMAT_R8_SNORM; + case texture_format::R8_UINT: + return DXGI_FORMAT_R8_UINT; + case texture_format::R8_SINT: + return DXGI_FORMAT_R8_SINT; + + // 16-bit formats + case texture_format::RG8_UNORM: + return DXGI_FORMAT_R8G8_UNORM; + case texture_format::RG8_SNORM: + return DXGI_FORMAT_R8G8_SNORM; + case texture_format::RG8_UINT: + return DXGI_FORMAT_R8G8_UINT; + case texture_format::RG8_SINT: + return DXGI_FORMAT_R8G8_SINT; + + // 24-bit formats + case texture_format::RGB8_UNORM: + return DXGI_FORMAT_B8G8R8X8_UNORM; // Note: DXGI doesn't have a direct RGB8 format + case texture_format::RGB8_SNORM: + return DXGI_FORMAT_UNKNOWN; // No direct equivalent + case texture_format::RGB8_UINT: + return DXGI_FORMAT_UNKNOWN; // No direct equivalent + case texture_format::RGB8_SINT: + return DXGI_FORMAT_UNKNOWN; // No direct equivalent + + // 32-bit formats + case texture_format::RGBA8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM; + case texture_format::RGBA8_SNORM: + return DXGI_FORMAT_R8G8B8A8_SNORM; + case texture_format::RGBA8_UINT: + return DXGI_FORMAT_R8G8B8A8_UINT; + case texture_format::RGBA8_SINT: + return DXGI_FORMAT_R8G8B8A8_SINT; + + // SRGB formats + case texture_format::SRGB8: + return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; // Note: Approximation + case texture_format::SRGB8_ALPHA8: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + // 16-bit float formats + case texture_format::R16_FLOAT: + return DXGI_FORMAT_R16_FLOAT; + case texture_format::RG16_FLOAT: + return DXGI_FORMAT_R16G16_FLOAT; + case texture_format::RGB16_FLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; // Note: No direct RGB16 format + case texture_format::RGBA16_FLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + // 32-bit float formats + case texture_format::R32_FLOAT: + return DXGI_FORMAT_R32_FLOAT; + case texture_format::RG32_FLOAT: + return DXGI_FORMAT_R32G32_FLOAT; + case texture_format::RGB32_FLOAT: + return DXGI_FORMAT_R32G32B32_FLOAT; + case texture_format::RGBA32_FLOAT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + // Integer formats + case texture_format::R16_UINT: + return DXGI_FORMAT_R16_UINT; + case texture_format::R16_SINT: + return DXGI_FORMAT_R16_SINT; + case texture_format::RG16_UINT: + return DXGI_FORMAT_R16G16_UINT; + case texture_format::RG16_SINT: + return DXGI_FORMAT_R16G16_SINT; + case texture_format::RGBA16_UINT: + return DXGI_FORMAT_R16G16B16A16_UINT; + case texture_format::RGBA16_SINT: + return DXGI_FORMAT_R16G16B16A16_SINT; + case texture_format::R32_UINT: + return DXGI_FORMAT_R32_UINT; + case texture_format::R32_SINT: + return DXGI_FORMAT_R32_SINT; + case texture_format::RG32_UINT: + return DXGI_FORMAT_R32G32_UINT; + case texture_format::RG32_SINT: + return DXGI_FORMAT_R32G32_SINT; + case texture_format::RGBA32_UINT: + return DXGI_FORMAT_R32G32B32A32_UINT; + case texture_format::RGBA32_SINT: + return DXGI_FORMAT_R32G32B32A32_SINT; + + // Depth/stencil formats + case texture_format::D16_UNORM: + return DXGI_FORMAT_D16_UNORM; + case texture_format::D24_UNORM_S8_UINT: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + case texture_format::D32_FLOAT: + return DXGI_FORMAT_D32_FLOAT; + case texture_format::D32_FLOAT_S8X24_UINT: + return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + + // Compressed formats + case texture_format::BC1_UNORM: + return DXGI_FORMAT_BC1_UNORM; + case texture_format::BC1_UNORM_SRGB: + return DXGI_FORMAT_BC1_UNORM_SRGB; + case texture_format::BC2_UNORM: + return DXGI_FORMAT_BC2_UNORM; + case texture_format::BC2_UNORM_SRGB: + return DXGI_FORMAT_BC2_UNORM_SRGB; + case texture_format::BC3_UNORM: + return DXGI_FORMAT_BC3_UNORM; + case texture_format::BC3_UNORM_SRGB: + return DXGI_FORMAT_BC3_UNORM_SRGB; + case texture_format::BC4_UNORM: + return DXGI_FORMAT_BC4_UNORM; + case texture_format::BC4_SNORM: + return DXGI_FORMAT_BC4_SNORM; + case texture_format::BC5_UNORM: + return DXGI_FORMAT_BC5_UNORM; + case texture_format::BC5_SNORM: + return DXGI_FORMAT_BC5_SNORM; + case texture_format::BC6H_UF16: + return DXGI_FORMAT_BC6H_UF16; + case texture_format::BC6H_SF16: + return DXGI_FORMAT_BC6H_SF16; + case texture_format::BC7_UNORM: + return DXGI_FORMAT_BC7_UNORM; + case texture_format::BC7_UNORM_SRGB: + return DXGI_FORMAT_BC7_UNORM_SRGB; + + default: + return DXGI_FORMAT_UNKNOWN; + } +} diff --git a/src/renderer/backend/dx/dx_texture.cpp b/src/renderer/backend/dx/dx_texture.cpp index ce87bdd..d91552e 100644 --- a/src/renderer/backend/dx/dx_texture.cpp +++ b/src/renderer/backend/dx/dx_texture.cpp @@ -2,33 +2,56 @@ #include "dx_renderer.h" -dx_texture::dx_texture(ID3D11Texture2D* texture) { m_texture = texture; } +dx_texture::dx_texture(const Eigen::Vector2i& size, texture_format format) : renderer_texture(format) { + auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device(); + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = size.x(); + desc.Height = size.y(); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = get_dxgi_format(format); + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + auto hr = d3d_device->CreateTexture2D(&desc, nullptr, &m_texture); + if (FAILED(hr)) { + spdlog::critical("无法创建纹理, 错误: {0}", hr); + return; + } -dx_texture::~dx_texture() { - // 如果是Debug模式, 检查m_data是否被释放 -#if defined(DEBUG) - assert(!m_data); -#endif - free(m_data); + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; + srv_desc.Format = desc.Format; + srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MostDetailedMip = 0; + srv_desc.Texture2D.MipLevels = 1; + hr = d3d_device->CreateShaderResourceView(m_texture, &srv_desc, &srv); + if (FAILED(hr)) { + spdlog::critical("无法创建着色器资源视图, 错误: {0}", hr); + return; + } } -void* dx_texture::lock() { +dx_texture::~dx_texture() { + if (srv) srv->Release(); + if (m_texture) m_texture->Release(); +} + +void* dx_texture::lock(unsigned int* out_row_pitch) { D3D11_TEXTURE2D_DESC desc; m_texture->GetDesc(&desc); - m_data = new char[desc.Width * desc.Height * 4]; - return m_data; + D3D11_MAPPED_SUBRESOURCE mappedResource; + auto context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); + context->Map(m_texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (out_row_pitch) *out_row_pitch = mappedResource.RowPitch; + return mappedResource.pData; } void dx_texture::unlock() { - // D3D11_TEXTURE2D_DESC desc; - // m_texture->GetDesc(&desc); - // D3D11_MAPPED_SUBRESOURCE mappedResource; - // auto context = dx_backend::get_instance(); - // context->Map(m_texture.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - // memcpy(mappedResource.pData, m_data, desc.Width * desc.Height * 4); - // context->Unmap(m_texture.get(), 0); - // delete[] m_data; - // m_data = nullptr; + auto context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); + context->Unmap(m_texture, 0); } bool dx_texture::resize(const Eigen::Vector2i& size) { return true; } diff --git a/src/renderer/backend/dx/dx_texture.h b/src/renderer/backend/dx/dx_texture.h index 7d4ad9e..d7bc306 100644 --- a/src/renderer/backend/dx/dx_texture.h +++ b/src/renderer/backend/dx/dx_texture.h @@ -7,14 +7,18 @@ // DX11纹理 class dx_texture : public renderer_texture { public: - explicit dx_texture(ID3D11Texture2D* texture); + dx_texture(const Eigen::Vector2i& size, texture_format format); ~dx_texture() override; - void* lock() override; + void* lock(unsigned int* out_row_pitch) override; void unlock() override; bool resize(const Eigen::Vector2i& size) override; Eigen::Vector2i size() override; + + [[nodiscard]] ID3D11ShaderResourceView* get_srv() const { return srv; } + void* get_native_handle() override { return m_texture; } + void* get_shader_resource_view() override { return srv; } private: - void* m_data = nullptr; - ID3D11Texture2D* m_texture; + ID3D11Texture2D* m_texture{}; + ID3D11ShaderResourceView* srv{}; }; diff --git a/src/renderer/backend/dx/dx_window.cpp b/src/renderer/backend/dx/dx_window.cpp index b751904..2570231 100644 --- a/src/renderer/backend/dx/dx_window.cpp +++ b/src/renderer/backend/dx/dx_window.cpp @@ -3,6 +3,7 @@ #include <spdlog/spdlog.h> #include "dx_renderer.h" +#include "core/renderer/renderer_texture.h" #include "misc/scope_exit.h" using namespace aorii; @@ -67,10 +68,10 @@ bool dx_window::create_surface(GLFWwindow* in_window) { return false; } + test_texture = dx->load_image(R"(D:\69054578_p0.jpg)", texture_format::RGBA8_UNORM); return true; } - void dx_window::begin_frame() { glfwMakeContextCurrent(get_glfw_window()); const auto render = aorii::get_renderer<dx_renderer>(); @@ -79,54 +80,17 @@ void dx_window::begin_frame() { d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr); d3d_context->OMSetBlendState(render->get_blend_state(), nullptr, 0xffffffff); d3d_context->ClearRenderTargetView(render_target_view, clear_color); - - if constexpr (false) { - static std::chrono::duration<double> timer = {}; - static linear_color random_color = { 0, 0, 0, 1 }; - static bool is_white = false; - static float pos_x = 0; - static float pos_y = 0; - static bool draw_test = true; - - if (draw_test) { - // 生成渐变色 - if (is_white) { - if (random_color.r > 0) { - random_color.r -= 0.01f; - } else if (random_color.b > 0) { - random_color.b -= 0.01f; - } else if (random_color.g > 0) { - random_color.g -= 0.01f; - } else { - is_white = false; - random_color = {0.0f, 0.0f, 0.0f, 1.0f}; - } - } - else { - if (random_color.r < 1) { - random_color.r += 0.01f; - } else if (random_color.b < 1) { - random_color.b += 0.01f; - } else if (random_color.g < 1) { - random_color.g += 0.01f; - } else { - is_white = true; - random_color = {1.0f, 1.0f, 1.0f, 1.0f}; - } - } - - context.draw_rectangle({ pos_x, pos_y }, { 1, 100 }, random_color); - if (pos_x >= 1000) { - pos_x = 0; - draw_test = false; - } - pos_x += 1; - } - } + context.set_projection_matrix(projection_matrix); context.draw_rectangle({ 400, 0 }, { 100, 100 }, { 0, 1, 0, 1 }); auto radius = abs(sin(get_total_time().count())) * 50; context.draw_rounded_rectangle({ 100, 100 }, { 200, 200 }, { 1, 0, 0, 1 }, radius); + + auto height = sin(get_total_time().count()) * 100; + context.draw_line({ 600, 600 - height }, { 700, 600 + height }, { 0, 0, 1, 1 }, 0.1); + + context.draw_texture({0, 0}, test_texture->size(), test_texture); + context.flush(); swap_chain->Present(1, 0); @@ -183,9 +147,7 @@ HRESULT dx_window::build_render_target_view() { viewport.TopLeftY = 0.0f; d3d_context->RSSetViewports(1, &viewport); - const auto& projection_matrix = get_projection_matrix().transpose(); - - context.set_projection_matrix(projection_matrix); + projection_matrix = get_projection_matrix().transpose(); return hr; } diff --git a/src/renderer/backend/dx/dx_window.h b/src/renderer/backend/dx/dx_window.h index e0ac60c..54fd904 100644 --- a/src/renderer/backend/dx/dx_window.h +++ b/src/renderer/backend/dx/dx_window.h @@ -18,4 +18,7 @@ private: renderer_context context; IDXGISwapChain1* swap_chain = nullptr; ID3D11RenderTargetView* render_target_view = nullptr; + Eigen::Matrix4f projection_matrix; + + renderer_texture* test_texture = nullptr; }; diff --git a/src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp b/src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp new file mode 100644 index 0000000..3174481 --- /dev/null +++ b/src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp @@ -0,0 +1,41 @@ +#include "dx_pipeline_loader.h" + +#include "backend/dx/dx_renderer.h" + +bool dx_pipeline_loader::load(const char* vertex_shader_name, const char* pixel_shader_name) { + auto renderer = aorii::get_renderer<dx_renderer>(); + const auto d3d_device = renderer->get_d3d_device(); + + const auto& vertex_shader_code = renderer->load_shader(vertex_shader_name); + const auto& pixel_shader_code = renderer->load_shader(pixel_shader_name); + + auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader); + if (FAILED(hr)) { + spdlog::critical("rect_pipeline 无法创建顶点着色器: {0}", hr); + return false; + } + hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader); + if (FAILED(hr)) { + spdlog::critical("rect_pipeline 无法创建像素着色器: {0}", hr); + return false; + } + D3D11_INPUT_ELEMENT_DESC layout_desc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC); + hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout); + if (FAILED(hr)) { + spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr); + return false; + } + return true; +} + +void dx_pipeline_loader::use() const { + const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); + d3d_context->VSSetShader(vertex_shader, nullptr, 0); + d3d_context->PSSetShader(pixel_shader, nullptr, 0); + d3d_context->IASetInputLayout(input_layout); +} diff --git a/src/renderer/backend/dx/pipeline/dx_pipeline_loader.h b/src/renderer/backend/dx/pipeline/dx_pipeline_loader.h new file mode 100644 index 0000000..d3de9f1 --- /dev/null +++ b/src/renderer/backend/dx/pipeline/dx_pipeline_loader.h @@ -0,0 +1,12 @@ +#pragma once +#include <d3d11.h> + +class dx_pipeline_loader { +public: + bool load(const char* vertex_shader_name, const char* pixel_shader_name); + void use() const; + + ID3D11VertexShader* vertex_shader = nullptr; + ID3D11PixelShader* pixel_shader = nullptr; + ID3D11InputLayout* input_layout = nullptr; +}; diff --git a/src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp b/src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp index 6dc5c4f..840460a 100644 --- a/src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp +++ b/src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp @@ -4,41 +4,12 @@ bool dx_rect_pipeline::init() { rect_pipeline::init(); - auto renderer = aorii::get_renderer<dx_renderer>(); - const auto d3d_device = renderer->get_d3d_device(); - - const auto& vertex_shader_code = renderer->load_shader("aorii_rect_vertex_main"); - const auto& pixel_shader_code = renderer->load_shader("aorii_rect_pixel_main"); - - auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader); - if (FAILED(hr)) { - spdlog::critical("rect_pipeline 无法创建顶点着色器: {0}", hr); - return false; - } - hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader); - if (FAILED(hr)) { - spdlog::critical("rect_pipeline 无法创建像素着色器: {0}", hr); - return false; - } - D3D11_INPUT_ELEMENT_DESC layout_desc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, - { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC); - hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout); - if (FAILED(hr)) { - spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr); - return false; - } + loader.load("aorii_rect_vertex_main", "aorii_rect_pixel_main"); return true; } void dx_rect_pipeline::use() { - const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); - d3d_context->VSSetShader(vertex_shader, nullptr, 0); - d3d_context->PSSetShader(pixel_shader, nullptr, 0); - d3d_context->IASetInputLayout(input_layout); + loader.use(); } void dx_rect_pipeline::draw() { diff --git a/src/renderer/backend/dx/pipeline/dx_rect_pipeline.h b/src/renderer/backend/dx/pipeline/dx_rect_pipeline.h index 3e7d12c..75ce40f 100644 --- a/src/renderer/backend/dx/pipeline/dx_rect_pipeline.h +++ b/src/renderer/backend/dx/pipeline/dx_rect_pipeline.h @@ -1,6 +1,7 @@ #pragma once #include <d3d11.h> +#include "dx_pipeline_loader.h" #include "core/pipeline/rect_pipeline.h" class dx_rect_pipeline : public rect_pipeline { @@ -9,7 +10,5 @@ public: void use() override; void draw() override; private: - ID3D11VertexShader* vertex_shader = nullptr; - ID3D11PixelShader* pixel_shader = nullptr; - ID3D11InputLayout* input_layout = nullptr; + dx_pipeline_loader loader; }; diff --git a/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.cpp b/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.cpp index 02018be..b54d147 100644 --- a/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.cpp +++ b/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.cpp @@ -4,41 +4,11 @@ bool dx_rounded_rect_pipeline::init() { rounded_rect_pipeline::init(); - auto renderer = aorii::get_renderer<dx_renderer>(); - const auto d3d_device = renderer->get_d3d_device(); - - const auto& vertex_shader_code = renderer->load_shader("aorii_rounded_rect_vertex_main"); - const auto& pixel_shader_code = renderer->load_shader("aorii_rounded_rect_pixel_main"); - - auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader); - if (FAILED(hr)) { - spdlog::critical("rounded_rect_pipeline 无法创建顶点着色器: {0}", hr); - return false; - } - hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader); - if (FAILED(hr)) { - spdlog::critical("rounded_rect_pipeline 无法创建像素着色器: {0}", hr); - return false; - } - D3D11_INPUT_ELEMENT_DESC layout_desc[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, - { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC); - hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout); - if (FAILED(hr)) { - spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr); - return false; - } - return true; + return loader.load("aorii_rounded_rect_vertex_main", "aorii_rounded_rect_pixel_main"); } void dx_rounded_rect_pipeline::use() { - const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); - d3d_context->VSSetShader(vertex_shader, nullptr, 0); - d3d_context->PSSetShader(pixel_shader, nullptr, 0); - d3d_context->IASetInputLayout(input_layout); + loader.use(); } void dx_rounded_rect_pipeline::draw() { diff --git a/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h b/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h index 1d2d79a..593771a 100644 --- a/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h +++ b/src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h @@ -1,6 +1,7 @@ #pragma once #include <d3d11.h> +#include "dx_pipeline_loader.h" #include "core/pipeline/rounded_rect_pipeline.h" class dx_rounded_rect_pipeline : public rounded_rect_pipeline { @@ -9,7 +10,5 @@ public: void use() override; void draw() override; private: - ID3D11VertexShader* vertex_shader = nullptr; - ID3D11PixelShader* pixel_shader = nullptr; - ID3D11InputLayout* input_layout = nullptr; + dx_pipeline_loader loader; }; diff --git a/src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp b/src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp new file mode 100644 index 0000000..7d0831a --- /dev/null +++ b/src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp @@ -0,0 +1,53 @@ +#include "dx_texture_pipeline.h" + +#include "backend/dx/dx_renderer.h" +#include "backend/dx/dx_texture.h" + +bool dx_texture_pipeline::init() { + texture_pipeline::init(); + const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device(); + + D3D11_SAMPLER_DESC sampler_desc = {}; + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + sampler_desc.MinLOD = 0; + sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; + d3d_device->CreateSamplerState(&sampler_desc, &sampler_state); + + return loader.load("aorii_texture_vertex_main", "aorii_texture_pixel_main"); +} + +void dx_texture_pipeline::use() { + loader.use(); +} + +void dx_texture_pipeline::draw() { + if (!texture) return; + const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context(); + + // 设置顶点缓冲区 + constexpr UINT stride = sizeof(aorii_vertex); + constexpr UINT offset = 0; + auto* v_buffer = static_cast<ID3D11Buffer*>(vertex_buffer->get_native_handle()); + auto* i_buffer = static_cast<ID3D11Buffer*>(index_buffer->get_native_handle()); + auto* c_buffer = static_cast<ID3D11Buffer*>(param_buffer->get_native_handle()); + auto* srv = (ID3D11ShaderResourceView*)texture->get_shader_resource_view(); + d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset); + d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0); + d3d_context->PSSetSamplers(0, 1, &sampler_state); + d3d_context->VSSetConstantBuffers(0, 1, &c_buffer); + d3d_context->PSSetShaderResources(0, 1, &srv); + + // 设置图元拓扑 + d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // 绘制矩形 + d3d_context->Draw(vertex_buffer->get_size(), 0); +} + +void dx_texture_pipeline::set_texture(renderer_texture* in_texture) { + texture = static_cast<dx_texture*>(in_texture); +} diff --git a/src/renderer/backend/dx/pipeline/dx_texture_pipeline.h b/src/renderer/backend/dx/pipeline/dx_texture_pipeline.h new file mode 100644 index 0000000..ed4c3ad --- /dev/null +++ b/src/renderer/backend/dx/pipeline/dx_texture_pipeline.h @@ -0,0 +1,19 @@ +#pragma once +#include <d3d11.h> + +#include "dx_pipeline_loader.h" +#include "core/pipeline/texture_pipeline.h" + +class dx_texture_pipeline : public texture_pipeline { +public: + bool init() override; + void use() override; + void draw() override; + + void set_texture(renderer_texture* in_texture) override; +private: + dx_pipeline_loader loader; + + ID3D11SamplerState* sampler_state = nullptr; + renderer_texture* texture = nullptr; +}; diff --git a/src/renderer/core/pipeline/texture_pipeline.cpp b/src/renderer/core/pipeline/texture_pipeline.cpp new file mode 100644 index 0000000..dda5ba6 --- /dev/null +++ b/src/renderer/core/pipeline/texture_pipeline.cpp @@ -0,0 +1,16 @@ +#include "texture_pipeline.h" + +#include "core/renderer/renderer.h" + +bool texture_pipeline::init() { + param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1); + return pipeline::init(); +} +void texture_pipeline::destroy() { + pipeline::destroy(); + aorii::get_renderer_raw()->destroy_buffer(param_buffer); +} + +void texture_pipeline::set_param(const param& in_param) { + param_buffer->set_data(in_param); +} diff --git a/src/renderer/core/pipeline/texture_pipeline.h b/src/renderer/core/pipeline/texture_pipeline.h new file mode 100644 index 0000000..afe57b2 --- /dev/null +++ b/src/renderer/core/pipeline/texture_pipeline.h @@ -0,0 +1,18 @@ +#pragma once +#include "pipeline.h" + +class renderer_texture; + +class texture_pipeline : public pipeline { +public: + struct param { + Eigen::Matrix4f projection_matrix; + }; + bool init() override; + void destroy() override; + + void set_param(const param& in_param); + virtual void set_texture(renderer_texture* in_texture) = 0; +protected: + renderer_buffer* param_buffer = nullptr; +}; diff --git a/src/renderer/core/renderer/renderer.cpp b/src/renderer/core/renderer/renderer.cpp index 93ce95d..bf65593 100644 --- a/src/renderer/core/renderer/renderer.cpp +++ b/src/renderer/core/renderer/renderer.cpp @@ -2,7 +2,10 @@ #include <spdlog/spdlog.h> +#include "renderer_texture.h" #include "core/window/renderer_window.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" #if DX_BACKEND #include "backend/dx/dx_renderer.h" @@ -17,6 +20,61 @@ renderer* s_renderer = nullptr; void renderer::tick() { } +void renderer::destroy_texture(renderer_texture* texture) { delete texture; } + +renderer_texture* renderer::load_image(const std::string& file_path, texture_format in_format) { + int width, height, channels; + auto result = stbi_load(file_path.c_str(), &width, &height, &channels, 0); + if (!result) { + spdlog::critical("Failed to load image: {0}", file_path); + return nullptr; + } + + int target_channel_count = get_format_channel_count(in_format); + unsigned int row_pitch = 0; + + auto texture = create_texture({ width, height }, in_format); + auto data = texture->lock(&row_pitch); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + unsigned char* src = result + (y * width + x) * channels; + unsigned char* dst = static_cast<unsigned char*>(data) + y * row_pitch + x * target_channel_count; + switch (channels) { + case 1: + dst[0] = src[0]; + dst[1] = 0; + dst[2] = 0; + dst[3] = 255; + break; + case 2: + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = 0; + dst[3] = 255; + break; + case 3: + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 255; + break; + case 4: + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + break; + default: + break; + } + } + } + texture->unlock(); + stbi_image_free(result); + + return texture; +} + void renderer::destroy_window(renderer_window* window) { delete window; } diff --git a/src/renderer/core/renderer/renderer.h b/src/renderer/core/renderer/renderer.h index 58517f7..d67e6da 100644 --- a/src/renderer/core/renderer/renderer.h +++ b/src/renderer/core/renderer/renderer.h @@ -6,6 +6,7 @@ #include "renderer_buffer.h" #include "core/pipeline/pipeline.h" +class texture_pipeline; class rounded_rect_pipeline; class rect_pipeline; class renderer_window; @@ -98,6 +99,114 @@ enum class texture_format { BC7_UNORM_SRGB, }; +inline int get_format_channel_count(texture_format format) { + switch (format) { + case texture_format::R8_UNORM: + case texture_format::R8_SNORM: + case texture_format::R8_UINT: + case texture_format::R8_SINT: + case texture_format::R16_FLOAT: + case texture_format::R16_UINT: + case texture_format::R16_SINT: + case texture_format::R32_FLOAT: + case texture_format::R32_UINT: + case texture_format::R32_SINT: + return 1; + case texture_format::RG8_UNORM: + case texture_format::RG8_SNORM: + case texture_format::RG8_UINT: + case texture_format::RG8_SINT: + case texture_format::RG16_FLOAT: + case texture_format::RG16_UINT: + case texture_format::RG16_SINT: + case texture_format::RG32_FLOAT: + case texture_format::RG32_UINT: + case texture_format::RG32_SINT: + return 2; + case texture_format::RGB8_UNORM: + case texture_format::RGB8_SNORM: + case texture_format::RGB8_UINT: + case texture_format::RGB8_SINT: + case texture_format::RGB16_FLOAT: + case texture_format::RGB32_FLOAT: + return 3; + case texture_format::RGBA8_UNORM: + case texture_format::RGBA8_SNORM: + case texture_format::RGBA8_UINT: + case texture_format::RGBA8_SINT: + case texture_format::RGBA16_FLOAT: + case texture_format::RGBA32_FLOAT: + case texture_format::RGBA32_UINT: + case texture_format::RGBA32_SINT: + return 4; + default: + return 0; + } +} + +inline int get_format_bits_pre_channel(texture_format format) { + switch (format) { + case texture_format::R8_UNORM: + case texture_format::R8_SNORM: + case texture_format::R8_UINT: + case texture_format::R8_SINT: + case texture_format::RG8_UNORM: + case texture_format::RG8_SNORM: + case texture_format::RG8_UINT: + case texture_format::RG8_SINT: + case texture_format::RGB8_UNORM: + case texture_format::RGB8_SNORM: + case texture_format::RGB8_UINT: + case texture_format::RGB8_SINT: + case texture_format::RGBA8_UNORM: + case texture_format::RGBA8_SNORM: + case texture_format::RGBA8_UINT: + case texture_format::RGBA8_SINT: + case texture_format::SRGB8: + case texture_format::SRGB8_ALPHA8: + case texture_format::BC1_UNORM: + case texture_format::BC1_UNORM_SRGB: + case texture_format::BC2_UNORM: + case texture_format::BC2_UNORM_SRGB: + case texture_format::BC3_UNORM: + case texture_format::BC3_UNORM_SRGB: + case texture_format::BC4_UNORM: + case texture_format::BC4_SNORM: + case texture_format::BC5_UNORM: + case texture_format::BC5_SNORM: + case texture_format::BC6H_UF16: + case texture_format::BC6H_SF16: + case texture_format::BC7_UNORM: + case texture_format::BC7_UNORM_SRGB: + return 8; + case texture_format::R16_FLOAT: + case texture_format::R16_UINT: + case texture_format::R16_SINT: + case texture_format::RG16_FLOAT: + case texture_format::RG16_UINT: + case texture_format::RG16_SINT: + case texture_format::RGB16_FLOAT: + case texture_format::RGBA16_FLOAT: + case texture_format::D16_UNORM: + return 16; + case texture_format::R32_FLOAT: + case texture_format::R32_UINT: + case texture_format::R32_SINT: + case texture_format::RG32_FLOAT: + case texture_format::RG32_UINT: + case texture_format::RG32_SINT: + case texture_format::RGB32_FLOAT: + case texture_format::RGBA32_FLOAT: + return 32; + case texture_format::D24_UNORM_S8_UINT: + case texture_format::D32_FLOAT: + case texture_format::D32_FLOAT_S8X24_UINT: + return 24; + default: + return 0; + } +} + class renderer { friend class window_manager; public: @@ -109,7 +218,9 @@ public: virtual bool render() = 0; virtual renderer_texture* create_texture(const Eigen::Vector2i& size, texture_format in_format) = 0; - virtual void destroy_texture(renderer_texture* texture) = 0; + virtual void destroy_texture(renderer_texture* texture); + + renderer_texture* load_image(const std::string& file_path, texture_format in_format); /** * 读取着色器代码 @@ -129,6 +240,7 @@ public: virtual rect_pipeline* get_rect_pipeline() = 0; virtual rounded_rect_pipeline* get_rounded_rect_pipeline() = 0; + virtual texture_pipeline* get_texture_pipeline() = 0; private: virtual renderer_window* create_window() = 0; virtual void destroy_window(renderer_window* window); diff --git a/src/renderer/core/renderer/renderer_context.cpp b/src/renderer/core/renderer/renderer_context.cpp index bbcb4e5..0b9b002 100644 --- a/src/renderer/core/renderer/renderer_context.cpp +++ b/src/renderer/core/renderer/renderer_context.cpp @@ -1,62 +1,25 @@ #include "renderer_context.h" #include "renderer.h" +#include "backend/dx/dx_renderer.h" void renderer_context::init() { - rect_p = aorii::get_renderer_raw()->get_rect_pipeline(); - rounded_rect_p = aorii::get_renderer_raw()->get_rounded_rect_pipeline(); } void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color) { to_rect_pipeline(); - const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角 - const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角 - const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角 - const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角 - - const uint32_t index1 = vertices.size(); - vertices.push_back(v1); - const uint32_t index2 = vertices.size(); - vertices.push_back(v2); - const uint32_t index3 = vertices.size(); - vertices.push_back(v3); - const uint32_t index4 = vertices.size(); - vertices.push_back(v4); - - const aorii_triangle t1 = { index1, index2, index3 }; - const aorii_triangle t2 = { index2, index3, index4 }; - triangles.push_back(t1); - triangles.push_back(t2); + make_rect(in_pos, in_size, in_color); } void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) { to_rounded_rect_pipeline(in_pos, in_size, in_radius); - - const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角 - const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角 - const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角 - const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角 - - const uint32_t index1 = vertices.size(); - vertices.push_back(v1); - const uint32_t index2 = vertices.size(); - vertices.push_back(v2); - const uint32_t index3 = vertices.size(); - vertices.push_back(v3); - const uint32_t index4 = vertices.size(); - vertices.push_back(v4); - - const aorii_triangle t1 = { index1, index2, index3 }; - const aorii_triangle t2 = { index2, index3, index4 }; - triangles.push_back(t1); - triangles.push_back(t2); - + make_rect(in_pos, in_size, in_color); // 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批 flush(); } void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness) { - switch_pipeline(rect_p); + to_rect_pipeline(); const Eigen::Vector2f direction = (in_pos_p2 - in_pos_p1).cast<float>().normalized(); const Eigen::Vector2f normal = { -direction.y(), direction.x() }; const Eigen::Vector2f offset = normal * in_thickness; @@ -80,3 +43,68 @@ void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen:: triangles.push_back(t1); triangles.push_back(t2); } + +void renderer_context::draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, + renderer_texture* in_texture, const linear_color& in_color) { + to_texture_pipeline(in_texture); + make_rect(in_pos, in_size, in_color); + // 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批 + flush(); +} + +void renderer_context::set_projection_matrix(const Eigen::Matrix4f& in_matrix) { + projection_matrix = in_matrix; + + // 更新默认管线的投影矩阵 + const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline(); + rect_p->set_param({ in_matrix }); + // 更新纹理管线的投影矩阵 + const auto texture_p = aorii::get_renderer<dx_renderer>()->get_texture_pipeline(); + texture_p->set_param({ in_matrix }); + + // 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新 +} + +void renderer_context::to_rect_pipeline() { + const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline(); + switch_pipeline(rect_p); +} + +void renderer_context::to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius) { + const auto rounded_rect_p = aorii::get_renderer<dx_renderer>()->get_rounded_rect_pipeline(); + switch_pipeline(rounded_rect_p); + rounded_rect_pipeline::param param; + param.projection_matrix = projection_matrix; + param.pos = in_pos.cast<float>(); + param.size = in_size.cast<float>(); + param.radius = in_radius; + rounded_rect_p->set_param(param); +} + +void renderer_context::to_texture_pipeline(renderer_texture* in_texture) { + const auto texture_p = aorii::get_renderer<dx_renderer>()->get_texture_pipeline(); + switch_pipeline(texture_p); + texture_p->set_texture(in_texture); +} + +void renderer_context::make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, + const linear_color& in_color) { + const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角 + const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角 + const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角 + const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角 + + const uint32_t index1 = vertices.size(); + vertices.push_back(v1); + const uint32_t index2 = vertices.size(); + vertices.push_back(v2); + const uint32_t index3 = vertices.size(); + vertices.push_back(v3); + const uint32_t index4 = vertices.size(); + vertices.push_back(v4); + + const aorii_triangle t1 = { index1, index2, index3 }; + const aorii_triangle t2 = { index2, index3, index4 }; + triangles.push_back(t1); + triangles.push_back(t2); +} diff --git a/src/renderer/core/renderer/renderer_context.h b/src/renderer/core/renderer/renderer_context.h index 7bb3763..af88cb3 100644 --- a/src/renderer/core/renderer/renderer_context.h +++ b/src/renderer/core/renderer/renderer_context.h @@ -5,6 +5,8 @@ #include "core/pipeline/rect_pipeline.h" #include "core/pipeline/rounded_rect_pipeline.h" +class renderer_texture; + class renderer_context { public: void init(); @@ -34,6 +36,14 @@ public: */ void draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness); + /** + * 绘制一个纹理 + * @param in_pos 当前控件坐标系的位置 + * @param in_size 绘制的大小(受控件缩放影响) + * @param in_texture 纹理 + */ + void draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, renderer_texture* in_texture, const linear_color& in_color = linear_color::white); + void clear() { vertices.clear(); triangles.clear(); @@ -53,14 +63,8 @@ public: } clear(); } - void set_projection_matrix(const Eigen::Matrix4f& in_matrix) { - projection_matrix = in_matrix; + void set_projection_matrix(const Eigen::Matrix4f& in_matrix); - // 更新默认管线的投影矩阵 - rect_p->set_param({ in_matrix }); - - // 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新 - } protected: void switch_pipeline(pipeline* in_pipeline) { #if DEBUG @@ -74,25 +78,15 @@ protected: } } - void to_rect_pipeline() { - switch_pipeline(rect_p); - } - void to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius) { - switch_pipeline(rounded_rect_p); - rounded_rect_pipeline::param param; - param.projection_matrix = projection_matrix; - param.pos = in_pos.cast<float>(); - param.size = in_size.cast<float>(); - param.radius = in_radius; - rounded_rect_p->set_param(param); - } + void to_rect_pipeline(); + void to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius); + void to_texture_pipeline(renderer_texture* in_texture); private: std::vector<aorii_vertex> vertices; std::vector<aorii_triangle> triangles; - rect_pipeline* rect_p = nullptr; - rounded_rect_pipeline* rounded_rect_p = nullptr; - pipeline* current_pipeline = nullptr; Eigen::Matrix4f projection_matrix; +private: + void make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color); }; diff --git a/src/renderer/core/renderer/renderer_texture.h b/src/renderer/core/renderer/renderer_texture.h index eb37a69..7676ad4 100644 --- a/src/renderer/core/renderer/renderer_texture.h +++ b/src/renderer/core/renderer/renderer_texture.h @@ -1,14 +1,42 @@ #pragma once #include <Eigen/Eigen> +#include "renderer.h" + class renderer_texture { public: + renderer_texture(texture_format in_format) : format(in_format) {} virtual ~renderer_texture() = default; - - virtual void* lock() = 0; + virtual void* lock(unsigned int* out_row_pitch) = 0; virtual void unlock() = 0; virtual bool resize(const Eigen::Vector2i& size) = 0; virtual Eigen::Vector2i size() = 0; + + virtual void* get_native_handle() = 0; + virtual void* get_shader_resource_view() = 0; + [[nodiscard]] texture_format get_format() const { return format; } + + + static void convert_rgb_to_rgba(const unsigned char* rgb, unsigned char* rgba, int width, int height) { + for (int i = 0; i < width * height; ++i) { + rgba[i * 4 + 0] = rgb[i * 3 + 0]; // R + rgba[i * 4 + 1] = rgb[i * 3 + 1]; // G + rgba[i * 4 + 2] = rgb[i * 3 + 2]; // B + rgba[i * 4 + 3] = 255; // A (完全不透明) + } + } +private: + const texture_format format; +}; + +class texture_format_converter { +public: + texture_format_converter(Eigen::Vector2i size, texture_format in_format, texture_format out_format) : size(size), in_format(in_format), out_format(out_format) {} + +private: + Eigen::Vector2i size; + texture_format in_format; + texture_format out_format; }; diff --git a/src/renderer/misc/color.cpp b/src/renderer/misc/color.cpp new file mode 100644 index 0000000..ad05900 --- /dev/null +++ b/src/renderer/misc/color.cpp @@ -0,0 +1,3 @@ +#include "color.h" + +const linear_color linear_color::white = linear_color(1, 1, 1, 1); diff --git a/src/renderer/misc/color.h b/src/renderer/misc/color.h index 66d90c6..e9a3a3a 100644 --- a/src/renderer/misc/color.h +++ b/src/renderer/misc/color.h @@ -38,4 +38,12 @@ public: return { r - in_color.r, g - in_color.g, b - in_color.b, a - in_color.a }; } float r, g, b, a; + + + + + + + + static const linear_color white; }; diff --git a/src/renderer/shader/aorii_texture.slang b/src/renderer/shader/aorii_texture.slang new file mode 100644 index 0000000..75f68ce --- /dev/null +++ b/src/renderer/shader/aorii_texture.slang @@ -0,0 +1,35 @@ +struct ParamBuffer +{ + matrix transform; +}; +ParameterBlock<ParamBuffer> param_buffer : register(b0); + +struct VSInput { + float2 position : POSITION; // 窗口坐标 + float2 uv : TEXCOORD0; // 纹理坐标 + float4 color : COLOR; // 颜色 +}; + +struct PSInput { + float4 position : SV_POSITION; // 裁剪空间坐标 + float2 uv : TEXCOORD0; // 纹理坐标 + float4 color : COLOR; // 颜色 +}; + +Texture2D<float4> texture : register(t0); +SamplerState sampler : register(s0); + +PSInput vertex_main(VSInput input) +{ + PSInput output; + output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform); + output.uv = input.uv; + output.color = input.color; + return output; +} + +float4 pixel_main(PSInput input) : SV_TARGET +{ + return input.color * texture.Sample(sampler, input.uv); +} +