代码整理

This commit is contained in:
Nanako 2024-11-06 18:49:50 +08:00
parent 879732da6e
commit 1a10d65de1
30 changed files with 1106 additions and 331 deletions

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.15)
project(aorii)
set(CMAKE_CXX_STANDARD 23)
@ -10,6 +10,8 @@ include(cmake/compile_shaders.cmake)
find_package(Eigen3 REQUIRED)
find_package(spdlog REQUIRED)
find_package(glfw3 REQUIRED)
find_package(Freetype REQUIRED)
find_package(Stb REQUIRED)
# Debug,
if (CMAKE_BUILD_TYPE STREQUAL "Debug")

View File

@ -26,8 +26,8 @@ if (METAL_BACKEND)
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})
target_link_libraries(${PROJECT_NAME} PUBLIC Eigen3::Eigen spdlog::spdlog glfw aorii_core Freetype::Freetype)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${Stb_INCLUDE_DIR})
target_compile_definitions(${PROJECT_NAME} PRIVATE NOMINMAX)
add_os_definitions(${PROJECT_NAME})
configure_glfw_native(${PROJECT_NAME})
@ -54,15 +54,18 @@ foreach(BACKEND ${ALL_BACKENDS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${BACKEND}=0)
endforeach()
# shader
if (NOT DEFINED SHADER_OUTPUT_DIR)
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shaders CACHE PATH "Output directory for compiled shaders")
message(STATUS "SHADER_OUTPUT_DIR not defined, using default: ${SHADER_OUTPUT_DIR}")
endif ()
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "vertex" "vertex_main")
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "pixel" "pixel_main")
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "pixel" "rounded_rect_pixel_main" -D IS_ROUNDED_RECT)
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "vertex" "vertex_main")
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")
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
# example, shader
if (BUILD_EXAMPLE)
# ${SHADER_OUTPUT_DIR}${CMAKE_CURRENT_BINARY_DIR}/example/resource/shaders
set(SOURCE_DIR ${SHADER_OUTPUT_DIR})

View File

@ -5,15 +5,34 @@
#include "dx_renderer.h"
#include "core/renderer/renderer_buffer.h"
template<typename DataType>
class dx_buffer : public renderer_buffer<DataType> {
class dx_buffer : public renderer_buffer {
public:
explicit dx_buffer(buffer_type in_type, int in_count);
explicit dx_buffer(buffer_type in_type, int in_element_byte, int in_size): renderer_buffer(in_type, in_element_byte, in_size) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
~dx_buffer() override;
D3D11_BUFFER_DESC buffer_desc = {};
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.ByteWidth = in_element_byte * in_size;
buffer_desc.BindFlags = get_dx_buffer_type();
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
DataType* lock() override;
void unlock() override;
auto hr = d3d_device->CreateBuffer(&buffer_desc, nullptr, &buffer);
if (FAILED(hr)) { spdlog::critical("无法创建缓冲区: {0}", hr); }
}
~dx_buffer() override { if (buffer) { buffer->Release(); } }
void* lock() override {
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 mapped_resource.pData; }
return {};
}
void unlock() override {
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
d3d_context->Unmap(buffer, 0);
}
[[nodiscard]] unsigned int get_dx_buffer_type() const {
switch (this->get_type()) {
@ -31,83 +50,40 @@ public:
return buffer;
}
protected:
void on_resize(int new_count) override;
void on_resize(int new_count) override {
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 old_desc = {};
if (buffer) {
buffer->GetDesc(&old_desc);
}
D3D11_BUFFER_DESC buffer_desc = old_desc;
buffer_desc.ByteWidth = element_byte * new_count;
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 && buffer) {
// 计算要复制的实际大小(取原始大小和新大小的较小值)
const auto copy_size = std::min(old_desc.ByteWidth, buffer_desc.ByteWidth);
// 复制旧数据到新缓冲区
D3D11_BOX source_region;
source_region.left = 0;
source_region.right = copy_size;
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);
}
if (buffer)
buffer->Release();
buffer = new_buffer;
}
private:
ID3D11Buffer* buffer = nullptr;
};
template<typename DataType>
dx_buffer<DataType>::dx_buffer(buffer_type in_type, const int in_count): renderer_buffer<DataType>(in_type, in_count) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
D3D11_BUFFER_DESC buffer_desc = {};
buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
buffer_desc.ByteWidth = sizeof(DataType) * in_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 old_desc = {};
if (buffer) {
buffer->GetDesc(&old_desc);
}
D3D11_BUFFER_DESC buffer_desc = old_desc;
buffer_desc.ByteWidth = sizeof(DataType) * new_count;
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 && buffer) {
// 计算要复制的实际大小(取原始大小和新大小的较小值)
const auto copy_size = std::min(old_desc.ByteWidth, buffer_desc.ByteWidth);
// 复制旧数据到新缓冲区
D3D11_BOX source_region;
source_region.left = 0;
source_region.right = copy_size;
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);
}
if (buffer)
buffer->Release();
buffer = new_buffer;
}

View File

