aorii/src/renderer/backend/dx/dx_window.cpp
2024-11-05 18:36:50 +08:00

209 lines
6.6 KiB
C++

#include "dx_window.h"
#include <spdlog/spdlog.h>
#include "dx_renderer.h"
#include "misc/scope_exit.h"
#include <math.h>
using namespace aorii;
dx_pipeline default_pipeline;
dx_pipeline rounded_rect_pipeline;
bool dx_window::create_surface(GLFWwindow* in_window) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
IDXGIDevice* dxgi_device = nullptr;
auto hr = d3d_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgi_device));
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIDevice, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_device) dxgi_device->Release();
};
IDXGIAdapter* dxgi_adapter = nullptr;
hr = dxgi_device->GetAdapter(&dxgi_adapter);
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIAdapter, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_adapter) dxgi_adapter->Release();
};
IDXGIFactory2* dxgi_factory = nullptr;
hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgi_factory));
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIFactory, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_factory) dxgi_factory->Release();
};
DXGI_SWAP_CHAIN_DESC1 sd = {};
sd.Width = 0; // 使用窗口宽度
sd.Height = 0; // 使用窗口高度
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 2;
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Flags = 0;
const auto hwnd = static_cast<HWND>(get_window_handle());
hr = dxgi_factory->CreateSwapChainForHwnd(d3d_device, hwnd, &sd, nullptr, nullptr, &swap_chain);
if (FAILED(hr)) {
spdlog::critical("无法创建交换链, 错误: {0}", hr);
return false;
}
default_pipeline.build_constant_buffer();
rounded_rect_pipeline.build_constant_buffer();
hr = build_render_target_view();
if (FAILED(hr)) {
spdlog::critical("无法创建渲染模板视图, 错误: {0}", hr);
return false;
}
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();
context.set_default_pipeline(&default_pipeline);
context.set_rounded_rectangular_pipeline(&rounded_rect_pipeline);
return true;
}
void dx_window::begin_frame() {
glfwMakeContextCurrent(get_glfw_window());
const auto render = aorii::get_renderer<dx_renderer>();
const auto d3d_context = render->get_d3d_context();
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
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.draw_rounded_rectangle({ 100, 100 }, { 100, 100 }, { 1, 0, 0, 1 }, 10);
context.flush();
swap_chain->Present(1, 0);
}
void dx_window::end_frame() {
}
void dx_window::on_resize(const Eigen::Vector2i& in_size) {
if (in_size.isZero())
return;
if (render_target_view) {
render_target_view->Release();
render_target_view = nullptr;
}
auto hr = swap_chain->ResizeBuffers(0, in_size.x(), in_size.y(), DXGI_FORMAT_UNKNOWN, 0);
if (FAILED(hr)) {
spdlog::critical("Failed to resize window. Error: {0}", hr);
return;
}
build_render_target_view();
}
HRESULT dx_window::build_render_target_view() {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
ID3D11Texture2D* back_buffer = nullptr;
auto hr = swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
if (FAILED(hr)) {
spdlog::critical("Failed to get back buffer. Error: {0}", hr);
return hr;
}
ON_SCOPE_EXIT{
if (back_buffer) back_buffer->Release();
};
hr = d3d_device->CreateRenderTargetView(back_buffer, nullptr, &render_target_view);
if (FAILED(hr)) {
spdlog::critical("Failed to create render target. Error: {0}", hr);
return hr;
}
auto framebuffer_size = get_framebuffer_size();
D3D11_VIEWPORT viewport = {};
viewport.Width = (float)framebuffer_size.x();
viewport.Height = (float)framebuffer_size.y();
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
d3d_context->RSSetViewports(1, &viewport);
const auto& projection_matrix = get_projection_matrix().transpose();
// 更新常量缓冲区
const auto constant_buffer = default_pipeline.lock_constant_buffer();
constant_buffer->projection_matrix = projection_matrix;
default_pipeline.unlock_constant_buffer();
const auto rounded_rect_constant_buffer = rounded_rect_pipeline.lock_constant_buffer();
rounded_rect_constant_buffer->projection_matrix = projection_matrix;
rounded_rect_pipeline.unlock_constant_buffer();
return hr;
}