通过矩阵变换,从CPU侧传入窗口内坐标,变换到顶点坐标

This commit is contained in:
2024-10-28 22:17:46 +08:00
parent 6333cb4f73
commit 6c8db0d783
11 changed files with 231 additions and 39 deletions

View File

@@ -1,5 +1,11 @@
struct MatrixBuffer
{
matrix transform;
};
ParameterBlock<MatrixBuffer> matrix_buffer;
struct VSInput {
float3 position : POSITION;
float2 position : POSITION;
float4 color : COLOR;
};
@@ -11,7 +17,7 @@ struct PSInput {
PSInput vertex_main(VSInput input)
{
PSInput output;
output.position = float4(input.position, 1.0f);
output.position = mul(float4(input.position, 0.0, 1.0), matrix_buffer.transform);
output.color = input.color;
return output;
}

View File

@@ -27,7 +27,7 @@ endif ()
add_library(${PROJECT_NAME} STATIC ${RENDERER_SOURCES})
target_link_libraries(${PROJECT_NAME} PUBLIC Eigen3::Eigen spdlog::spdlog glfw aorii_core)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
add_os_definitions(${PROJECT_NAME})
configure_glfw_native(${PROJECT_NAME})

View File

@@ -0,0 +1,110 @@
#pragma once
#include <d3d11.h>
#include <spdlog/spdlog.h>
#include "dx_renderer.h"
#include "core/renderer/renderer_buffer.h"
template<typename DataType>
class dx_buffer : public renderer_buffer<DataType> {
public:
explicit dx_buffer(buffer_type in_type, const int count);
~dx_buffer() override;
DataType* lock() override;
void unlock() override;
[[nodiscard]] unsigned int get_dx_buffer_type() const {
switch (this->get_type()) {
case buffer_type::vertex:
return D3D11_BIND_VERTEX_BUFFER;
case buffer_type::index:
return D3D11_BIND_INDEX_BUFFER;
case buffer_type::constant:
return D3D11_BIND_CONSTANT_BUFFER;
default:
return 0;
}
}
[[nodiscard]] void* get_native_handle() override {
return buffer;
}
protected:
void on_resize(int new_count) override;
private:
ID3D11Buffer* buffer = nullptr;
};
template<typename DataType>
dx_buffer<DataType>::dx_buffer(buffer_type in_type, const int count): renderer_buffer<DataType>(in_type, count) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
D3D11_BUFFER_DESC buffer_desc = {};
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.ByteWidth = sizeof(DataType) * count;
buffer_desc.BindFlags = get_dx_buffer_type();
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
auto hr = d3d_device->CreateBuffer(&buffer_desc, nullptr, &buffer);
if (FAILED(hr)) {
spdlog::critical("无法创建缓冲区: {0}", hr);
}
}
template<typename DataType>
dx_buffer<DataType>::~dx_buffer() {
if (buffer) {
buffer->Release();
}
}
template<typename DataType>
DataType* dx_buffer<DataType>::lock() {
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
D3D11_MAPPED_SUBRESOURCE mapped_resource;
HRESULT hr = d3d_context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource);
if (SUCCEEDED(hr)) {
return static_cast<DataType*>(mapped_resource.pData);
}
return {};
}
template<typename DataType>
void dx_buffer<DataType>::unlock() {
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
d3d_context->Unmap(buffer, 0);
}
template<typename DataType>
void dx_buffer<DataType>::on_resize(int new_count) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
D3D11_BUFFER_DESC buffer_desc = {};
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.ByteWidth = sizeof(DataType) * new_count;
buffer_desc.BindFlags = get_dx_buffer_type();
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ID3D11Buffer* new_buffer = nullptr;
auto hr = d3d_device->CreateBuffer(&buffer_desc, nullptr, &new_buffer);
if (FAILED(hr)) {
spdlog::critical("无法创建缓冲区: {0}", hr);
return;
}
if (new_buffer) {
// 复制旧数据到新缓冲区
D3D11_BOX source_region;
source_region.left = 0;
source_region.right = sizeof(DataType) * new_count;
source_region.top = 0;
source_region.bottom = 1;
source_region.front = 0;
source_region.back = 1;
d3d_context->CopySubresourceRegion(new_buffer, 0, 0, 0, 0, buffer, 0, &source_region);
buffer->Release();
}
buffer = new_buffer;
}