@ -1,93 +0,0 @@
#include "dx_pipeline.h"
#include <fstream>
#include <spdlog/spdlog.h>
#include "dx_renderer.h"
#include "core/renderer/renderer.h"
dx_pipeline::dx_pipeline(): vertex_buffer(buffer_type::vertex, 4), triangle_buffer(buffer_type::index, 2), constant_buffer(buffer_type::constant, 1) {
}
dx_pipeline::~dx_pipeline() {
if (vertex_shader) { vertex_shader->Release(); }
if (pixel_shader) { pixel_shader->Release(); }
}
void dx_pipeline::use() {
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);
}
void dx_pipeline::draw() {
auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
// 设置顶点缓冲区
constexpr UINT stride = sizeof(aorii_vertex_type);
constexpr UINT offset = 0;
auto* v_buffer = static_cast<ID3D11Buffer*>(vertex_buffer.get_native_handle());
auto* i_buffer = static_cast<ID3D11Buffer*>(triangle_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->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
d3d_context->PSSetConstantBuffers(0, 1, &c_buffer);
// 设置图元拓扑
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// 绘制矩形
d3d_context->Draw(vertex_buffer.get_size(), 0);
}
void dx_pipeline::load_pixel_shader(const char* shader_name) {
if (pixel_shader) { pixel_shader->Release(); }
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto& shader_code = load_shader(shader_name);
const auto hr = d3d_device->CreatePixelShader(shader_code.data(), shader_code.size(), nullptr, &pixel_shader);
if (FAILED(hr)) { spdlog::critical("无法创建像素着色器: {0}", hr); }
}
void dx_pipeline::load_vertex_shader() {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto& shader_code = load_shader(AORII_DEFAULT_VERTEX_SHADER_NAME);
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_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;
}
}
void dx_pipeline::set_triangle(const std::span<const aorii_vertex_type>& in_vertexes,
const std::span<const aorii_triangle_type>& in_triangles) {
if (vertex_buffer.get_size() < in_vertexes.size()) { vertex_buffer.resize(static_cast<int>(in_vertexes.size())); }
aorii_vertex_type* v_buffer = vertex_buffer.lock();
std::ranges::copy(in_vertexes, v_buffer);
vertex_buffer.unlock();
if (triangle_buffer.get_size() < in_triangles.size()) { triangle_buffer.resize(static_cast<int>(in_triangles.size())); }
aorii_triangle_type* i_buffer = triangle_buffer.lock();
std::ranges::copy(in_triangles, i_buffer);
triangle_buffer.unlock();
}
aorii_constant_buffer_type* dx_pipeline::lock_constant_buffer() { return constant_buffer.lock(); }
void dx_pipeline::unlock_constant_buffer() { constant_buffer.unlock(); }
std::vector<char> dx_pipeline::load_shader(const std::string& shader_name) {
auto file_pathname = aorii::get_shader_path(shader_name).generic_string() + ".dxbc";
std::ifstream file(file_pathname, std::ios::binary);
return { (std::istreambuf_iterator(file)), std::istreambuf_iterator<char>() };
}

View File

@ -1,37 +0,0 @@
#pragma once
#include <d3d11.h>
#include <vector>
#include "core/pipeline/pipeline.h"
#include <span>
#include "dx_buffer.h"
class dx_pipeline : public pipeline {
public:
dx_pipeline();
~dx_pipeline() override;
void use() override;
void draw() override;
void load_pixel_shader(const char* shader_name);
void load_vertex_shader();
void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) override;
aorii_constant_buffer_type* lock_constant_buffer() override;
void unlock_constant_buffer() override;
private:
static std::vector<char> load_shader(const std::string& shader_name);
ID3D11VertexShader* vertex_shader = nullptr;
ID3D11PixelShader* pixel_shader = nullptr;
ID3D11InputLayout* input_layout = nullptr;
dx_buffer<aorii_vertex_type> vertex_buffer;
dx_buffer<aorii_triangle_type> triangle_buffer;
dx_buffer<aorii_constant_buffer_type> constant_buffer;
int vertex_count = 0;
};

View File

@ -1,12 +1,153 @@
#include "dx_renderer.h"
#include <fstream>
#include <GLFW/glfw3.h>
#include "dx_buffer.h"
#include "dx_texture.h"
#include "dx_window.h"
#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);
@ -29,24 +170,16 @@ bool dx_renderer::init() {
return false;
}
default_pipeline = new dx_pipeline();
rounded_rect_pipeline = new dx_pipeline();
default_pipeline->load_pixel_shader(AORII_DEFAULT_PIXEL_SHADER_NAME);
default_pipeline->load_vertex_shader();
rounded_rect_pipeline->load_pixel_shader(AORII_DEFAULT_ROUNDED_RECT_PIXEL_SHADER_NAME);
rounded_rect_pipeline->load_vertex_shader();
default_pipeline.init();
rounded_rect_pipeline.init();
return true;
}
void dx_renderer::destroy() {
if (blend_state) blend_state->Release();
delete default_pipeline;
delete rounded_rect_pipeline;
default_pipeline = nullptr;
rounded_rect_pipeline = nullptr;
default_pipeline.destroy();
rounded_rect_pipeline.destroy();
glfwTerminate();
}
@ -65,13 +198,13 @@ void dx_renderer::destroy_texture(renderer_texture* texture) {
#endif
}
renderer_texture* dx_renderer::create_texture(const Eigen::Vector2i& size) {
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 = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.Format = get_dxgi_format(in_format);
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DYNAMIC;
@ -85,6 +218,16 @@ renderer_texture* dx_renderer::create_texture(const Eigen::Vector2i& size) {
return new dx_texture(texture);
}
std::vector<char> dx_renderer::load_shader(const std::string& shader_name) {
auto file_pathname = aorii::get_shader_path(shader_name).generic_string() + ".dxbc";
std::ifstream file(file_pathname, std::ios::binary);
return { (std::istreambuf_iterator(file)), std::istreambuf_iterator<char>() };
}
renderer_buffer* dx_renderer::create_buffer(buffer_type in_buffer_type, int in_element_byte, int in_size) {
return new dx_buffer(in_buffer_type, in_element_byte, in_size);
}
renderer_window* dx_renderer::create_window() {
return new dx_window();
}

View File

@ -2,8 +2,9 @@
#include <d3d11.h>
#include "core/renderer/renderer.h"
#include "pipeline/dx_rect_pipeline.h"
#include "pipeline/dx_rounded_rect_pipeline.h"
class dx_pipeline;
class dx_window;
class dx_renderer : public renderer {
@ -12,15 +13,19 @@ public:
void destroy() override;
bool render() override;
renderer_texture* create_texture(const Eigen::Vector2i& size) 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; }
[[nodiscard]] dx_pipeline* get_default_pipeline() const { return default_pipeline; }
[[nodiscard]] dx_pipeline* get_rounded_rect_pipeline() const { return rounded_rect_pipeline; }
rect_pipeline* get_rect_pipeline() override { return &default_pipeline; }
rounded_rect_pipeline* get_rounded_rect_pipeline() override { return &rounded_rect_pipeline; }
[[nodiscard]] ID3D11BlendState* get_blend_state() const { return blend_state; }
std::vector<char> load_shader(const std::string& shader_name) override;
renderer_buffer* create_buffer(buffer_type in_buffer_type, int in_element_byte, int in_size) override;
private:
renderer_window* create_window() override;
@ -30,7 +35,7 @@ private:
ID3D11DeviceContext* context = nullptr;
ID3D11BlendState* blend_state = nullptr;
dx_pipeline* default_pipeline = nullptr;
dx_pipeline* rounded_rect_pipeline = nullptr;
dx_rect_pipeline default_pipeline;
dx_rounded_rect_pipeline rounded_rect_pipeline;
};

