代码整理
This commit is contained in:
parent
879732da6e
commit
1a10d65de1
@ -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")
|
||||
|
@ -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})
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>() };
|
||||
}
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
||||
|
61
src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp
Normal file
61
src/renderer/backend/dx/pipeline/dx_rect_pipeline.cpp
Normal 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);
|
||||
}
|
15
src/renderer/backend/dx/pipeline/dx_rect_pipeline.h
Normal file
15
src/renderer/backend/dx/pipeline/dx_rect_pipeline.h
Normal 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;
|
||||
};
|
@ -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);
|
||||
}
|
15
src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h
Normal file
15
src/renderer/backend/dx/pipeline/dx_rounded_rect_pipeline.h
Normal 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;
|
||||
};
|
119
src/renderer/backend/gl/gl_renderer.cpp
Normal file
119
src/renderer/backend/gl/gl_renderer.cpp
Normal 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
|
||||
}
|
||||
}
|
6
src/renderer/backend/gl/gl_renderer.h
Normal file
6
src/renderer/backend/gl/gl_renderer.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "core/renderer/renderer.h"
|
||||
|
||||
class gl_renderer : public renderer {
|
||||
|
||||
};
|
112
src/renderer/backend/metal/texture_format.cpp
Normal file
112
src/renderer/backend/metal/texture_format.cpp
Normal 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
|
||||
}
|
||||
}
|
116
src/renderer/backend/vk/texture_forma.cpp
Normal file
116
src/renderer/backend/vk/texture_forma.cpp
Normal 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
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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() {
|
||||
|
17
src/renderer/core/pipeline/rect_pipeline.cpp
Normal file
17
src/renderer/core/pipeline/rect_pipeline.cpp
Normal 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);
|
||||
}
|
15
src/renderer/core/pipeline/rect_pipeline.h
Normal file
15
src/renderer/core/pipeline/rect_pipeline.h
Normal 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;
|
||||
};
|
17
src/renderer/core/pipeline/rounded_rect_pipeline.cpp
Normal file
17
src/renderer/core/pipeline/rounded_rect_pipeline.cpp
Normal 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);
|
||||
}
|
19
src/renderer/core/pipeline/rounded_rect_pipeline.h
Normal file
19
src/renderer/core/pipeline/rounded_rect_pipeline.h
Normal 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;
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
28
src/renderer/shader/aorii_rect.slang
Normal file
28
src/renderer/shader/aorii_rect.slang
Normal 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;
|
||||
}
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user