新增图片绘制

This commit is contained in:
Nanako 2024-11-06 21:56:47 +08:00
parent 4de6e2d965
commit 9dfc4f2fed
25 changed files with 708 additions and 369 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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; }

View File

@ -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{};
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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() {

View File

@ -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;
};

View File

@ -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() {

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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;
};

View File

@ -0,0 +1,3 @@
#include "color.h"
const linear_color linear_color::white = linear_color(1, 1, 1, 1);

View File

@ -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;
};

View File

@ -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);
}