View File

@ -58,8 +58,8 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
spdlog::critical("无法创建交换链, 错误: {0}", hr);
return false;
}
context.set_default_pipeline(dx->get_default_pipeline());
context.set_rounded_rectangular_pipeline(dx->get_rounded_rect_pipeline());
context.init();
hr = build_render_target_view();
if (FAILED(hr)) {
@ -125,7 +125,8 @@ void dx_window::begin_frame() {
}
context.draw_rectangle({ 400, 0 }, { 100, 100 }, { 0, 1, 0, 1 });
context.draw_rounded_rectangle({ 100, 100 }, { 200, 200 }, { 1, 0, 0, 1 }, 10);
auto radius = abs(sin(get_total_time().count())) * 50;
context.draw_rounded_rectangle({ 100, 100 }, { 200, 200 }, { 1, 0, 0, 1 }, radius);
context.flush();
swap_chain->Present(1, 0);

View File

@ -2,7 +2,6 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include "dx_pipeline.h"
#include "core/renderer/renderer_context.h"
#include "core/window/renderer_window.h"

View File

@ -0,0 +1,61 @@
#include "dx_rect_pipeline.h"
#include "backend/dx/dx_renderer.h"
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_DEFAULT_VERTEX_SHADER_NAME);
const auto& pixel_shader_code = renderer->load_shader(AORII_DEFAULT_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 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 8, 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_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);
}
void dx_rect_pipeline::draw() {
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());
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
// 设置图元拓扑
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// 绘制矩形
d3d_context->Draw(vertex_buffer->get_size(), 0);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <d3d11.h>
#include "core/pipeline/rect_pipeline.h"
class dx_rect_pipeline : public rect_pipeline {
public:
bool init() override;
void use() override;
void draw() override;
private:
ID3D11VertexShader* vertex_shader = nullptr;
ID3D11PixelShader* pixel_shader = nullptr;
ID3D11InputLayout* input_layout = nullptr;
};

View File

@ -0,0 +1,63 @@
#include "dx_rounded_rect_pipeline.h"
#include "backend/dx/dx_renderer.h"
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_DEFAULT_VERTEX_SHADER_NAME);
const auto& pixel_shader_code = renderer->load_shader(AORII_DEFAULT_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_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);
}
void dx_rounded_rect_pipeline::draw() {
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());
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
d3d_context->PSSetConstantBuffers(0, 1, &c_buffer);
// 设置图元拓扑
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// 绘制矩形
d3d_context->Draw(vertex_buffer->get_size(), 0);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <d3d11.h>
#include "core/pipeline/rounded_rect_pipeline.h"
class dx_rounded_rect_pipeline : public rounded_rect_pipeline {
public:
bool init() override;
void use() override;
void draw() override;
private:
ID3D11VertexShader* vertex_shader = nullptr;
ID3D11PixelShader* pixel_shader = nullptr;
ID3D11InputLayout* input_layout = nullptr;
};

View File

@ -0,0 +1,119 @@
#include "gl_renderer.h"
#include <GL/gl.h>
#include <GL/glad.h> // 或 <glad/glad.h>
GLenum GetOpenGLInternalFormat(texture_format format) {
switch (format) {
// 8-bit formats
case texture_format::R8_UNORM:
return GL_R8;
case texture_format::R8_SNORM:
return GL_R8_SNORM;
case texture_format::R8_UINT:
return GL_R8UI;
case texture_format::R8_SINT:
return GL_R8I;
// 16-bit formats
case texture_format::RG8_UNORM:
return GL_RG8;
case texture_format::RG8_SNORM:
return GL_RG8_SNORM;
case texture_format::RG8_UINT:
return GL_RG8UI;
case texture_format::RG8_SINT:
return GL_RG8I;
// 24-bit formats
case texture_format::RGB8_UNORM:
return GL_RGB8;
case texture_format::RGB8_SNORM:
return GL_RGB8_SNORM;
case texture_format::RGB8_UINT:
return GL_RGB8UI;
case texture_format::RGB8_SINT:
return GL_RGB8I;
// 32-bit formats
case texture_format::RGBA8_UNORM:
return GL_RGBA8;
case texture_format::RGBA8_SNORM:
return GL_RGBA8_SNORM;
case texture_format::RGBA8_UINT:
return GL_RGBA8UI;
case texture_format::RGBA8_SINT:
return GL_RGBA8I;
// SRGB formats
case texture_format::SRGB8:
return GL_SRGB8;
case texture_format::SRGB8_ALPHA8:
return GL_SRGB8_ALPHA8;
// 16-bit float formats
case texture_format::R16_FLOAT:
return GL_R16F;
case texture_format::RG16_FLOAT:
return GL_RG16F;
case texture_format::RGB16_FLOAT:
return GL_RGB16F;
case texture_format::RGBA16_FLOAT:
return GL_RGBA16F;
// 32-bit float formats
case texture_format::R32_FLOAT:
return GL_R32F;
case texture_format::RG32_FLOAT:
return GL_RG32F;
case texture_format::RGB32_FLOAT:
return GL_RGB32F;
case texture_format::RGBA32_FLOAT:
return GL_RGBA32F;
// Integer formats
case texture_format::R16_UINT:
return GL_R16UI;
case texture_format::R16_SINT:
return GL_R16I;
case texture_format::RG16_UINT:
return GL_RG16UI;
case texture_format::RG16_SINT:
return GL_RG16I;
case texture_format::RGBA16_UINT:
return GL_RGBA16UI;
case texture_format::RGBA16_SINT:
return GL_RGBA16I;
case texture_format::R32_UINT:
return GL_R32UI;
case texture_format::R32_SINT:
return GL_R32I;
case texture_format::RG32_UINT:
return GL_RG32UI;
case texture_format::RG32_SINT:
return GL_RG32I;
case texture_format::RGBA32_UINT:
return GL_RGBA32UI;
case texture_format::RGBA32_SINT:
return GL_RGBA32I;
// Depth/stencil formats
case texture_format::D16_UNORM:
return GL_DEPTH_COMPONENT16;
case texture_format::D24_UNORM_S8_UINT:
return GL_DEPTH24_STENCIL8;
case texture_format::D32_FLOAT:
return GL_DEPTH_COMPONENT32F;
case texture_format::D32_FLOAT_S8X24_UINT:
return GL_DEPTH32F_STENCIL8;
// Compressed formats
case texture_format::BC1_UNORM:
return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
case texture_format::BC3_UNORM:
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
default:
return 0; // Unsupported format
}
}

