通过矩阵变换,从CPU侧传入窗口内坐标,变换到顶点坐标
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
|
||||
|
||||
110
src/renderer/backend/dx/dx_buffer.h
Normal file
110
src/renderer/backend/dx/dx_buffer.h
Normal 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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "renderer_buffer.h"
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user