新增图片绘制
This commit is contained in:
parent
4de6e2d965
commit
9dfc4f2fed
@ -63,6 +63,8 @@ compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "ver
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rect.slang" "pixel" "pixel_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "vertex" "vertex_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_rounded_rect.slang" "pixel" "pixel_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "vertex" "vertex_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/aorii_texture.slang" "pixel" "pixel_main")
|
||||
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
|
||||
|
||||
# 如果需要编译example, 添加自定义命令用于拷贝shader文件
|
||||
|
@ -9,145 +9,6 @@
|
||||
#include "core/window/window_manager.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
DXGI_FORMAT get_dxgi_format(texture_format format) {
|
||||
switch (format) {
|
||||
// 8-bit formats
|
||||
case texture_format::R8_UNORM:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case texture_format::R8_SNORM:
|
||||
return DXGI_FORMAT_R8_SNORM;
|
||||
case texture_format::R8_UINT:
|
||||
return DXGI_FORMAT_R8_UINT;
|
||||
case texture_format::R8_SINT:
|
||||
return DXGI_FORMAT_R8_SINT;
|
||||
|
||||
// 16-bit formats
|
||||
case texture_format::RG8_UNORM:
|
||||
return DXGI_FORMAT_R8G8_UNORM;
|
||||
case texture_format::RG8_SNORM:
|
||||
return DXGI_FORMAT_R8G8_SNORM;
|
||||
case texture_format::RG8_UINT:
|
||||
return DXGI_FORMAT_R8G8_UINT;
|
||||
case texture_format::RG8_SINT:
|
||||
return DXGI_FORMAT_R8G8_SINT;
|
||||
|
||||
// 24-bit formats
|
||||
case texture_format::RGB8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM; // Note: DXGI doesn't have a direct RGB8 format
|
||||
case texture_format::RGB8_SNORM:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
case texture_format::RGB8_UINT:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
case texture_format::RGB8_SINT:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
|
||||
// 32-bit formats
|
||||
case texture_format::RGBA8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case texture_format::RGBA8_SNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_SNORM;
|
||||
case texture_format::RGBA8_UINT:
|
||||
return DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
case texture_format::RGBA8_SINT:
|
||||
return DXGI_FORMAT_R8G8B8A8_SINT;
|
||||
|
||||
// SRGB formats
|
||||
case texture_format::SRGB8:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; // Note: Approximation
|
||||
case texture_format::SRGB8_ALPHA8:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
|
||||
// 16-bit float formats
|
||||
case texture_format::R16_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case texture_format::RG16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16_FLOAT;
|
||||
case texture_format::RGB16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT; // Note: No direct RGB16 format
|
||||
case texture_format::RGBA16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
|
||||
// 32-bit float formats
|
||||
case texture_format::R32_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case texture_format::RG32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32_FLOAT;
|
||||
case texture_format::RGB32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
case texture_format::RGBA32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
// Integer formats
|
||||
case texture_format::R16_UINT:
|
||||
return DXGI_FORMAT_R16_UINT;
|
||||
case texture_format::R16_SINT:
|
||||
return DXGI_FORMAT_R16_SINT;
|
||||
case texture_format::RG16_UINT:
|
||||
return DXGI_FORMAT_R16G16_UINT;
|
||||
case texture_format::RG16_SINT:
|
||||
return DXGI_FORMAT_R16G16_SINT;
|
||||
case texture_format::RGBA16_UINT:
|
||||
return DXGI_FORMAT_R16G16B16A16_UINT;
|
||||
case texture_format::RGBA16_SINT:
|
||||
return DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
case texture_format::R32_UINT:
|
||||
return DXGI_FORMAT_R32_UINT;
|
||||
case texture_format::R32_SINT:
|
||||
return DXGI_FORMAT_R32_SINT;
|
||||
case texture_format::RG32_UINT:
|
||||
return DXGI_FORMAT_R32G32_UINT;
|
||||
case texture_format::RG32_SINT:
|
||||
return DXGI_FORMAT_R32G32_SINT;
|
||||
case texture_format::RGBA32_UINT:
|
||||
return DXGI_FORMAT_R32G32B32A32_UINT;
|
||||
case texture_format::RGBA32_SINT:
|
||||
return DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
|
||||
// Depth/stencil formats
|
||||
case texture_format::D16_UNORM:
|
||||
return DXGI_FORMAT_D16_UNORM;
|
||||
case texture_format::D24_UNORM_S8_UINT:
|
||||
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
case texture_format::D32_FLOAT:
|
||||
return DXGI_FORMAT_D32_FLOAT;
|
||||
case texture_format::D32_FLOAT_S8X24_UINT:
|
||||
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
|
||||
// Compressed formats
|
||||
case texture_format::BC1_UNORM:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case texture_format::BC1_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC1_UNORM_SRGB;
|
||||
case texture_format::BC2_UNORM:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case texture_format::BC2_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC2_UNORM_SRGB;
|
||||
case texture_format::BC3_UNORM:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case texture_format::BC3_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC3_UNORM_SRGB;
|
||||
case texture_format::BC4_UNORM:
|
||||
return DXGI_FORMAT_BC4_UNORM;
|
||||
case texture_format::BC4_SNORM:
|
||||
return DXGI_FORMAT_BC4_SNORM;
|
||||
case texture_format::BC5_UNORM:
|
||||
return DXGI_FORMAT_BC5_UNORM;
|
||||
case texture_format::BC5_SNORM:
|
||||
return DXGI_FORMAT_BC5_SNORM;
|
||||
case texture_format::BC6H_UF16:
|
||||
return DXGI_FORMAT_BC6H_UF16;
|
||||
case texture_format::BC6H_SF16:
|
||||
return DXGI_FORMAT_BC6H_SF16;
|
||||
case texture_format::BC7_UNORM:
|
||||
return DXGI_FORMAT_BC7_UNORM;
|
||||
case texture_format::BC7_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC7_UNORM_SRGB;
|
||||
|
||||
default:
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
bool dx_renderer::init() {
|
||||
if (!glfwInit()) return false;
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
@ -172,6 +33,7 @@ bool dx_renderer::init() {
|
||||
|
||||
rect_p.init();
|
||||
rounded_rect_p.init();
|
||||
texture_p.init();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -180,6 +42,7 @@ void dx_renderer::destroy() {
|
||||
if (blend_state) blend_state->Release();
|
||||
rect_p.destroy();
|
||||
rounded_rect_p.destroy();
|
||||
texture_p.destroy();
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
@ -192,30 +55,8 @@ bool dx_renderer::render() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void dx_renderer::destroy_texture(renderer_texture* texture) {
|
||||
#ifdef DEBUG
|
||||
spdlog::info("Destroying texture");
|
||||
#endif
|
||||
}
|
||||
|
||||
renderer_texture* dx_renderer::create_texture(const Eigen::Vector2i& size, texture_format in_format) {
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = size.x();
|
||||
desc.Height = size.y();
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = get_dxgi_format(in_format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
ID3D11Texture2D* texture = nullptr;
|
||||
if (FAILED(device->CreateTexture2D(&desc, nullptr, &texture))) { return nullptr; }
|
||||
|
||||
return new dx_texture(texture);
|
||||
return new dx_texture(size, in_format);
|
||||
}
|
||||
|
||||
std::vector<char> dx_renderer::load_shader(const std::string& shader_name) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "core/renderer/renderer.h"
|
||||
#include "pipeline/dx_rect_pipeline.h"
|
||||
#include "pipeline/dx_rounded_rect_pipeline.h"
|
||||
#include "pipeline/dx_texture_pipeline.h"
|
||||
|
||||
class dx_window;
|
||||
|
||||
@ -14,13 +15,13 @@ public:
|
||||
bool render() override;
|
||||
|
||||
renderer_texture* create_texture(const Eigen::Vector2i& size, texture_format in_format) override;
|
||||
void destroy_texture(renderer_texture* texture) override;
|
||||
|
||||
[[nodiscard]] ID3D11Device* get_d3d_device() const { return device; }
|
||||
[[nodiscard]] ID3D11DeviceContext* get_d3d_context() const { return context; }
|
||||
|
||||
rect_pipeline* get_rect_pipeline() override { return &rect_p; }
|
||||
rounded_rect_pipeline* get_rounded_rect_pipeline() override { return &rounded_rect_p; }
|
||||
texture_pipeline* get_texture_pipeline() override { return &texture_p; }
|
||||
[[nodiscard]] ID3D11BlendState* get_blend_state() const { return blend_state; }
|
||||
|
||||
std::vector<char> load_shader(const std::string& shader_name) override;
|
||||
@ -37,5 +38,144 @@ private:
|
||||
|
||||
dx_rect_pipeline rect_p;
|
||||
dx_rounded_rect_pipeline rounded_rect_p;
|
||||
dx_texture_pipeline texture_p;
|
||||
};
|
||||
|
||||
inline DXGI_FORMAT get_dxgi_format(texture_format format) {
|
||||
switch (format) {
|
||||
// 8-bit formats
|
||||
case texture_format::R8_UNORM:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case texture_format::R8_SNORM:
|
||||
return DXGI_FORMAT_R8_SNORM;
|
||||
case texture_format::R8_UINT:
|
||||
return DXGI_FORMAT_R8_UINT;
|
||||
case texture_format::R8_SINT:
|
||||
return DXGI_FORMAT_R8_SINT;
|
||||
|
||||
// 16-bit formats
|
||||
case texture_format::RG8_UNORM:
|
||||
return DXGI_FORMAT_R8G8_UNORM;
|
||||
case texture_format::RG8_SNORM:
|
||||
return DXGI_FORMAT_R8G8_SNORM;
|
||||
case texture_format::RG8_UINT:
|
||||
return DXGI_FORMAT_R8G8_UINT;
|
||||
case texture_format::RG8_SINT:
|
||||
return DXGI_FORMAT_R8G8_SINT;
|
||||
|
||||
// 24-bit formats
|
||||
case texture_format::RGB8_UNORM:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM; // Note: DXGI doesn't have a direct RGB8 format
|
||||
case texture_format::RGB8_SNORM:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
case texture_format::RGB8_UINT:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
case texture_format::RGB8_SINT:
|
||||
return DXGI_FORMAT_UNKNOWN; // No direct equivalent
|
||||
|
||||
// 32-bit formats
|
||||
case texture_format::RGBA8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case texture_format::RGBA8_SNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_SNORM;
|
||||
case texture_format::RGBA8_UINT:
|
||||
return DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
case texture_format::RGBA8_SINT:
|
||||
return DXGI_FORMAT_R8G8B8A8_SINT;
|
||||
|
||||
// SRGB formats
|
||||
case texture_format::SRGB8:
|
||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB; // Note: Approximation
|
||||
case texture_format::SRGB8_ALPHA8:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
|
||||
// 16-bit float formats
|
||||
case texture_format::R16_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case texture_format::RG16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16_FLOAT;
|
||||
case texture_format::RGB16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT; // Note: No direct RGB16 format
|
||||
case texture_format::RGBA16_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
|
||||
// 32-bit float formats
|
||||
case texture_format::R32_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case texture_format::RG32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32_FLOAT;
|
||||
case texture_format::RGB32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
case texture_format::RGBA32_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
|
||||
// Integer formats
|
||||
case texture_format::R16_UINT:
|
||||
return DXGI_FORMAT_R16_UINT;
|
||||
case texture_format::R16_SINT:
|
||||
return DXGI_FORMAT_R16_SINT;
|
||||
case texture_format::RG16_UINT:
|
||||
return DXGI_FORMAT_R16G16_UINT;
|
||||
case texture_format::RG16_SINT:
|
||||
return DXGI_FORMAT_R16G16_SINT;
|
||||
case texture_format::RGBA16_UINT:
|
||||
return DXGI_FORMAT_R16G16B16A16_UINT;
|
||||
case texture_format::RGBA16_SINT:
|
||||
return DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
case texture_format::R32_UINT:
|
||||
return DXGI_FORMAT_R32_UINT;
|
||||
case texture_format::R32_SINT:
|
||||
return DXGI_FORMAT_R32_SINT;
|
||||
case texture_format::RG32_UINT:
|
||||
return DXGI_FORMAT_R32G32_UINT;
|
||||
case texture_format::RG32_SINT:
|
||||
return DXGI_FORMAT_R32G32_SINT;
|
||||
case texture_format::RGBA32_UINT:
|
||||
return DXGI_FORMAT_R32G32B32A32_UINT;
|
||||
case texture_format::RGBA32_SINT:
|
||||
return DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
|
||||
// Depth/stencil formats
|
||||
case texture_format::D16_UNORM:
|
||||
return DXGI_FORMAT_D16_UNORM;
|
||||
case texture_format::D24_UNORM_S8_UINT:
|
||||
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
case texture_format::D32_FLOAT:
|
||||
return DXGI_FORMAT_D32_FLOAT;
|
||||
case texture_format::D32_FLOAT_S8X24_UINT:
|
||||
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
|
||||
// Compressed formats
|
||||
case texture_format::BC1_UNORM:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case texture_format::BC1_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC1_UNORM_SRGB;
|
||||
case texture_format::BC2_UNORM:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case texture_format::BC2_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC2_UNORM_SRGB;
|
||||
case texture_format::BC3_UNORM:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case texture_format::BC3_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC3_UNORM_SRGB;
|
||||
case texture_format::BC4_UNORM:
|
||||
return DXGI_FORMAT_BC4_UNORM;
|
||||
case texture_format::BC4_SNORM:
|
||||
return DXGI_FORMAT_BC4_SNORM;
|
||||
case texture_format::BC5_UNORM:
|
||||
return DXGI_FORMAT_BC5_UNORM;
|
||||
case texture_format::BC5_SNORM:
|
||||
return DXGI_FORMAT_BC5_SNORM;
|
||||
case texture_format::BC6H_UF16:
|
||||
return DXGI_FORMAT_BC6H_UF16;
|
||||
case texture_format::BC6H_SF16:
|
||||
return DXGI_FORMAT_BC6H_SF16;
|
||||
case texture_format::BC7_UNORM:
|
||||
return DXGI_FORMAT_BC7_UNORM;
|
||||
case texture_format::BC7_UNORM_SRGB:
|
||||
return DXGI_FORMAT_BC7_UNORM_SRGB;
|
||||
|
||||
default:
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -2,33 +2,56 @@
|
||||
|
||||
#include "dx_renderer.h"
|
||||
|
||||
dx_texture::dx_texture(ID3D11Texture2D* texture) { m_texture = texture; }
|
||||
dx_texture::dx_texture(const Eigen::Vector2i& size, texture_format format) : renderer_texture(format) {
|
||||
auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = size.x();
|
||||
desc.Height = size.y();
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = get_dxgi_format(format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
auto hr = d3d_device->CreateTexture2D(&desc, nullptr, &m_texture);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("无法创建纹理, 错误: {0}", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
dx_texture::~dx_texture() {
|
||||
// 如果是Debug模式, 检查m_data是否被释放
|
||||
#if defined(DEBUG)
|
||||
assert(!m_data);
|
||||
#endif
|
||||
free(m_data);
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {};
|
||||
srv_desc.Format = desc.Format;
|
||||
srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
||||
srv_desc.Texture2D.MipLevels = 1;
|
||||
hr = d3d_device->CreateShaderResourceView(m_texture, &srv_desc, &srv);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("无法创建着色器资源视图, 错误: {0}", hr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void* dx_texture::lock() {
|
||||
dx_texture::~dx_texture() {
|
||||
if (srv) srv->Release();
|
||||
if (m_texture) m_texture->Release();
|
||||
}
|
||||
|
||||
void* dx_texture::lock(unsigned int* out_row_pitch) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
m_texture->GetDesc(&desc);
|
||||
m_data = new char[desc.Width * desc.Height * 4];
|
||||
return m_data;
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
auto context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
context->Map(m_texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
if (out_row_pitch) *out_row_pitch = mappedResource.RowPitch;
|
||||
return mappedResource.pData;
|
||||
}
|
||||
|
||||
void dx_texture::unlock() {
|
||||
// D3D11_TEXTURE2D_DESC desc;
|
||||
// m_texture->GetDesc(&desc);
|
||||
// D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
// auto context = dx_backend::get_instance();
|
||||
// context->Map(m_texture.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
// memcpy(mappedResource.pData, m_data, desc.Width * desc.Height * 4);
|
||||
// context->Unmap(m_texture.get(), 0);
|
||||
// delete[] m_data;
|
||||
// m_data = nullptr;
|
||||
auto context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
context->Unmap(m_texture, 0);
|
||||
}
|
||||
|
||||
bool dx_texture::resize(const Eigen::Vector2i& size) { return true; }
|
||||
|
@ -7,14 +7,18 @@
|
||||
// DX11纹理
|
||||
class dx_texture : public renderer_texture {
|
||||
public:
|
||||
explicit dx_texture(ID3D11Texture2D* texture);
|
||||
dx_texture(const Eigen::Vector2i& size, texture_format format);
|
||||
~dx_texture() override;
|
||||
void* lock() override;
|
||||
void* lock(unsigned int* out_row_pitch) override;
|
||||
void unlock() override;
|
||||
|
||||
bool resize(const Eigen::Vector2i& size) override;
|
||||
Eigen::Vector2i size() override;
|
||||
|
||||
[[nodiscard]] ID3D11ShaderResourceView* get_srv() const { return srv; }
|
||||
void* get_native_handle() override { return m_texture; }
|
||||
void* get_shader_resource_view() override { return srv; }
|
||||
private:
|
||||
void* m_data = nullptr;
|
||||
ID3D11Texture2D* m_texture;
|
||||
ID3D11Texture2D* m_texture{};
|
||||
ID3D11ShaderResourceView* srv{};
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "dx_renderer.h"
|
||||
#include "core/renderer/renderer_texture.h"
|
||||
#include "misc/scope_exit.h"
|
||||
|
||||
using namespace aorii;
|
||||
@ -67,10 +68,10 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
test_texture = dx->load_image(R"(D:\69054578_p0.jpg)", texture_format::RGBA8_UNORM);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void dx_window::begin_frame() {
|
||||
glfwMakeContextCurrent(get_glfw_window());
|
||||
const auto render = aorii::get_renderer<dx_renderer>();
|
||||
@ -79,54 +80,17 @@ void dx_window::begin_frame() {
|
||||
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
|
||||
d3d_context->OMSetBlendState(render->get_blend_state(), nullptr, 0xffffffff);
|
||||
d3d_context->ClearRenderTargetView(render_target_view, clear_color);
|
||||
|
||||
if constexpr (false) {
|
||||
static std::chrono::duration<double> timer = {};
|
||||
static linear_color random_color = { 0, 0, 0, 1 };
|
||||
static bool is_white = false;
|
||||
static float pos_x = 0;
|
||||
static float pos_y = 0;
|
||||
static bool draw_test = true;
|
||||
|
||||
if (draw_test) {
|
||||
// 生成渐变色
|
||||
if (is_white) {
|
||||
if (random_color.r > 0) {
|
||||
random_color.r -= 0.01f;
|
||||
} else if (random_color.b > 0) {
|
||||
random_color.b -= 0.01f;
|
||||
} else if (random_color.g > 0) {
|
||||
random_color.g -= 0.01f;
|
||||
} else {
|
||||
is_white = false;
|
||||
random_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (random_color.r < 1) {
|
||||
random_color.r += 0.01f;
|
||||
} else if (random_color.b < 1) {
|
||||
random_color.b += 0.01f;
|
||||
} else if (random_color.g < 1) {
|
||||
random_color.g += 0.01f;
|
||||
} else {
|
||||
is_white = true;
|
||||
random_color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
}
|
||||
|
||||
context.draw_rectangle({ pos_x, pos_y }, { 1, 100 }, random_color);
|
||||
if (pos_x >= 1000) {
|
||||
pos_x = 0;
|
||||
draw_test = false;
|
||||
}
|
||||
pos_x += 1;
|
||||
}
|
||||
}
|
||||
context.set_projection_matrix(projection_matrix);
|
||||
|
||||
context.draw_rectangle({ 400, 0 }, { 100, 100 }, { 0, 1, 0, 1 });
|
||||
auto radius = abs(sin(get_total_time().count())) * 50;
|
||||
context.draw_rounded_rectangle({ 100, 100 }, { 200, 200 }, { 1, 0, 0, 1 }, radius);
|
||||
|
||||
auto height = sin(get_total_time().count()) * 100;
|
||||
context.draw_line({ 600, 600 - height }, { 700, 600 + height }, { 0, 0, 1, 1 }, 0.1);
|
||||
|
||||
context.draw_texture({0, 0}, test_texture->size(), test_texture);
|
||||
|
||||
context.flush();
|
||||
|
||||
swap_chain->Present(1, 0);
|
||||
@ -183,9 +147,7 @@ HRESULT dx_window::build_render_target_view() {
|
||||
viewport.TopLeftY = 0.0f;
|
||||
d3d_context->RSSetViewports(1, &viewport);
|
||||
|
||||
const auto& projection_matrix = get_projection_matrix().transpose();
|
||||
|
||||
context.set_projection_matrix(projection_matrix);
|
||||
projection_matrix = get_projection_matrix().transpose();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -18,4 +18,7 @@ private:
|
||||
renderer_context context;
|
||||
IDXGISwapChain1* swap_chain = nullptr;
|
||||
ID3D11RenderTargetView* render_target_view = nullptr;
|
||||
Eigen::Matrix4f projection_matrix;
|
||||
|
||||
renderer_texture* test_texture = nullptr;
|
||||
};
|
||||
|
41
src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp
Normal file
41
src/renderer/backend/dx/pipeline/dx_pipeline_loader.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "dx_pipeline_loader.h"
|
||||
|
||||
#include "backend/dx/dx_renderer.h"
|
||||
|
||||
bool dx_pipeline_loader::load(const char* vertex_shader_name, const char* pixel_shader_name) {
|
||||
auto renderer = aorii::get_renderer<dx_renderer>();
|
||||
const auto d3d_device = renderer->get_d3d_device();
|
||||
|
||||
const auto& vertex_shader_code = renderer->load_shader(vertex_shader_name);
|
||||
const auto& pixel_shader_code = renderer->load_shader(pixel_shader_name);
|
||||
|
||||
auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建顶点着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建像素着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC);
|
||||
hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void dx_pipeline_loader::use() const {
|
||||
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
d3d_context->VSSetShader(vertex_shader, nullptr, 0);
|
||||
d3d_context->PSSetShader(pixel_shader, nullptr, 0);
|
||||
d3d_context->IASetInputLayout(input_layout);
|
||||
}
|
12
src/renderer/backend/dx/pipeline/dx_pipeline_loader.h
Normal file
12
src/renderer/backend/dx/pipeline/dx_pipeline_loader.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <d3d11.h>
|
||||
|
||||
class dx_pipeline_loader {
|
||||
public:
|
||||
bool load(const char* vertex_shader_name, const char* pixel_shader_name);
|
||||
void use() const;
|
||||
|
||||
ID3D11VertexShader* vertex_shader = nullptr;
|
||||
ID3D11PixelShader* pixel_shader = nullptr;
|
||||
ID3D11InputLayout* input_layout = nullptr;
|
||||
};
|
@ -4,41 +4,12 @@
|
||||
|
||||
bool dx_rect_pipeline::init() {
|
||||
rect_pipeline::init();
|
||||
auto renderer = aorii::get_renderer<dx_renderer>();
|
||||
const auto d3d_device = renderer->get_d3d_device();
|
||||
|
||||
const auto& vertex_shader_code = renderer->load_shader("aorii_rect_vertex_main");
|
||||
const auto& pixel_shader_code = renderer->load_shader("aorii_rect_pixel_main");
|
||||
|
||||
auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建顶点着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建像素着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC);
|
||||
hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
loader.load("aorii_rect_vertex_main", "aorii_rect_pixel_main");
|
||||
return true;
|
||||
}
|
||||
|
||||
void dx_rect_pipeline::use() {
|
||||
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
d3d_context->VSSetShader(vertex_shader, nullptr, 0);
|
||||
d3d_context->PSSetShader(pixel_shader, nullptr, 0);
|
||||
d3d_context->IASetInputLayout(input_layout);
|
||||
loader.use();
|
||||
}
|
||||
|
||||
void dx_rect_pipeline::draw() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "dx_pipeline_loader.h"
|
||||
#include "core/pipeline/rect_pipeline.h"
|
||||
|
||||
class dx_rect_pipeline : public rect_pipeline {
|
||||
@ -9,7 +10,5 @@ public:
|
||||
void use() override;
|
||||
void draw() override;
|
||||
private:
|
||||
ID3D11VertexShader* vertex_shader = nullptr;
|
||||
ID3D11PixelShader* pixel_shader = nullptr;
|
||||
ID3D11InputLayout* input_layout = nullptr;
|
||||
dx_pipeline_loader loader;
|
||||
};
|
||||
|
@ -4,41 +4,11 @@
|
||||
|
||||
bool dx_rounded_rect_pipeline::init() {
|
||||
rounded_rect_pipeline::init();
|
||||
auto renderer = aorii::get_renderer<dx_renderer>();
|
||||
const auto d3d_device = renderer->get_d3d_device();
|
||||
|
||||
const auto& vertex_shader_code = renderer->load_shader("aorii_rounded_rect_vertex_main");
|
||||
const auto& pixel_shader_code = renderer->load_shader("aorii_rounded_rect_pixel_main");
|
||||
|
||||
auto hr = d3d_device->CreateVertexShader(vertex_shader_code.data(), vertex_shader_code.size(), nullptr, &vertex_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rounded_rect_pipeline 无法创建顶点着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
hr = d3d_device->CreatePixelShader(pixel_shader_code.data(), pixel_shader_code.size(), nullptr, &pixel_shader);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rounded_rect_pipeline 无法创建像素着色器: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
D3D11_INPUT_ELEMENT_DESC layout_desc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
constexpr int32_t element_count = sizeof(layout_desc) / sizeof(D3D11_INPUT_ELEMENT_DESC);
|
||||
hr = d3d_device->CreateInputLayout(layout_desc, element_count, vertex_shader_code.data(), vertex_shader_code.size(), &input_layout);
|
||||
if (FAILED(hr)) {
|
||||
spdlog::critical("rect_pipeline 无法创建输入布局: {0}", hr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return loader.load("aorii_rounded_rect_vertex_main", "aorii_rounded_rect_pixel_main");
|
||||
}
|
||||
|
||||
void dx_rounded_rect_pipeline::use() {
|
||||
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
d3d_context->VSSetShader(vertex_shader, nullptr, 0);
|
||||
d3d_context->PSSetShader(pixel_shader, nullptr, 0);
|
||||
d3d_context->IASetInputLayout(input_layout);
|
||||
loader.use();
|
||||
}
|
||||
|
||||
void dx_rounded_rect_pipeline::draw() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "dx_pipeline_loader.h"
|
||||
#include "core/pipeline/rounded_rect_pipeline.h"
|
||||
|
||||
class dx_rounded_rect_pipeline : public rounded_rect_pipeline {
|
||||
@ -9,7 +10,5 @@ public:
|
||||
void use() override;
|
||||
void draw() override;
|
||||
private:
|
||||
ID3D11VertexShader* vertex_shader = nullptr;
|
||||
ID3D11PixelShader* pixel_shader = nullptr;
|
||||
ID3D11InputLayout* input_layout = nullptr;
|
||||
dx_pipeline_loader loader;
|
||||
};
|
||||
|
53
src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp
Normal file
53
src/renderer/backend/dx/pipeline/dx_texture_pipeline.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "dx_texture_pipeline.h"
|
||||
|
||||
#include "backend/dx/dx_renderer.h"
|
||||
#include "backend/dx/dx_texture.h"
|
||||
|
||||
bool dx_texture_pipeline::init() {
|
||||
texture_pipeline::init();
|
||||
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
|
||||
|
||||
D3D11_SAMPLER_DESC sampler_desc = {};
|
||||
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
sampler_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
sampler_desc.MinLOD = 0;
|
||||
sampler_desc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
d3d_device->CreateSamplerState(&sampler_desc, &sampler_state);
|
||||
|
||||
return loader.load("aorii_texture_vertex_main", "aorii_texture_pixel_main");
|
||||
}
|
||||
|
||||
void dx_texture_pipeline::use() {
|
||||
loader.use();
|
||||
}
|
||||
|
||||
void dx_texture_pipeline::draw() {
|
||||
if (!texture) return;
|
||||
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
|
||||
|
||||
// 设置顶点缓冲区
|
||||
constexpr UINT stride = sizeof(aorii_vertex);
|
||||
constexpr UINT offset = 0;
|
||||
auto* v_buffer = static_cast<ID3D11Buffer*>(vertex_buffer->get_native_handle());
|
||||
auto* i_buffer = static_cast<ID3D11Buffer*>(index_buffer->get_native_handle());
|
||||
auto* c_buffer = static_cast<ID3D11Buffer*>(param_buffer->get_native_handle());
|
||||
auto* srv = (ID3D11ShaderResourceView*)texture->get_shader_resource_view();
|
||||
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
|
||||
d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
|
||||
d3d_context->PSSetSamplers(0, 1, &sampler_state);
|
||||
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
|
||||
d3d_context->PSSetShaderResources(0, 1, &srv);
|
||||
|
||||
// 设置图元拓扑
|
||||
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
// 绘制矩形
|
||||
d3d_context->Draw(vertex_buffer->get_size(), 0);
|
||||
}
|
||||
|
||||
void dx_texture_pipeline::set_texture(renderer_texture* in_texture) {
|
||||
texture = static_cast<dx_texture*>(in_texture);
|
||||
}
|
19
src/renderer/backend/dx/pipeline/dx_texture_pipeline.h
Normal file
19
src/renderer/backend/dx/pipeline/dx_texture_pipeline.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "dx_pipeline_loader.h"
|
||||
#include "core/pipeline/texture_pipeline.h"
|
||||
|
||||
class dx_texture_pipeline : public texture_pipeline {
|
||||
public:
|
||||
bool init() override;
|
||||
void use() override;
|
||||
void draw() override;
|
||||
|
||||
void set_texture(renderer_texture* in_texture) override;
|
||||
private:
|
||||
dx_pipeline_loader loader;
|
||||
|
||||
ID3D11SamplerState* sampler_state = nullptr;
|
||||
renderer_texture* texture = nullptr;
|
||||
};
|
16
src/renderer/core/pipeline/texture_pipeline.cpp
Normal file
16
src/renderer/core/pipeline/texture_pipeline.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "texture_pipeline.h"
|
||||
|
||||
#include "core/renderer/renderer.h"
|
||||
|
||||
bool texture_pipeline::init() {
|
||||
param_buffer = aorii::get_renderer_raw()->create_buffer(buffer_type::constant, sizeof(param), 1);
|
||||
return pipeline::init();
|
||||
}
|
||||
void texture_pipeline::destroy() {
|
||||
pipeline::destroy();
|
||||
aorii::get_renderer_raw()->destroy_buffer(param_buffer);
|
||||
}
|
||||
|
||||
void texture_pipeline::set_param(const param& in_param) {
|
||||
param_buffer->set_data(in_param);
|
||||
}
|
18
src/renderer/core/pipeline/texture_pipeline.h
Normal file
18
src/renderer/core/pipeline/texture_pipeline.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "pipeline.h"
|
||||
|
||||
class renderer_texture;
|
||||
|
||||
class texture_pipeline : public pipeline {
|
||||
public:
|
||||
struct param {
|
||||
Eigen::Matrix4f projection_matrix;
|
||||
};
|
||||
bool init() override;
|
||||
void destroy() override;
|
||||
|
||||
void set_param(const param& in_param);
|
||||
virtual void set_texture(renderer_texture* in_texture) = 0;
|
||||
protected:
|
||||
renderer_buffer* param_buffer = nullptr;
|
||||
};
|
@ -2,7 +2,10 @@
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "renderer_texture.h"
|
||||
#include "core/window/renderer_window.h"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
#if DX_BACKEND
|
||||
#include "backend/dx/dx_renderer.h"
|
||||
@ -17,6 +20,61 @@ renderer* s_renderer = nullptr;
|
||||
void renderer::tick() {
|
||||
}
|
||||
|
||||
void renderer::destroy_texture(renderer_texture* texture) { delete texture; }
|
||||
|
||||
renderer_texture* renderer::load_image(const std::string& file_path, texture_format in_format) {
|
||||
int width, height, channels;
|
||||
auto result = stbi_load(file_path.c_str(), &width, &height, &channels, 0);
|
||||
if (!result) {
|
||||
spdlog::critical("Failed to load image: {0}", file_path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int target_channel_count = get_format_channel_count(in_format);
|
||||
unsigned int row_pitch = 0;
|
||||
|
||||
auto texture = create_texture({ width, height }, in_format);
|
||||
auto data = texture->lock(&row_pitch);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
unsigned char* src = result + (y * width + x) * channels;
|
||||
unsigned char* dst = static_cast<unsigned char*>(data) + y * row_pitch + x * target_channel_count;
|
||||
switch (channels) {
|
||||
case 1:
|
||||
dst[0] = src[0];
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = 255;
|
||||
break;
|
||||
case 2:
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = 0;
|
||||
dst[3] = 255;
|
||||
break;
|
||||
case 3:
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = 255;
|
||||
break;
|
||||
case 4:
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
texture->unlock();
|
||||
stbi_image_free(result);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void renderer::destroy_window(renderer_window* window) {
|
||||
delete window;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "renderer_buffer.h"
|
||||
#include "core/pipeline/pipeline.h"
|
||||
|
||||
class texture_pipeline;
|
||||
class rounded_rect_pipeline;
|
||||
class rect_pipeline;
|
||||
class renderer_window;
|
||||
@ -98,6 +99,114 @@ enum class texture_format {
|
||||
BC7_UNORM_SRGB,
|
||||
};
|
||||
|
||||
inline int get_format_channel_count(texture_format format) {
|
||||
switch (format) {
|
||||
case texture_format::R8_UNORM:
|
||||
case texture_format::R8_SNORM:
|
||||
case texture_format::R8_UINT:
|
||||
case texture_format::R8_SINT:
|
||||
case texture_format::R16_FLOAT:
|
||||
case texture_format::R16_UINT:
|
||||
case texture_format::R16_SINT:
|
||||
case texture_format::R32_FLOAT:
|
||||
case texture_format::R32_UINT:
|
||||
case texture_format::R32_SINT:
|
||||
return 1;
|
||||
case texture_format::RG8_UNORM:
|
||||
case texture_format::RG8_SNORM:
|
||||
case texture_format::RG8_UINT:
|
||||
case texture_format::RG8_SINT:
|
||||
case texture_format::RG16_FLOAT:
|
||||
case texture_format::RG16_UINT:
|
||||
case texture_format::RG16_SINT:
|
||||
case texture_format::RG32_FLOAT:
|
||||
case texture_format::RG32_UINT:
|
||||
case texture_format::RG32_SINT:
|
||||
return 2;
|
||||
case texture_format::RGB8_UNORM:
|
||||
case texture_format::RGB8_SNORM:
|
||||
case texture_format::RGB8_UINT:
|
||||
case texture_format::RGB8_SINT:
|
||||
case texture_format::RGB16_FLOAT:
|
||||
case texture_format::RGB32_FLOAT:
|
||||
return 3;
|
||||
case texture_format::RGBA8_UNORM:
|
||||
case texture_format::RGBA8_SNORM:
|
||||
case texture_format::RGBA8_UINT:
|
||||
case texture_format::RGBA8_SINT:
|
||||
case texture_format::RGBA16_FLOAT:
|
||||
case texture_format::RGBA32_FLOAT:
|
||||
case texture_format::RGBA32_UINT:
|
||||
case texture_format::RGBA32_SINT:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline int get_format_bits_pre_channel(texture_format format) {
|
||||
switch (format) {
|
||||
case texture_format::R8_UNORM:
|
||||
case texture_format::R8_SNORM:
|
||||
case texture_format::R8_UINT:
|
||||
case texture_format::R8_SINT:
|
||||
case texture_format::RG8_UNORM:
|
||||
case texture_format::RG8_SNORM:
|
||||
case texture_format::RG8_UINT:
|
||||
case texture_format::RG8_SINT:
|
||||
case texture_format::RGB8_UNORM:
|
||||
case texture_format::RGB8_SNORM:
|
||||
case texture_format::RGB8_UINT:
|
||||
case texture_format::RGB8_SINT:
|
||||
case texture_format::RGBA8_UNORM:
|
||||
case texture_format::RGBA8_SNORM:
|
||||
case texture_format::RGBA8_UINT:
|
||||
case texture_format::RGBA8_SINT:
|
||||
case texture_format::SRGB8:
|
||||
case texture_format::SRGB8_ALPHA8:
|
||||
case texture_format::BC1_UNORM:
|
||||
case texture_format::BC1_UNORM_SRGB:
|
||||
case texture_format::BC2_UNORM:
|
||||
case texture_format::BC2_UNORM_SRGB:
|
||||
case texture_format::BC3_UNORM:
|
||||
case texture_format::BC3_UNORM_SRGB:
|
||||
case texture_format::BC4_UNORM:
|
||||
case texture_format::BC4_SNORM:
|
||||
case texture_format::BC5_UNORM:
|
||||
case texture_format::BC5_SNORM:
|
||||
case texture_format::BC6H_UF16:
|
||||
case texture_format::BC6H_SF16:
|
||||
case texture_format::BC7_UNORM:
|
||||
case texture_format::BC7_UNORM_SRGB:
|
||||
return 8;
|
||||
case texture_format::R16_FLOAT:
|
||||
case texture_format::R16_UINT:
|
||||
case texture_format::R16_SINT:
|
||||
case texture_format::RG16_FLOAT:
|
||||
case texture_format::RG16_UINT:
|
||||
case texture_format::RG16_SINT:
|
||||
case texture_format::RGB16_FLOAT:
|
||||
case texture_format::RGBA16_FLOAT:
|
||||
case texture_format::D16_UNORM:
|
||||
return 16;
|
||||
case texture_format::R32_FLOAT:
|
||||
case texture_format::R32_UINT:
|
||||
case texture_format::R32_SINT:
|
||||
case texture_format::RG32_FLOAT:
|
||||
case texture_format::RG32_UINT:
|
||||
case texture_format::RG32_SINT:
|
||||
case texture_format::RGB32_FLOAT:
|
||||
case texture_format::RGBA32_FLOAT:
|
||||
return 32;
|
||||
case texture_format::D24_UNORM_S8_UINT:
|
||||
case texture_format::D32_FLOAT:
|
||||
case texture_format::D32_FLOAT_S8X24_UINT:
|
||||
return 24;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class renderer {
|
||||
friend class window_manager;
|
||||
public:
|
||||
@ -109,7 +218,9 @@ public:
|
||||
virtual bool render() = 0;
|
||||
|
||||
virtual renderer_texture* create_texture(const Eigen::Vector2i& size, texture_format in_format) = 0;
|
||||
virtual void destroy_texture(renderer_texture* texture) = 0;
|
||||
virtual void destroy_texture(renderer_texture* texture);
|
||||
|
||||
renderer_texture* load_image(const std::string& file_path, texture_format in_format);
|
||||
|
||||
/**
|
||||
* 读取着色器代码
|
||||
@ -129,6 +240,7 @@ public:
|
||||
|
||||
virtual rect_pipeline* get_rect_pipeline() = 0;
|
||||
virtual rounded_rect_pipeline* get_rounded_rect_pipeline() = 0;
|
||||
virtual texture_pipeline* get_texture_pipeline() = 0;
|
||||
private:
|
||||
virtual renderer_window* create_window() = 0;
|
||||
virtual void destroy_window(renderer_window* window);
|
||||
|
@ -1,62 +1,25 @@
|
||||
#include "renderer_context.h"
|
||||
|
||||
#include "renderer.h"
|
||||
#include "backend/dx/dx_renderer.h"
|
||||
|
||||
void renderer_context::init() {
|
||||
rect_p = aorii::get_renderer_raw()->get_rect_pipeline();
|
||||
rounded_rect_p = aorii::get_renderer_raw()->get_rounded_rect_pipeline();
|
||||
}
|
||||
|
||||
void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color) {
|
||||
to_rect_pipeline();
|
||||
const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角
|
||||
const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角
|
||||
const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角
|
||||
const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
const uint32_t index2 = vertices.size();
|
||||
vertices.push_back(v2);
|
||||
const uint32_t index3 = vertices.size();
|
||||
vertices.push_back(v3);
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle t1 = { index1, index2, index3 };
|
||||
const aorii_triangle t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
make_rect(in_pos, in_size, in_color);
|
||||
}
|
||||
|
||||
void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) {
|
||||
to_rounded_rect_pipeline(in_pos, in_size, in_radius);
|
||||
|
||||
const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角
|
||||
const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角
|
||||
const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角
|
||||
const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
const uint32_t index2 = vertices.size();
|
||||
vertices.push_back(v2);
|
||||
const uint32_t index3 = vertices.size();
|
||||
vertices.push_back(v3);
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle t1 = { index1, index2, index3 };
|
||||
const aorii_triangle t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
|
||||
make_rect(in_pos, in_size, in_color);
|
||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||
flush();
|
||||
}
|
||||
|
||||
void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness) {
|
||||
switch_pipeline(rect_p);
|
||||
to_rect_pipeline();
|
||||
const Eigen::Vector2f direction = (in_pos_p2 - in_pos_p1).cast<float>().normalized();
|
||||
const Eigen::Vector2f normal = { -direction.y(), direction.x() };
|
||||
const Eigen::Vector2f offset = normal * in_thickness;
|
||||
@ -80,3 +43,68 @@ void renderer_context::draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
}
|
||||
|
||||
void renderer_context::draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size,
|
||||
renderer_texture* in_texture, const linear_color& in_color) {
|
||||
to_texture_pipeline(in_texture);
|
||||
make_rect(in_pos, in_size, in_color);
|
||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||
flush();
|
||||
}
|
||||
|
||||
void renderer_context::set_projection_matrix(const Eigen::Matrix4f& in_matrix) {
|
||||
projection_matrix = in_matrix;
|
||||
|
||||
// 更新默认管线的投影矩阵
|
||||
const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline();
|
||||
rect_p->set_param({ in_matrix });
|
||||
// 更新纹理管线的投影矩阵
|
||||
const auto texture_p = aorii::get_renderer<dx_renderer>()->get_texture_pipeline();
|
||||
texture_p->set_param({ in_matrix });
|
||||
|
||||
// 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
|
||||
}
|
||||
|
||||
void renderer_context::to_rect_pipeline() {
|
||||
const auto rect_p = aorii::get_renderer<dx_renderer>()->get_rect_pipeline();
|
||||
switch_pipeline(rect_p);
|
||||
}
|
||||
|
||||
void renderer_context::to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius) {
|
||||
const auto rounded_rect_p = aorii::get_renderer<dx_renderer>()->get_rounded_rect_pipeline();
|
||||
switch_pipeline(rounded_rect_p);
|
||||
rounded_rect_pipeline::param param;
|
||||
param.projection_matrix = projection_matrix;
|
||||
param.pos = in_pos.cast<float>();
|
||||
param.size = in_size.cast<float>();
|
||||
param.radius = in_radius;
|
||||
rounded_rect_p->set_param(param);
|
||||
}
|
||||
|
||||
void renderer_context::to_texture_pipeline(renderer_texture* in_texture) {
|
||||
const auto texture_p = aorii::get_renderer<dx_renderer>()->get_texture_pipeline();
|
||||
switch_pipeline(texture_p);
|
||||
texture_p->set_texture(in_texture);
|
||||
}
|
||||
|
||||
void renderer_context::make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size,
|
||||
const linear_color& in_color) {
|
||||
const aorii_vertex v1{ { in_pos.x(), in_pos.y() }, { 0, 0 }, in_color }; // 左上角
|
||||
const aorii_vertex v2{ { in_pos.x() + in_size.x(), in_pos.y() }, { 1, 0 }, in_color }; // 右上角
|
||||
const aorii_vertex v3{ { in_pos.x(), in_pos.y() + in_size.y() }, { 0, 1 }, in_color }; // 左下角
|
||||
const aorii_vertex v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, { 1, 1 }, in_color }; // 右下角
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
const uint32_t index2 = vertices.size();
|
||||
vertices.push_back(v2);
|
||||
const uint32_t index3 = vertices.size();
|
||||
vertices.push_back(v3);
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle t1 = { index1, index2, index3 };
|
||||
const aorii_triangle t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "core/pipeline/rect_pipeline.h"
|
||||
#include "core/pipeline/rounded_rect_pipeline.h"
|
||||
|
||||
class renderer_texture;
|
||||
|
||||
class renderer_context {
|
||||
public:
|
||||
void init();
|
||||
@ -34,6 +36,14 @@ public:
|
||||
*/
|
||||
void draw_line(const Eigen::Vector2i& in_pos_p1, const Eigen::Vector2i& in_pos_p2, const linear_color& in_color, float in_thickness);
|
||||
|
||||
/**
|
||||
* 绘制一个纹理
|
||||
* @param in_pos 当前控件坐标系的位置
|
||||
* @param in_size 绘制的大小(受控件缩放影响)
|
||||
* @param in_texture 纹理
|
||||
*/
|
||||
void draw_texture(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, renderer_texture* in_texture, const linear_color& in_color = linear_color::white);
|
||||
|
||||
void clear() {
|
||||
vertices.clear();
|
||||
triangles.clear();
|
||||
@ -53,14 +63,8 @@ public:
|
||||
}
|
||||
clear();
|
||||
}
|
||||
void set_projection_matrix(const Eigen::Matrix4f& in_matrix) {
|
||||
projection_matrix = in_matrix;
|
||||
void set_projection_matrix(const Eigen::Matrix4f& in_matrix);
|
||||
|
||||
// 更新默认管线的投影矩阵
|
||||
rect_p->set_param({ in_matrix });
|
||||
|
||||
// 圆角矩形管线的投影矩阵不需要更新, 因为它在每次绘制时都会更新
|
||||
}
|
||||
protected:
|
||||
void switch_pipeline(pipeline* in_pipeline) {
|
||||
#if DEBUG
|
||||
@ -74,25 +78,15 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void to_rect_pipeline() {
|
||||
switch_pipeline(rect_p);
|
||||
}
|
||||
void to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius) {
|
||||
switch_pipeline(rounded_rect_p);
|
||||
rounded_rect_pipeline::param param;
|
||||
param.projection_matrix = projection_matrix;
|
||||
param.pos = in_pos.cast<float>();
|
||||
param.size = in_size.cast<float>();
|
||||
param.radius = in_radius;
|
||||
rounded_rect_p->set_param(param);
|
||||
}
|
||||
void to_rect_pipeline();
|
||||
void to_rounded_rect_pipeline(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, float in_radius);
|
||||
void to_texture_pipeline(renderer_texture* in_texture);
|
||||
private:
|
||||
std::vector<aorii_vertex> vertices;
|
||||
std::vector<aorii_triangle> triangles;
|
||||
|
||||
rect_pipeline* rect_p = nullptr;
|
||||
rounded_rect_pipeline* rounded_rect_p = nullptr;
|
||||
|
||||
pipeline* current_pipeline = nullptr;
|
||||
Eigen::Matrix4f projection_matrix;
|
||||
private:
|
||||
void make_rect(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color);
|
||||
};
|
||||
|
@ -1,14 +1,42 @@
|
||||
#pragma once
|
||||
#include <Eigen/Eigen>
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
class renderer_texture {
|
||||
public:
|
||||
renderer_texture(texture_format in_format) : format(in_format) {}
|
||||
virtual ~renderer_texture() = default;
|
||||
|
||||
|
||||
virtual void* lock() = 0;
|
||||
virtual void* lock(unsigned int* out_row_pitch) = 0;
|
||||
virtual void unlock() = 0;
|
||||
|
||||
virtual bool resize(const Eigen::Vector2i& size) = 0;
|
||||
virtual Eigen::Vector2i size() = 0;
|
||||
|
||||
virtual void* get_native_handle() = 0;
|
||||
virtual void* get_shader_resource_view() = 0;
|
||||
[[nodiscard]] texture_format get_format() const { return format; }
|
||||
|
||||
|
||||
static void convert_rgb_to_rgba(const unsigned char* rgb, unsigned char* rgba, int width, int height) {
|
||||
for (int i = 0; i < width * height; ++i) {
|
||||
rgba[i * 4 + 0] = rgb[i * 3 + 0]; // R
|
||||
rgba[i * 4 + 1] = rgb[i * 3 + 1]; // G
|
||||
rgba[i * 4 + 2] = rgb[i * 3 + 2]; // B
|
||||
rgba[i * 4 + 3] = 255; // A (完全不透明)
|
||||
}
|
||||
}
|
||||
private:
|
||||
const texture_format format;
|
||||
};
|
||||
|
||||
class texture_format_converter {
|
||||
public:
|
||||
texture_format_converter(Eigen::Vector2i size, texture_format in_format, texture_format out_format) : size(size), in_format(in_format), out_format(out_format) {}
|
||||
|
||||
private:
|
||||
Eigen::Vector2i size;
|
||||
texture_format in_format;
|
||||
texture_format out_format;
|
||||
};
|
||||
|
3
src/renderer/misc/color.cpp
Normal file
3
src/renderer/misc/color.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "color.h"
|
||||
|
||||
const linear_color linear_color::white = linear_color(1, 1, 1, 1);
|
@ -38,4 +38,12 @@ public:
|
||||
return { r - in_color.r, g - in_color.g, b - in_color.b, a - in_color.a };
|
||||
}
|
||||
float r, g, b, a;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const linear_color white;
|
||||
};
|
||||
|
35
src/renderer/shader/aorii_texture.slang
Normal file
35
src/renderer/shader/aorii_texture.slang
Normal file
@ -0,0 +1,35 @@
|
||||
struct ParamBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
ParameterBlock<ParamBuffer> param_buffer : register(b0);
|
||||
|
||||
struct VSInput {
|
||||
float2 position : POSITION; // 窗口坐标
|
||||
float2 uv : TEXCOORD0; // 纹理坐标
|
||||
float4 color : COLOR; // 颜色
|
||||
};
|
||||
|
||||
struct PSInput {
|
||||
float4 position : SV_POSITION; // 裁剪空间坐标
|
||||
float2 uv : TEXCOORD0; // 纹理坐标
|
||||
float4 color : COLOR; // 颜色
|
||||
};
|
||||
|
||||
Texture2D<float4> texture : register(t0);
|
||||
SamplerState sampler : register(s0);
|
||||
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform);
|
||||
output.uv = input.uv;
|
||||
output.color = input.color;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color * texture.Sample(sampler, input.uv);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user