View File

@ -0,0 +1,6 @@
#pragma once
#include "core/renderer/renderer.h"
class gl_renderer : public renderer {
};

View File

@ -0,0 +1,112 @@
#include <Metal/Metal.h>
MTLPixelFormat GetMetalPixelFormat(texture_format format) {
switch (format) {
// 8-bit formats
case texture_format::R8_UNORM:
return MTLPixelFormatR8Unorm;
case texture_format::R8_SNORM:
return MTLPixelFormatR8Snorm;
case texture_format::R8_UINT:
return MTLPixelFormatR8Uint;
case texture_format::R8_SINT:
return MTLPixelFormatR8Sint;
// 16-bit formats
case texture_format::RG8_UNORM:
return MTLPixelFormatRG8Unorm;
case texture_format::RG8_SNORM:
return MTLPixelFormatRG8Snorm;
case texture_format::RG8_UINT:
return MTLPixelFormatRG8Uint;
case texture_format::RG8_SINT:
return MTLPixelFormatRG8Sint;
// 24-bit formats
case texture_format::RGB8_UNORM:
return MTLPixelFormatRGB8Unorm;
case texture_format::RGB8_SNORM:
return MTLPixelFormatRGB8Snorm;
case texture_format::RGB8_UINT:
return MTLPixelFormatRGB8Uint;
case texture_format::RGB8_SINT:
return MTLPixelFormatRGB8Sint;
// 32-bit formats
case texture_format::RGBA8_UNORM:
return MTLPixelFormatRGBA8Unorm;
case texture_format::RGBA8_SNORM:
return MTLPixelFormatRGBA8Snorm;
case texture_format::RGBA8_UINT:
return MTLPixelFormatRGBA8Uint;
case texture_format::RGBA8_SINT:
return MTLPixelFormatRGBA8Sint;
// SRGB formats
case texture_format::SRGB8:
return MTLPixelFormatBGRA8Unorm_sRGB;
case texture_format::SRGB8_ALPHA8:
return MTLPixelFormatRGBA8Unorm_sRGB;
// 16-bit float formats
case texture_format::R16_FLOAT:
return MTLPixelFormatR16Float;
case texture_format::RG16_FLOAT:
return MTLPixelFormatRG16Float;
case texture_format::RGBA16_FLOAT:
return MTLPixelFormatRGBA16Float;
// 32-bit float formats
case texture_format::R32_FLOAT:
return MTLPixelFormatR32Float;
case texture_format::RG32_FLOAT:
return MTLPixelFormatRG32Float;
case texture_format::RGBA32_FLOAT:
return MTLPixelFormatRGBA32Float;
// Integer formats
case texture_format::R16_UINT:
return MTLPixelFormatR16Uint;
case texture_format::R16_SINT:
return MTLPixelFormatR16Sint;
case texture_format::RG16_UINT:
return MTLPixelFormatRG16Uint;
case texture_format::RG16_SINT:
return MTLPixelFormatRG16Sint;
case texture_format::RGBA16_UINT:
return MTLPixelFormatRGBA16Uint;
case texture_format::RGBA16_SINT:
return MTLPixelFormatRGBA16Sint;
case texture_format::R32_UINT:
return MTLPixelFormatR32Uint;
case texture_format::R32_SINT:
return MTLPixelFormatR32Sint;
case texture_format::RG32_UINT:
return MTLPixelFormatRG32Uint;
case texture_format::RG32_SINT:
return MTLPixelFormatRG32Sint;
case texture_format::RGBA32_UINT:
return MTLPixelFormatRGBA32Uint;
case texture_format::RGBA32_SINT:
return MTLPixelFormatRGBA32Sint;
// Depth/stencil formats
case texture_format::D16_UNORM:
return MTLPixelFormatDepth16Unorm;
case texture_format::D24_UNORM_S8_UINT:
return MTLPixelFormatDepth24Unorm_Stencil8;
case texture_format::D32_FLOAT:
return MTLPixelFormatDepth32Float;
case texture_format::D32_FLOAT_S8X24_UINT:
return MTLPixelFormatDepth32Float_Stencil8;
// Compressed formats
case texture_format::BC1_UNORM:
return MTLPixelFormatBC1_RGBA;
case texture_format::BC3_UNORM:
return MTLPixelFormatBC3_RGBA;
default:
return MTLPixelFormatInvalid; // Unsupported format
}
}

View File

