1
0
Files
BasaltMeter/BasaltPresenter/Plugins/Engine/DirectX11Engine/main.cpp

234 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <basalt_export.hpp>
#include <engine.hpp>
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <wrl/client.h>
#include <vector>
#include <iostream>
using Microsoft::WRL::ComPtr;
// 常量
constexpr UINT Width = 800;
constexpr UINT Height = 600;
constexpr const wchar_t* PipeName = L"\\\\.\\pipe\\54da494c-301a-47a9-9d67-4fbebaeda8cf";
// 立方体顶点(位置)
struct Vertex {
float x, y, z;
};
Vertex CubeVertices[] = {
// 前面
{-1, -1, -1},
{1, -1, -1},
{1, 1, -1},
{-1, -1, -1},
{1, 1, -1},
{-1, 1, -1},
// 后面
{-1, -1, 1},
{-1, 1, 1},
{1, 1, 1},
{-1, -1, 1},
{1, 1, 1},
{1, -1, 1},
// 其他面...(为简化,此处略,或用完整立方体)
// 实际建议使用完整12个三角面36顶点
};
// 为简化,这里只渲染前面,实际请补全
// 简单顶点着色器(只传位置)
const char* g_VS = R"(
float4 main(float3 pos : POSITION) : SV_POSITION {
return float4(pos, 1.0f);
}
)";
// 简单像素着色器(返回固定颜色)
const char* g_PS = R"(
float4 main() : SV_TARGET {
return float4(0.2f, 0.4f, 0.8f, 1.0f);
}
)";
int main() {
// 初始化 COM
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
// 创建设备和上下文
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
D3D11CreateDevice(
nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_DEBUG, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context);
// 创建交换链(窗口可选,这里仅用于渲染上下文)
ComPtr<IDXGISwapChain> swapChain;
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferDesc.Width = Width;
sd.BufferDesc.Height = Height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = GetConsoleWindow(); // 或创建窗口
sd.Windowed = TRUE;
ComPtr<IDXGIDevice> dxgiDevice;
device.As(&dxgiDevice);
ComPtr<IDXGIAdapter> adapter;
dxgiDevice->GetAdapter(&adapter);
ComPtr<IDXGIFactory> factory;
adapter->GetParent(IID_PPV_ARGS(&factory));
factory->CreateSwapChain(device.Get(), &sd, &swapChain);
// 创建渲染目标
ComPtr<ID3D11RenderTargetView> rtv;
ComPtr<ID3D11Texture2D> backBuffer;
swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
device->CreateRenderTargetView(backBuffer.Get(), nullptr, &rtv);
// 创建深度缓冲D32_FLOAT
ComPtr<ID3D11Texture2D> depthBuffer;
D3D11_TEXTURE2D_DESC depthDesc = {};
depthDesc.Width = Width;
depthDesc.Height = Height;
depthDesc.MipLevels = 1;
depthDesc.ArraySize = 1;
depthDesc.Format = DXGI_FORMAT_D32_FLOAT;
depthDesc.SampleDesc.Count = 1;
depthDesc.Usage = D3D11_USAGE_DEFAULT;
depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
device->CreateTexture2D(&depthDesc, nullptr, &depthBuffer);
ComPtr<ID3D11DepthStencilView> dsv;
device->CreateDepthStencilView(depthBuffer.Get(), nullptr, &dsv);
// 创建 staging texture 用于 CPU 读取深度R32_FLOAT
ComPtr<ID3D11Texture2D> depthStaging;
D3D11_TEXTURE2D_DESC stagingDesc = depthDesc;
stagingDesc.Format = DXGI_FORMAT_R32_FLOAT; // 注意DSV 用 D32_FLOATstaging 用 R32_FLOAT
stagingDesc.BindFlags = 0;
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stagingDesc.Usage = D3D11_USAGE_STAGING;
device->CreateTexture2D(&stagingDesc, nullptr, &depthStaging);
// 编译并创建着色器
ComPtr<ID3D11VertexShader> vs;
ComPtr<ID3D11PixelShader> ps;
ComPtr<ID3DBlob> vsBlob, psBlob;
D3DCompile(g_VS, strlen(g_VS), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vsBlob, nullptr);
D3DCompile(g_PS, strlen(g_PS), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &psBlob, nullptr);
device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &vs);
device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &ps);
// 输入布局
D3D11_INPUT_ELEMENT_DESC layout[] = {{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}};
ComPtr<ID3D11InputLayout> inputLayout;
device->CreateInputLayout(layout, 1, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &inputLayout);
// 顶点缓冲
ComPtr<ID3D11Buffer> vertexBuffer;
D3D11_BUFFER_DESC vbDesc = {};
vbDesc.ByteWidth = sizeof(CubeVertices);
vbDesc.Usage = D3D11_USAGE_DEFAULT;
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA vbData = {CubeVertices};
device->CreateBuffer(&vbDesc, &vbData, &vertexBuffer);
// 深度测试启用
ComPtr<ID3D11DepthStencilState> depthState;
D3D11_DEPTH_STENCIL_DESC dsDesc = {};
dsDesc.DepthEnable = TRUE;
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D11_COMPARISON_LESS;
device->CreateDepthStencilState(&dsDesc, &depthState);
// 视口
D3D11_VIEWPORT vp = {0, 0, (float) Width, (float) Height, 0, 1};
context->RSSetViewports(1, &vp);
// 打开命名管道(需另一进程已创建)
HANDLE hPipe = CreateFileW(PipeName, GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (hPipe == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open named pipe. Ensure another process created it.\n";
return -1;
}
constexpr size_t depthSize = Width * Height * sizeof(float);
std::vector<BYTE> depthData(depthSize);
// 渲染循环示例只渲染10帧
for (int frame = 0; frame < 10; ++frame) {
// 清屏
float clearColor[] = {0.1f, 0.1f, 0.1f, 1.0f};
context->ClearRenderTargetView(rtv.Get(), clearColor);
context->ClearDepthStencilView(dsv.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
// 设置管线
context->OMSetRenderTargets(1, rtv.GetAddressOf(), dsv.Get());
context->OMSetDepthStencilState(depthState.Get(), 1);
context->VSSetShader(vs.Get(), nullptr, 0);
context->PSSetShader(ps.Get(), nullptr, 0);
context->IASetInputLayout(inputLayout.Get());
UINT stride = sizeof(Vertex), offset = 0;
context->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// 绘制立方体
context->Draw(6, 0); // 仅前面实际应为36
// 复制深度缓冲到 staging texture
context->CopyResource(depthStaging.Get(), depthBuffer.Get());
// Map 获取数据
D3D11_MAPPED_SUBRESOURCE mapped;
context->Map(depthStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped);
memcpy(depthData.data(), mapped.pData, depthSize);
context->Unmap(depthStaging.Get(), 0);
// 写入命名管道
DWORD written;
if (!WriteFile(hPipe, depthData.data(), static_cast<DWORD>(depthSize), &written, nullptr) || written != depthSize) {
std::cerr << "WriteFile failed or incomplete.\n";
break;
}
// 呈现(可选)
swapChain->Present(0, 0);
}
CloseHandle(hPipe);
CoUninitialize();
return 0;
}
using ::Basalt::Shared::Engine::EngineConfig;
using ::Basalt::Shared::Engine::IEngine;
class DirectX11Engine : public IEngine {
public:
DirectX11Engine() : IEngine() {}
virtual ~DirectX11Engine() {}
private:
ComPtr<ID3D11Device> device; ///< 设备
ComPtr<ID3D11DeviceContext> context; ///< 上下文
ComPtr<IDXGISwapChain> swapChain; ///< 交换链
public:
virtual void Startup(EngineConfig&& config) override { IEngine::Startup(std::move(config)); }
virtual void Tick() override { IEngine::Tick(); }
virtual void Shutdown() override { IEngine::Shutdown(); }
};
BS_EXPORT void* BSCreateInstance() {
return new DirectX11Engine();
}
BS_EXPORT void BSDestroyInstance(void* instance) {
delete reinterpret_cast<DirectX11Engine*>(instance);
}