From 6333cb4f7312d72df6df2d7c8d659eaf2d0d8fe4 Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Sun, 20 Oct 2024 17:29:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Edx=5Fpipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/src/main.cpp | 1 - resource/shader/default_shader.slang | 5 +- src/renderer/CMakeLists.txt | 1 + src/renderer/backend/dx/dx_pipeline.cpp | 55 ++++++++++++++++++++-- src/renderer/backend/dx/dx_pipeline.h | 9 +++- src/renderer/backend/dx/dx_window.cpp | 41 +++++++--------- src/renderer/backend/dx/dx_window.h | 2 - src/renderer/core/pipeline/pipeline.h | 12 +++++ src/renderer/core/renderer/renderer.h | 2 +- src/renderer/core/window/renderer_window.h | 12 ++--- src/renderer/misc/color.h | 21 +++++++++ 11 files changed, 122 insertions(+), 39 deletions(-) create mode 100644 src/renderer/misc/color.h diff --git a/example/src/main.cpp b/example/src/main.cpp index 2518281..c5d8767 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -11,7 +11,6 @@ int main(int argc, char* argv[]) { auto window = aorii::create_window({128, 128}, "hello world"); auto glfw_window = window->get_glfw_window(); while (!glfwWindowShouldClose(glfw_window)) { - glfwMakeContextCurrent(glfw_window); glfwPollEvents(); aorii::s_renderer->render(0.01f); } diff --git a/resource/shader/default_shader.slang b/resource/shader/default_shader.slang index 42dc6da..108aaa1 100644 --- a/resource/shader/default_shader.slang +++ b/resource/shader/default_shader.slang @@ -1,19 +1,22 @@ struct VSInput { float3 position : POSITION; + float4 color : COLOR; }; struct PSInput { float4 position : SV_POSITION; + float4 color : COLOR; }; PSInput vertex_main(VSInput input) { PSInput output; output.position = float4(input.position, 1.0f); + output.color = input.color; return output; } float4 pixel_main(PSInput input) : SV_TARGET { - return float4(1.0f, 0.0f, 0.0f, 1.0f); // Red color + return input.color; } diff --git a/src/renderer/CMakeLists.txt b/src/renderer/CMakeLists.txt index 00b9168..b06dec2 100644 --- a/src/renderer/CMakeLists.txt +++ b/src/renderer/CMakeLists.txt @@ -11,6 +11,7 @@ endif() set(RENDERER_SOURCES "") retrieve_files(core RENDERER_SOURCES) +retrieve_files(misc RENDERER_SOURCES) if (GL_BACKEND) retrieve_files(backend/gl RENDERER_SOURCES) endif() diff --git a/src/renderer/backend/dx/dx_pipeline.cpp b/src/renderer/backend/dx/dx_pipeline.cpp index c522f2a..1237f8d 100644 --- a/src/renderer/backend/dx/dx_pipeline.cpp +++ b/src/renderer/backend/dx/dx_pipeline.cpp @@ -26,6 +26,21 @@ void dx_pipeline::use() { d3d_context->IASetInputLayout(input_layout); } +void dx_pipeline::draw() { + auto d3d_context = aorii::get_renderer()->get_d3d_context(); + + // 设置顶点缓冲区 + constexpr UINT stride = sizeof(vertex_type); + constexpr UINT offset = 0; + d3d_context->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); + + // 设置图元拓扑 + d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // 绘制矩形 + d3d_context->Draw(4, 0); +} + void dx_pipeline::set_pixel_shader(const std::string& shader_name) { const auto d3d_device = aorii::get_renderer()->get_d3d_device(); const auto& shader_code = load_shader(shader_name); @@ -38,15 +53,49 @@ void dx_pipeline::set_pixel_shader(const std::string& shader_name) { void dx_pipeline::set_vertex_shader(const std::string& shader_name) { const auto d3d_device = aorii::get_renderer()->get_d3d_device(); const auto& shader_code = load_shader(shader_name); - const auto hr = d3d_device->CreateVertexShader(shader_code.data(), shader_code.size(), nullptr, &vertex_shader); + auto hr = d3d_device->CreateVertexShader(shader_code.data(), shader_code.size(), nullptr, &vertex_shader); if (FAILED(hr)) { spdlog::critical("无法创建顶点着色器: {0}", hr); return; } D3D11_INPUT_ELEMENT_DESC layout_desc[] = { - {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0} + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} }; - d3d_device->CreateInputLayout(layout_desc, 1, shader_code.data(), shader_code.size(), &input_layout); + hr = d3d_device->CreateInputLayout(layout_desc, 2, shader_code.data(), shader_code.size(), &input_layout); + if (FAILED(hr)) { + spdlog::critical("无法创建输入布局: {0}", hr); + return; + } + + D3D11_BUFFER_DESC buffer_desc = {0}; + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.ByteWidth = sizeof(vertex_type) * 4; + buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + hr = d3d_device->CreateBuffer(&buffer_desc, nullptr, &vertex_buffer); + if (FAILED(hr)) { + spdlog::critical("无法创建顶点缓冲区: {0}", hr); + } +} + +std::span dx_pipeline::lock_vertex_buffer() { + const auto d3d_context = aorii::get_renderer()->get_d3d_context(); + D3D11_MAPPED_SUBRESOURCE mapped_resource; + HRESULT hr = d3d_context->Map(vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource); + if (SUCCEEDED(hr)) { + // 更新顶点数据 + vertex_data = static_cast(mapped_resource.pData); + // 这里更新顶点数据 + return {vertex_data, 4}; + } + return {}; +} + +void dx_pipeline::unlock_vertex_buffer() const { + const auto d3d_context = aorii::get_renderer()->get_d3d_context(); + d3d_context->Unmap(vertex_buffer, 0); } // void dx_pipeline::set_compute_shader(const std::string& shader_name) { diff --git a/src/renderer/backend/dx/dx_pipeline.h b/src/renderer/backend/dx/dx_pipeline.h index 2930060..2b4b622 100644 --- a/src/renderer/backend/dx/dx_pipeline.h +++ b/src/renderer/backend/dx/dx_pipeline.h @@ -4,16 +4,20 @@ #include #include "core/pipeline/pipeline.h" +#include class dx_pipeline : public pipeline { public: ~dx_pipeline() override; void use() override; - + void draw() override; void set_pixel_shader(const std::string& shader_name) override; void set_vertex_shader(const std::string& shader_name) override; // void set_compute_shader(const std::string& shader_name) override; + + std::span lock_vertex_buffer(); + void unlock_vertex_buffer() const; private: static std::vector load_shader(const std::string& shader_name); @@ -21,4 +25,7 @@ private: ID3D11PixelShader* pixel_shader = nullptr; // ID3D11ComputeShader* compute_shader = nullptr; ID3D11InputLayout* input_layout = nullptr; + ID3D11Buffer* vertex_buffer = nullptr; + + vertex_type* vertex_data = nullptr; }; diff --git a/src/renderer/backend/dx/dx_window.cpp b/src/renderer/backend/dx/dx_window.cpp index e39eb40..e102dec 100644 --- a/src/renderer/backend/dx/dx_window.cpp +++ b/src/renderer/backend/dx/dx_window.cpp @@ -67,26 +67,11 @@ bool dx_window::create_surface(GLFWwindow* in_window) { pipeline.set_pixel_shader("default_shader_pixel"); pipeline.set_vertex_shader("default_shader_vertex"); - Eigen::Vector3f vertices[] = { - {-0.5f, -0.5f, 0.0f}, - {0.5f, -0.5f, 0.0f}, - {0.5f, 0.5f, 0.0f}, - {-0.5f, 0.5f, 0.0f} - }; - - D3D11_BUFFER_DESC buffer_desc = {0}; - buffer_desc.Usage = D3D11_USAGE_DEFAULT; - buffer_desc.ByteWidth = sizeof(vertex_data) * 4; - buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - - D3D11_SUBRESOURCE_DATA subresource_data = {}; - subresource_data.pSysMem = vertices; - d3d_device->CreateBuffer(&buffer_desc, &subresource_data, &vertex_buffer); - return true; } void dx_window::begin_frame() { + glfwMakeContextCurrent(get_glfw_window()); const auto render = aorii::get_renderer(); const auto d3d_context = render->get_d3d_context(); @@ -95,16 +80,24 @@ void dx_window::begin_frame() { pipeline.use(); - // 设置顶点缓冲区 - UINT stride = sizeof(Eigen::Vector3f); - UINT offset = 0; - d3d_context->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset); + float random_r = static_cast(rand()) / RAND_MAX; + float random_g = static_cast(rand()) / RAND_MAX; + float random_b = static_cast(rand()) / RAND_MAX; + linear_color random_color = {random_r, random_g, random_b, 1.0f}; - // 设置图元拓扑 - d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + const vertex_type v1 {{-0.5f, 0.5f, 0.0f}, random_color }; + const vertex_type v2 {{0.5f, 0.5f, 0.0f}, random_color }; + const vertex_type v3 {{-0.5f, -0.5f, 0.0f}, random_color }; + const vertex_type v4 {{0.5f, -0.5f, 0.0f}, random_color }; + const vertex_type vertices[] = { + v1, v2, v3, v4 + }; - // 绘制矩形 - d3d_context->Draw(4, 0); + auto vertex_buffer = pipeline.lock_vertex_buffer(); + std::ranges::copy(vertices, vertex_buffer.begin()); + pipeline.unlock_vertex_buffer(); + + pipeline.draw(); swap_chain->Present(1, 0); } diff --git a/src/renderer/backend/dx/dx_window.h b/src/renderer/backend/dx/dx_window.h index 306ed41..70eda24 100644 --- a/src/renderer/backend/dx/dx_window.h +++ b/src/renderer/backend/dx/dx_window.h @@ -19,6 +19,4 @@ private: ID3D11RenderTargetView* render_target_view = nullptr; dx_pipeline pipeline; - - ID3D11Buffer* vertex_buffer; }; diff --git a/src/renderer/core/pipeline/pipeline.h b/src/renderer/core/pipeline/pipeline.h index 0d4c13d..e13162b 100644 --- a/src/renderer/core/pipeline/pipeline.h +++ b/src/renderer/core/pipeline/pipeline.h @@ -1,11 +1,23 @@ #pragma once #include +#include + +#include "misc/color.h" + + +struct aorii_vertex { + Eigen::Vector3f position; + linear_color color; +}; +using vertex_type = aorii_vertex; class pipeline { public: + virtual ~pipeline() = default; virtual void use() = 0; + virtual void draw() = 0; virtual void set_vertex_shader(const std::string& shader_name) = 0; virtual void set_pixel_shader(const std::string& shader_name) = 0; diff --git a/src/renderer/core/renderer/renderer.h b/src/renderer/core/renderer/renderer.h index 01027f6..befa462 100644 --- a/src/renderer/core/renderer/renderer.h +++ b/src/renderer/core/renderer/renderer.h @@ -44,7 +44,7 @@ namespace aorii { bool create_renderer(renderer_api api); void destroy_renderer(); - inline std::filesystem::path s_shader_relative_path = "resource/shaders"; + inline std::filesystem::path s_shader_relative_path = "resource/shader"; inline void set_shader_relative_path(const std::filesystem::path& path) { s_shader_relative_path = path; } inline std::filesystem::path get_shader_path(const std::string& shader_name) { return std::filesystem::current_path() / s_shader_relative_path / shader_name; } } diff --git a/src/renderer/core/window/renderer_window.h b/src/renderer/core/window/renderer_window.h index 5857b0a..30957d4 100644 --- a/src/renderer/core/window/renderer_window.h +++ b/src/renderer/core/window/renderer_window.h @@ -19,20 +19,20 @@ public: on_resize(in_size); } - Eigen::Vector2i get_window_size() const { + [[nodiscard]] Eigen::Vector2i get_window_size() const { int w, h; glfwGetWindowSize(window, &w, &h); - return Eigen::Vector2i(w, h); + return { w, h }; } - Eigen::Vector2i get_framebuffer_size() const { + [[nodiscard]] Eigen::Vector2i get_framebuffer_size() const { int w, h; glfwGetFramebufferSize(window, &w, &h); - return Eigen::Vector2i(w, h); + return { w, h }; } - void* get_window_handle() const; - GLFWwindow* get_glfw_window() const { return window; } + [[nodiscard]] void* get_window_handle() const; + [[nodiscard]] GLFWwindow* get_glfw_window() const { return window; } protected: virtual bool create_surface(GLFWwindow* in_window) = 0; virtual void on_resize(const Eigen::Vector2i& in_size) = 0; diff --git a/src/renderer/misc/color.h b/src/renderer/misc/color.h new file mode 100644 index 0000000..0fdde0b --- /dev/null +++ b/src/renderer/misc/color.h @@ -0,0 +1,21 @@ +#pragma once +#include + +class linear_color { +public: + linear_color(float in_r, float in_g, float in_b, float in_a = 1.0f) : r(in_r), g(in_g), b(in_b), a(in_a) {} + + static linear_color from_srgb(float in_r, float in_g, float in_b, float in_a = 1.0f) { + return linear_color( + in_r <= 0.04045f ? in_r / 12.92f : std::pow((in_r + 0.055f) / 1.055f, 2.4f), + in_g <= 0.04045f ? in_g / 12.92f : std::pow((in_g + 0.055f) / 1.055f, 2.4f), + in_b <= 0.04045f ? in_b / 12.92f : std::pow((in_b + 0.055f) / 1.055f, 2.4f), + in_a + ); + } + static linear_color from_srgb(const linear_color& in_color) { + return from_srgb(in_color.r, in_color.g, in_color.b, in_color.a); + } +private: + float r, g, b, a; +};