@ -0,0 +1,116 @@
#include <vulkan/vulkan.h>
VkFormat GetVulkanFormat(texture_format format) {
switch (format) {
// 8-bit formats
case texture_format::R8_UNORM:
return VK_FORMAT_R8_UNORM;
case texture_format::R8_SNORM:
return VK_FORMAT_R8_SNORM;
case texture_format::R8_UINT:
return VK_FORMAT_R8_UINT;
case texture_format::R8_SINT:
return VK_FORMAT_R8_SINT;
// 16-bit formats
case texture_format::RG8_UNORM:
return VK_FORMAT_R8G8_UNORM;
case texture_format::RG8_SNORM:
return VK_FORMAT_R8G8_SNORM;
case texture_format::RG8_UINT:
return VK_FORMAT_R8G8_UINT;
case texture_format::RG8_SINT:
return VK_FORMAT_R8G8_SINT;
// 24-bit formats
case texture_format::RGB8_UNORM:
return VK_FORMAT_R8G8B8_UNORM;
case texture_format::RGB8_SNORM:
return VK_FORMAT_R8G8B8_SNORM;
case texture_format::RGB8_UINT:
return VK_FORMAT_R8G8B8_UINT;
case texture_format::RGB8_SINT:
return VK_FORMAT_R8G8B8_SINT;
// 32-bit formats
case texture_format::RGBA8_UNORM:
return VK_FORMAT_R8G8B8A8_UNORM;
case texture_format::RGBA8_SNORM:
return VK_FORMAT_R8G8B8A8_SNORM;
case texture_format::RGBA8_UINT:
return VK_FORMAT_R8G8B8A8_UINT;
case texture_format::RGBA8_SINT:
return VK_FORMAT_R8G8B8A8_SINT;
// SRGB formats
case texture_format::SRGB8:
return VK_FORMAT_R8G8B8_SRGB;
case texture_format::SRGB8_ALPHA8:
return VK_FORMAT_R8G8B8A8_SRGB;
// 16-bit float formats
case texture_format::R16_FLOAT:
return VK_FORMAT_R16_SFLOAT;
case texture_format::RG16_FLOAT:
return VK_FORMAT_R16G16_SFLOAT;
case texture_format::RGB16_FLOAT:
return VK_FORMAT_R16G16B16_SFLOAT;
case texture_format::RGBA16_FLOAT:
return VK_FORMAT_R16G16B16A16_SFLOAT;
// 32-bit float formats
case texture_format::R32_FLOAT:
return VK_FORMAT_R32_SFLOAT;
case texture_format::RG32_FLOAT:
return VK_FORMAT_R32G32_SFLOAT;
case texture_format::RGB32_FLOAT:
return VK_FORMAT_R32G32B32_SFLOAT;
case texture_format::RGBA32_FLOAT:
return VK_FORMAT_R32G32B32A32_SFLOAT;
// Integer formats
case texture_format::R16_UINT:
return VK_FORMAT_R16_UINT;
case texture_format::R16_SINT:
return VK_FORMAT_R16_SINT;
case texture_format::RG16_UINT:
return VK_FORMAT_R16G16_UINT;
case texture_format::RG16_SINT:
return VK_FORMAT_R16G16_SINT;
case texture_format::RGBA16_UINT:
return VK_FORMAT_R16G16B16A16_UINT;
case texture_format::RGBA16_SINT:
return VK_FORMAT_R16G16B16A16_SINT;
case texture_format::R32_UINT:
return VK_FORMAT_R32_UINT;
case texture_format::R32_SINT:
return VK_FORMAT_R32_SINT;
case texture_format::RG32_UINT:
return VK_FORMAT_R32G32_UINT;
case texture_format::RG32_SINT:
return VK_FORMAT_R32G32_SINT;
case texture_format::RGBA32_UINT:
return VK_FORMAT_R32G32B32A32_UINT;
case texture_format::RGBA32_SINT:
return VK_FORMAT_R32G32B32A32_SINT;
// Depth/stencil formats
case texture_format::D16_UNORM:
return VK_FORMAT_D16_UNORM;
case texture_format::D24_UNORM_S8_UINT:
return VK_FORMAT_D24_UNORM_S8_UINT;
case texture_format::D32_FLOAT:
return VK_FORMAT_D32_SFLOAT;
case texture_format::D32_FLOAT_S8X24_UINT:
return VK_FORMAT_D32_SFLOAT_S8_UINT;
// Compressed formats
case texture_format::BC1_UNORM:
return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
case texture_format::BC3_UNORM:
return VK_FORMAT_BC3_UNORM_BLOCK;
default:
return VK_FORMAT_UNDEFINED; // Unsupported format
}
}

View File

@ -1 +1,27 @@
#include "pipeline.h"
#include "core/renderer/renderer.h"
bool pipeline::init() {
vertex_buffer = aorii::get_renderer_raw()->create_vertex_buffer();
index_buffer = aorii::get_renderer_raw()->create_index_buffer();
return true;
}
void pipeline::destroy() {
aorii::get_renderer_raw()->destroy_buffer(vertex_buffer);
aorii::get_renderer_raw()->destroy_buffer(index_buffer);
}
void pipeline::set_triangle(const std::span<const aorii_vertex>& in_vertexes,
const std::span<const aorii_triangle>& in_triangles) {
if (vertex_buffer->get_size() < in_vertexes.size()) { vertex_buffer->resize(static_cast<int>(in_vertexes.size())); }
const auto v_buffer = static_cast<aorii_vertex*>(vertex_buffer->lock());
std::ranges::copy(in_vertexes, v_buffer);
vertex_buffer->unlock();
if (index_buffer->get_size() < in_triangles.size()) { index_buffer->resize(static_cast<int>(in_triangles.size())); }
const auto i_buffer = static_cast<aorii_triangle*>(index_buffer->lock());
std::ranges::copy(in_triangles, i_buffer);
index_buffer->unlock();
}

View File