View File

@@ -13,6 +13,8 @@ dx_pipeline::~dx_pipeline() {
if (pixel_shader) {
pixel_shader->Release();
}
delete vertex_buffer;
delete constant_buffer;
// if (compute_shader) {
// compute_shader->Release();
// }
@@ -32,7 +34,10 @@ void dx_pipeline::draw() {
// 设置顶点缓冲区
constexpr UINT stride = sizeof(vertex_type);
constexpr UINT offset = 0;
d3d_context->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &offset);
auto* v_buffer = static_cast<ID3D11Buffer*>(vertex_buffer->get_native_handle());
auto* c_buffer = static_cast<ID3D11Buffer*>(constant_buffer->get_native_handle());
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
// 设置图元拓扑
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
@@ -59,43 +64,40 @@ void dx_pipeline::set_vertex_shader(const std::string& shader_name) {
return;
}
D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
{"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}
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
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;
void dx_pipeline::build_vertex_buffer(int vertex_count) {
delete vertex_buffer;
vertex_buffer = new dx_buffer<vertex_type>(buffer_type::vertex, vertex_count);
}
hr = d3d_device->CreateBuffer(&buffer_desc, nullptr, &vertex_buffer);
if (FAILED(hr)) {
spdlog::critical("无法创建顶点缓冲区: {0}", hr);
}
void dx_pipeline::build_constant_buffer() {
constant_buffer = new dx_buffer<constant_buffer_type>(buffer_type::constant, 1);
}
std::span<vertex_type> dx_pipeline::lock_vertex_buffer() {
const auto d3d_context = aorii::get_renderer<dx_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<vertex_type*>(mapped_resource.pData);
// 这里更新顶点数据
return {vertex_data, 4};
}
return {};
return {vertex_buffer->lock(), 4};
}
void dx_pipeline::unlock_vertex_buffer() const {
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
d3d_context->Unmap(vertex_buffer, 0);
void dx_pipeline::unlock_vertex_buffer() {
vertex_buffer->unlock();
}
void dx_pipeline::set_projection_matrix(const Eigen::Matrix4f& matrix) {
if (!constant_buffer) {
return;
}
const auto data = constant_buffer->lock();
data->projection_matrix = matrix;
constant_buffer->unlock();
}
// void dx_pipeline::set_compute_shader(const std::string& shader_name) {

View File

@@ -6,6 +6,8 @@
#include "core/pipeline/pipeline.h"
#include <span>
#include "dx_buffer.h"
class dx_pipeline : public pipeline {
public:
~dx_pipeline() override;
@@ -14,10 +16,14 @@ public:
void set_pixel_shader(const std::string& shader_name) override;
void set_vertex_shader(const std::string& shader_name) override;
void build_vertex_buffer(int vertex_count) override;
void build_constant_buffer() override;
// void set_compute_shader(const std::string& shader_name) override;
std::span<vertex_type> lock_vertex_buffer();
void unlock_vertex_buffer() const;
void unlock_vertex_buffer();
void set_projection_matrix(const Eigen::Matrix4f& matrix);
private:
static std::vector<char> load_shader(const std::string& shader_name);
@@ -25,7 +31,7 @@ private:
ID3D11PixelShader* pixel_shader = nullptr;
// ID3D11ComputeShader* compute_shader = nullptr;
ID3D11InputLayout* input_layout = nullptr;
ID3D11Buffer* vertex_buffer = nullptr;
vertex_type* vertex_data = nullptr;
dx_buffer<vertex_type>* vertex_buffer = nullptr;
dx_buffer<constant_buffer_type>* constant_buffer = nullptr;
};

View File

@@ -58,6 +58,9 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
return false;
}
pipeline.build_vertex_buffer(4);
pipeline.build_constant_buffer();
hr = build_render_target_view();
if (FAILED(hr)) {
spdlog::critical("无法创建渲染模板视图, 错误: {0}", hr);
@@ -85,10 +88,10 @@ void dx_window::begin_frame() {
float random_b = static_cast<float>(rand()) / RAND_MAX;
linear_color random_color = {random_r, random_g, random_b, 1.0f};
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 v1 {{0.f, 0.f}, random_color }; // 左上角
const vertex_type v2 {{100.f, 0.f}, random_color }; // 右上角
const vertex_type v3 {{0.f, 100.f}, random_color }; // 左下角
const vertex_type v4 {{100.f, 100.f}, random_color }; // 右下角
const vertex_type vertices[] = {
v1, v2, v3, v4
};
@@ -152,5 +155,9 @@ HRESULT dx_window::build_render_target_view() {
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
d3d_context->RSSetViewports(1, &viewport);
const auto& projection_matrix = get_projection_matrix().transpose();
pipeline.set_projection_matrix(projection_matrix);
return hr;
}

View File

@@ -6,10 +6,14 @@
struct aorii_vertex {
Eigen::Vector3f position;
Eigen::Vector2f position;
linear_color color;
};
struct aorii_constant_buffer {
Eigen::Matrix4f projection_matrix;
};
using vertex_type = aorii_vertex;
using constant_buffer_type = aorii_constant_buffer;
class pipeline {
public:
@@ -21,5 +25,7 @@ public:
virtual void set_vertex_shader(const std::string& shader_name) = 0;
virtual void set_pixel_shader(const std::string& shader_name) = 0;
virtual void build_vertex_buffer(int vertex_count) = 0;
virtual void build_constant_buffer() = 0;
// virtual void set_compute_shader(const std::string& shader_name) = 0;
};

View File

@@ -1 +0,0 @@
#include "renderer_buffer.h"

View File

@@ -1,5 +1,36 @@
#pragma once
#include <span>
class renderer_buffer {
enum class buffer_type {
vertex,
index,
constant,
};
template<typename DataType>
class renderer_buffer {
public:
explicit renderer_buffer(buffer_type in_type, const int count = 1) : count(count), type(in_type) {}
virtual ~renderer_buffer() = default;
virtual DataType* lock() = 0;
virtual void unlock() = 0;
void resize(const int new_count) {
if (new_count == count)
return;
count = new_count;
on_resize(new_count);
}
[[nodiscard]] int get_count() const {
return count;
}
[[nodiscard]] buffer_type get_type() const {
return type;
}
[[nodiscard]] virtual void* get_native_handle() = 0;
protected:
virtual void on_resize(int new_count) = 0;
int count;
const buffer_type type;
};

View File

@@ -9,6 +9,30 @@ bool renderer_window::init(const Eigen::Vector2i& in_size, const std::string& in
return create_surface(window);
}
Eigen::Matrix4f renderer_window::get_projection_matrix() const {
// 创建一个单位矩阵
Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
const auto& window_size = get_window_size();
// 缩放因子
const float scale_x = 2.0f / static_cast<float>(window_size.x());
const float scale_y = -2.0f / static_cast<float>(window_size.y()); // Y轴翻转因为窗口坐标系Y轴向下
// 平移因子
constexpr float translate_x = -1.0f;
constexpr float translate_y = 1.0f;
// 设置缩放
matrix(0, 0) = scale_x;
matrix(1, 1) = scale_y;
// 设置平移
matrix(0, 3) = translate_x;
matrix(1, 3) = translate_y;
return matrix;
}
void* renderer_window::get_window_handle() const {
#if WINDOWS
return glfwGetWin32Window(window);

View File

@@ -30,6 +30,7 @@ public:
glfwGetFramebufferSize(window, &w, &h);
return { w, h };
}
[[nodiscard]] virtual Eigen::Matrix4f get_projection_matrix() const;
[[nodiscard]] void* get_window_handle() const;
[[nodiscard]] GLFWwindow* get_glfw_window() const { return window; }