@ -3,6 +3,7 @@
#include <string>
#include <Eigen/Eigen>
#include "core/renderer/renderer_buffer.h"
#include "misc/color.h"
#define AORII_DEFAULT_PIXEL_SHADER_NAME "default_shader_pixel_main"
@ -11,33 +12,33 @@
struct aorii_vertex {
Eigen::Vector2f position;
Eigen::Vector2f uv;
linear_color color;
};
struct aorii_triangle {
uint32_t index[3];
};
struct aorii_constant_buffer {
Eigen::Matrix4f projection_matrix;
Eigen::Vector2f pos;
Eigen::Vector2f size;
float radius;
};
using aorii_vertex_type = aorii_vertex;
using aorii_triangle_type = aorii_triangle;
using aorii_constant_buffer_type = aorii_constant_buffer;
// struct aorii_constant_buffer {
// Eigen::Matrix4f projection_matrix;
// Eigen::Vector2f pos;
// Eigen::Vector2f size;
// float radius;
// };
class pipeline {
public:
virtual ~pipeline() = default;
virtual bool init();
virtual void destroy();
virtual void use() = 0;
virtual void draw() = 0;
virtual void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) = 0;
virtual aorii_constant_buffer_type* lock_constant_buffer() = 0;
virtual void unlock_constant_buffer() = 0;
virtual void set_triangle(const std::span<const aorii_vertex>& in_vertexes, const std::span<const aorii_triangle>& in_triangles);
protected:
renderer_buffer* vertex_buffer = nullptr;
renderer_buffer* index_buffer = nullptr;
};
class custom_pipeline : public pipeline {
@ -52,8 +53,10 @@ private:
*
*
*/
class post_process_pipeline : public pipeline {
class post_process_pipeline {
public:
virtual ~post_process_pipeline() = default;
virtual void set_compute_shader(const std::string& shader_name) = 0;
template<typename T>
T* get_constant_buffer() {

View File

@ -0,0 +1,17 @@
#include "rect_pipeline.h"
#include "core/renderer/renderer.h"
bool rect_pipeline::init() {
param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1);
return pipeline::init();
}
void rect_pipeline::destroy() {
pipeline::destroy();
aorii::get_renderer_raw()->destroy_buffer(param_buffer);
}
void rect_pipeline::set_param(const param& in_param) {
param_buffer->set_data(in_param);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "pipeline.h"
class rect_pipeline : public pipeline {
public:
struct param {
Eigen::Matrix4f projection_matrix;
};
bool init() override;
void destroy() override;
virtual void set_param(const param& in_param);
protected:
renderer_buffer* param_buffer = nullptr;
};

View File

@ -0,0 +1,17 @@
#include "rounded_rect_pipeline.h"
#include "core/renderer/renderer.h"
bool rounded_rect_pipeline::init() {
param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1);
return pipeline::init();
}
void rounded_rect_pipeline::destroy() {
pipeline::destroy();
aorii::get_renderer_raw()->destroy_buffer(param_buffer);
}
void rounded_rect_pipeline::set_param(const param& in_param) {
param_buffer->set_data(in_param);
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "pipeline.h"
class rounded_rect_pipeline : public pipeline {
public:
struct param {
Eigen::Matrix4f projection_matrix;
Eigen::Vector2f pos;
Eigen::Vector2f size;
float radius;
};
bool init() override;
void destroy() override;
void set_param(const param& in_param);
protected:
renderer_buffer* param_buffer = nullptr;
};

View File

@ -8,8 +8,10 @@
#include "backend/dx/dx_renderer.h"
#endif
using time_type = decltype(std::chrono::high_resolution_clock::now());
std::chrono::duration<double> delta_time = {};
decltype(std::chrono::high_resolution_clock::now()) last_time = {};
time_type begin_time = {};
time_type last_time = {};
renderer* s_renderer = nullptr;
void renderer::tick() {
@ -24,6 +26,7 @@ renderer* aorii::get_renderer_raw() {
}
bool aorii::create_renderer(renderer_api api) {
begin_time = std::chrono::high_resolution_clock::now();
if (s_renderer) return true;
switch (api) {
#if DX_BACKEND
@ -72,3 +75,7 @@ void aorii::update() {
const std::chrono::duration<double>& aorii::get_delta_time() {
return delta_time;
}
std::chrono::duration<double> aorii::get_total_time() {
return std::chrono::high_resolution_clock::now() - begin_time;
}

View File

@ -3,6 +3,11 @@
#include <Eigen/Eigen>
#include <filesystem>
#include "renderer_buffer.h"
#include "core/pipeline/pipeline.h"
class rounded_rect_pipeline;
class rect_pipeline;
class renderer_window;
class renderer_texture;
@ -13,6 +18,86 @@ enum class renderer_api {
metal,
};
enum class texture_format {
// 未压缩的颜色格式
// 单通道 8 位
R8_UNORM,
R8_SNORM,
R8_UINT,
R8_SINT,
// 双通道 8 位
RG8_UNORM,
RG8_SNORM,
RG8_UINT,
RG8_SINT,
// 三通道 8 位
RGB8_UNORM,
RGB8_SNORM,
RGB8_UINT,
RGB8_SINT,
// 四通道 8 位
RGBA8_UNORM,
RGBA8_SNORM,
RGBA8_UINT,
RGBA8_SINT,
// SRGB 格式
SRGB8,
SRGB8_ALPHA8,
// 16 位浮点格式
R16_FLOAT,
RG16_FLOAT,
RGB16_FLOAT,
RGBA16_FLOAT,
// 32 位浮点格式
R32_FLOAT,
RG32_FLOAT,
RGB32_FLOAT,
RGBA32_FLOAT,
// 整数格式
R16_UINT,
R16_SINT,
RG16_UINT,
RG16_SINT,
RGBA16_UINT,
RGBA16_SINT,
R32_UINT,
R32_SINT,
RG32_UINT,
RG32_SINT,
RGBA32_UINT,
RGBA32_SINT,
// 深度/模板格式
D16_UNORM,
D24_UNORM_S8_UINT,
D32_FLOAT,
D32_FLOAT_S8X24_UINT,
// 压缩格式(以 DXGI 格式为例)
BC1_UNORM, // DXT1
BC1_UNORM_SRGB,
BC2_UNORM, // DXT3
BC2_UNORM_SRGB,
BC3_UNORM, // DXT5
BC3_UNORM_SRGB,
BC4_UNORM,
BC4_SNORM,
BC5_UNORM,
BC5_SNORM,
BC6H_UF16,
BC6H_SF16,
BC7_UNORM,
BC7_UNORM_SRGB,
};
class renderer {
friend class window_manager;
public:
@ -23,9 +108,27 @@ public:
virtual void tick();
virtual bool render() = 0;
virtual renderer_texture* create_texture(const Eigen::Vector2i& size) = 0;
virtual renderer_texture* create_texture(const Eigen::Vector2i& size, texture_format in_format) = 0;
virtual void destroy_texture(renderer_texture* texture) = 0;
/**
*
* @param shader_name , , 使aorii::get_shader_path获取路径, API下会自动添加后缀
* @return
*/
virtual std::vector<char> load_shader(const std::string& shader_name) = 0;
renderer_buffer* create_vertex_buffer(const int in_size = 4) {
return create_buffer(buffer_type::vertex, sizeof(aorii_vertex), in_size);
}
renderer_buffer* create_index_buffer(const int in_size = 2) {
return create_buffer(buffer_type::index, sizeof(aorii_triangle), in_size);
}
virtual renderer_buffer* create_buffer(buffer_type in_buffer_type, int in_element_byte, int in_element_count) = 0;
virtual void destroy_buffer(renderer_buffer* buffer) { delete buffer; }
virtual rect_pipeline* get_rect_pipeline() = 0;
virtual rounded_rect_pipeline* get_rounded_rect_pipeline() = 0;
private:
virtual renderer_window* create_window() = 0;
virtual void destroy_window(renderer_window* window);
@ -44,6 +147,7 @@ namespace aorii {
void update();
const std::chrono::duration<double>& get_delta_time();
std::chrono::duration<double> get_total_time();
inline std::filesystem::path s_shader_relative_path = "resource/shaders";
inline void set_shader_relative_path(const std::filesystem::path& path) { s_shader_relative_path = path; }

View File

@ -1,5 +1,6 @@
#pragma once
#include <span>
#include <spdlog/spdlog.h>
enum class buffer_type {
vertex,
@ -7,15 +8,54 @@ enum class buffer_type {
constant,
};
template<typename DataType>
class renderer_buffer {
public:
explicit renderer_buffer(buffer_type in_type, const int count = 1) : size(count), type(in_type) {}
explicit renderer_buffer(buffer_type in_type, const int in_element_byte, const int in_size = 1) : size(in_size),
element_byte(in_element_byte), type(in_type) {
}
virtual ~renderer_buffer() = default;
virtual DataType* lock() = 0;
virtual void* lock() = 0;
virtual void unlock() = 0;
template<class T>
bool set_data(const T& in_data) {
#if DEBUG
if (sizeof(T) != element_byte) {
spdlog::error("数据大小不匹配");
return false;
}
#endif
if (auto data = lock()) {
memcpy(data, &in_data, sizeof(T));
unlock();
return true;
}
#if DEBUG
spdlog::error("Failed to set param buffer data");
#endif
return false;
}
template<class T>
bool set_data(const std::span<const T>& in_data) {
#if DEBUG
if (sizeof(T) != element_byte) {
spdlog::error("数据大小不匹配");
return false;
}
#endif
if (auto data = lock()) {
memcpy(data, in_data.data(), sizeof(T) * in_data.size());
unlock();
return true;
}
#if DEBUG
spdlog::error("Failed to set param buffer data");
#endif
return false;
}
void resize(const int new_size) {
if (new_size == size)
return;
@ -35,5 +75,6 @@ public:
protected:
virtual void on_resize(int new_size) = 0;
int size;
const int element_byte;
const buffer_type type;
};

View File

@ -1,11 +1,18 @@
#include "renderer_context.h"
#include "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) {
switch_pipeline(default_pipeline);
const aorii_vertex_type v1{ { in_pos.x(), in_pos.y() }, in_color }; // 左上角
const aorii_vertex_type v2{ { in_pos.x() + in_size.x(), in_pos.y() }, in_color }; // 右上角
const aorii_vertex_type v3{ { in_pos.x(), in_pos.y() + in_size.y() }, in_color }; // 左下角
const aorii_vertex_type v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, 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);
@ -16,28 +23,19 @@ void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen
const uint32_t index4 = vertices.size();
vertices.push_back(v4);
const aorii_triangle_type t1 = { index1, index2, index3 };
const aorii_triangle_type t2 = { index2, index3, index4 };
const aorii_triangle t1 = { index1, index2, index3 };
const aorii_triangle t2 = { index2, index3, index4 };
triangles.push_back(t1);
triangles.push_back(t2);
}
void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) {
pipeline_context.pos = in_pos.cast<float>();
pipeline_context.size = in_size.cast<float>();
pipeline_context.radius = in_radius;
to_rounded_rect_pipeline(in_pos, in_size, in_radius);
switch_pipeline(rounded_rectangular_pipeline);
const auto constant_buffer = rounded_rectangular_pipeline->lock_constant_buffer();
memcpy(constant_buffer, &pipeline_context, sizeof(aorii_constant_buffer_type));
rounded_rectangular_pipeline->unlock_constant_buffer();
const aorii_vertex_type v1{ { in_pos.x(), in_pos.y() }, in_color }; // 左上角
const aorii_vertex_type v2{ { in_pos.x() + in_size.x(), in_pos.y() }, in_color }; // 右上角
const aorii_vertex_type v3{ { in_pos.x(), in_pos.y() + in_size.y() }, in_color }; // 左下角
const aorii_vertex_type v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, 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);
@ -48,8 +46,8 @@ void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, con
const uint32_t index4 = vertices.size();
vertices.push_back(v4);
const aorii_triangle_type t1 = { index1, index2, index3 };
const aorii_triangle_type t2 = { index2, index3, index4 };
const aorii_triangle t1 = { index1, index2, index3 };
const aorii_triangle t2 = { index2, index3, index4 };
triangles.push_back(t1);
triangles.push_back(t2);
@ -58,15 +56,15 @@ void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, con
}
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(default_pipeline);
switch_pipeline(rect_p);
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;
const aorii_vertex_type v1{ { in_pos_p1.x() + offset.x(), in_pos_p1.y() + offset.y() }, in_color };
const aorii_vertex_type v2{ { in_pos_p1.x() - offset.x(), in_pos_p1.y() - offset.y() }, in_color };
const aorii_vertex_type v3{ { in_pos_p2.x() + offset.x(), in_pos_p2.y() + offset.y() }, in_color };
const aorii_vertex_type v4{ { in_pos_p2.x() - offset.x(), in_pos_p2.y() - offset.y() }, in_color };
const aorii_vertex v1{ { in_pos_p1.x() + offset.x(), in_pos_p1.y() + offset.y() }, { 0, 0 }, in_color };
const aorii_vertex v2{ { in_pos_p1.x() - offset.x(), in_pos_p1.y() - offset.y() }, { 1, 0 }, in_color };
const aorii_vertex v3{ { in_pos_p2.x() + offset.x(), in_pos_p2.y() + offset.y() }, { 0, 1 }, in_color };
const aorii_vertex v4{ { in_pos_p2.x() - offset.x(), in_pos_p2.y() - offset.y() }, { 1, 1 }, in_color };
const uint32_t index1 = vertices.size();
vertices.push_back(v1);
@ -77,8 +75,8 @@ void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::
const uint32_t index4 = vertices.size();
vertices.push_back(v4);
const aorii_triangle_type t1 = { index1, index2, index3 };
const aorii_triangle_type t2 = { index2, index3, index4 };
const aorii_triangle t1 = { index1, index2, index3 };
const aorii_triangle t2 = { index2, index3, index4 };
triangles.push_back(t1);
triangles.push_back(t2);
}

View File

@ -2,9 +2,12 @@
#include <spdlog/spdlog.h>
#include "core/pipeline/pipeline.h"
#include "core/pipeline/rect_pipeline.h"
#include "core/pipeline/rounded_rect_pipeline.h"
class renderer_context {
public:
void init();
/**
*
* @param in_pos
@ -31,22 +34,15 @@ public:
*/
void draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness);
void set_default_pipeline(pipeline* in_pipeline) {
default_pipeline = in_pipeline;
}
void set_rounded_rectangular_pipeline(pipeline* in_pipeline) {
rounded_rectangular_pipeline = in_pipeline;
}
void clear() {
vertices.clear();
triangles.clear();
}
[[nodiscard]] const std::vector<aorii_vertex_type>& get_vertices() const {
[[nodiscard]] const std::vector<aorii_vertex>& get_vertices() const {
return vertices;
}
[[nodiscard]] const std::vector<aorii_triangle_type>& get_triangles() const {
[[nodiscard]] const std::vector<aorii_triangle>& get_triangles() const {
return triangles;
}
void flush() {
@ -58,39 +54,45 @@ public:
clear();
}
void set_projection_matrix(const Eigen::Matrix4f& in_matrix) {
pipeline_context.projection_matrix = in_matrix;
projection_matrix = in_matrix;
// 更新默认管线的投影矩阵
if (default_pipeline) {
auto constant_buffer = default_pipeline->lock_constant_buffer();
memcpy(constant_buffer, &pipeline_context, sizeof(aorii_constant_buffer_type));
default_pipeline->unlock_constant_buffer();
}
rect_p->set_param({ in_matrix });
// 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
}
[[nodiscard]] const auto& get_pipeline_context() const {
return pipeline_context;
}
protected:
void switch_pipeline(pipeline* in_pipeline) {
#if DEBUG
if (!in_pipeline)
spdlog::critical("尝试切换到空管线");
#endif
if (current_pipeline != in_pipeline) {
if (current_pipeline != in_pipeline && in_pipeline) {
flush();
current_pipeline = in_pipeline;
current_pipeline->use();
}
}
private:
std::vector<aorii_vertex_type> vertices;
std::vector<aorii_triangle_type> triangles;
aorii_constant_buffer_type pipeline_context = {};
pipeline* default_pipeline = nullptr;
pipeline* rounded_rectangular_pipeline = nullptr;
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);
}
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;
};

View File

@ -0,0 +1,28 @@
struct ParamBuffer
{
matrix transform;
};
ParameterBlock<ParamBuffer> param_buffer : register(b0);
struct VSInput {
float2 position : POSITION; // 窗口坐标
float4 color : COLOR; // 颜色
};
struct PSInput {
float4 position : SV_POSITION; // 裁剪空间坐标
float4 color : COLOR; // 颜色
};
PSInput vertex_main(VSInput input)
{
PSInput output;
output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform);
output.color = input.color;
return output;
}
float4 pixel_main(PSInput input) : SV_TARGET
{
return input.color;
}

View File

@ -6,15 +6,16 @@ struct ParamBuffer
float radius; // 圆角像素单位
};
ParameterBlock<ParamBuffer> param_buffer : register(b0);
SamplerState texture_sampler : register(s0);
struct VSInput {
float2 position : POSITION; // 窗口坐标
float2 uv : TEXCOORD0; // 纹理坐标
float4 color : COLOR; // 颜色
};
struct PSInput {
float4 position : SV_POSITION; // 裁剪空间坐标
float2 uv : TEXCOORD0; // 纹理坐标
float4 color : COLOR; // 颜色
};
@ -26,21 +27,18 @@ PSInput vertex_main(VSInput input)
return output;
}
#ifdef IS_ROUNDED_RECT
// 圆角矩形像素着色器
float4 rounded_rect_pixel_main(PSInput input) : SV_TARGET
float4 pixel_main(PSInput input) : SV_TARGET
{
float2 pixel_pos = input.position.xy;
// 圆角半径
float radius = param_buffer.radius;
// 计算矩形的中心位置
float2 rect_center = param_buffer.pos + param_buffer.size * 0.5;
// 计算半尺寸,减去圆角半径
float2 half_size = param_buffer.size * 0.5 - radius;
// 当前像素在视口内位置
float2 pixel_pos = input.position.xy;
// 将坐标系平移到矩形中心
float2 pos = pixel_pos - rect_center;
@ -53,9 +51,3 @@ float4 rounded_rect_pixel_main(PSInput input) : SV_TARGET
// inside <= 0.0 说明在圆角矩形内
return input.color * step(inside, 0.0);
}
#else
float4 pixel_main(PSInput input) : SV_TARGET
{
return input.color;
}
#endif