namespace dx11
{
static ID3D11Device* device; // Direct3D 设备
static ID3D11DeviceContext* context; // 设备上下文
// 创建纹理
[[nodiscard]] static ID3D11Texture2D* createTexture(int width, int height) noexcept
{
// 检查宽高是否有效
if (width <= 0 || height <= 0) {
printf("Invalid texture dimensions: width=%d, height=%d\n", width, height);
return nullptr;
}
printf("Invalid texture dimensions: width=%d, height=%d\n", width, height);
// 检查设备支持的最大纹理尺寸
D3D11_FEATURE_DATA_D3D11_OPTIONS options;
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
ID3D11Texture2D* texture = nullptr;
HRESULT hr = device->CreateTexture2D(&desc, nullptr, &texture); // 创建纹理
if (FAILED(hr)) {
printf("Failed to create texture: HRESULT = 0x%08X\n", hr);
}
else {
printf("createTexture2D succeeded: %p\n", texture);
}
return texture;
}
// 将后台缓冲区复制到纹理
static void copyBackbufferToTexture(ID3D11Texture2D* texture) noexcept
{
ID3D11Texture2D* backBuffer = nullptr; // 声明后台缓冲区指针
ID3D11RenderTargetView* rtv = nullptr; // 声明渲染目标视图指针
// 获取当前的渲染目标
context->OMGetRenderTargets(1, &rtv, nullptr);
if (rtv) {
rtv->GetResource(reinterpret_cast<ID3D11Resource**>(&backBuffer)); // 获取后台缓冲区的资源
rtv->Release(); // 释放渲染目标视图
}
if (backBuffer) {
// 复制资源
context->CopyResource(texture, backBuffer);
backBuffer->Release(); // 释放后台缓冲区
}
else {
printf("Failed to get back buffer.\n");
}
}
// 设置渲染目标
static void setRenderTarget(ID3D11Texture2D* rtTexture) noexcept
{
ID3D11RenderTargetView* rtv;
device->CreateRenderTargetView(rtTexture, nullptr, &rtv); // 创建渲染目标视图
context->OMSetRenderTargets(1, &rtv, nullptr); // 设置渲染目标
}
class ShaderProgram {
public:
ShaderProgram() = default; // 默认构造函数
// 初始化着色器
void init(const BYTE* pixelShaderSrc, SIZE_T size) noexcept {
if (initialized) return;
initialized = true;
// 确保 pixelShaderSrc 和 size 是有效的
if (!pixelShaderSrc || size == 0) {
printf("Invalid pixel shader source or size.\n");
return;
}
HRESULT hr = device->CreatePixelShader(pixelShaderSrc, size, nullptr, &pixelShader);
if (FAILED(hr)) {
printf("Failed to create pixel shader: HRESULT = 0x%08X\n", hr);
return;
}
// 创建常量缓冲区
// Create the constant buffer
D3D11_BUFFER_DESC cbd;
ZeroMemory(&cbd, sizeof(cbd));
cbd.Usage = D3D11_USAGE_DYNAMIC;
cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbd.ByteWidth = sizeof(float)*5000;
hr = device->CreateBuffer(&cbd, nullptr, uniformBuffer.GetAddressOf());
if (FAILED(hr)) {
printf("Failed to create uniform buffer: HRESULT = 0x%08X\n", hr);
}
}
void use(float uniform, int location) const noexcept {
// 设置像素着色器
context->PSSetShader(pixelShader.Get(), nullptr, 0);
// 确保 uniformBuffer 已创建
if (!uniformBuffer) {
printf("Uniform buffer is not initialized!\n");
return;
}
// 设置常量数据
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = context->Map(uniformBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
printf("Failed to map uniform buffer: HRESULT = 0x%08X\n", hr);
return;
}
// 复制数据到缓冲区
memcpy(mappedResource.pData, &uniform, sizeof(float));
context->Unmap(uniformBuffer.Get(), 0);
// 设置常量缓冲区
context->PSSetConstantBuffers(location, 1, uniformBuffer.GetAddressOf());
}
private:
ComPtr<ID3D11PixelShader> pixelShader; // 像素着色器
ComPtr<ID3D11Buffer> uniformBuffer; // 常量缓冲区
bool initialized = false; // 是否已初始化
};
//class ShaderProgram {
//public:
// // 使用着色器并设置常量
// void use(float uniform, int location) const noexcept
// {
// // 设置像素着色器
// context->PSSetShader(pixelShader.Get(), nullptr, 0);
// // 创建或更新常量缓冲区
// if (!uniformBuffer) {
// // 创建常量缓冲区的代码(如果尚未创建)
// D3D11_BUFFER_DESC bufferDesc = {};
// bufferDesc.ByteWidth = sizeof(float); // 确保大小足够
// bufferDesc.Usage = D3D11_USAGE_DEFAULT;
// bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
// HRESULT hr = device->CreateBuffer(&bufferDesc, nullptr, uniformBuffer.GetAddressOf());
// if (FAILED(hr)) {
// printf("Failed to create uniform buffer: HRESULT = 0x%08X\n", hr);
// return; // 处理失败
// }
// }
// if (!uniformBuffer) {
// printf("Uniform buffer is not initialized!\n");
// return;
// }
// // 设置常量数据
// D3D11_MAPPED_SUBRESOURCE mappedResource;
// HRESULT hr = context->Map(uniformBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
// if (FAILED(hr)) {
// printf("Failed to map uniform buffer: HRESULT = 0x%08X\n", hr);
// // 额外的调试信息
// if (hr == E_INVALIDARG) {
// printf("Invalid argument passed to Map.\n");
// }
// else if (hr == DXGI_ERROR_INVALID_CALL) {
// printf("Invalid call in Map. Ensure the buffer is created properly and not currently in use.\n");
// }
// return; // 映射失败,提前返回
// }
// // 复制数据到缓冲区
// memcpy(mappedResource.pData, &uniform, sizeof(float)); // 将 uniform 值复制到缓冲区
// context->Unmap(uniformBuffer.Get(), 0);
// // 设置常量缓冲区
// context->PSSetConstantBuffers(location, 1, uniformBuffer.GetAddressOf()); // 修改为: 设置常量缓冲区
// }
// // 初始化着色器
// void init(const BYTE* pixelShaderSrc) noexcept
// {
// if (initialized)
// return;
// initialized = true;
// device->CreatePixelShader(pixelShaderSrc, sizeof(pixelShaderSrc), nullptr, &pixelShader); // 创建像素着色器
// // 创建常量缓冲区
// D3D11_BUFFER_DESC bufferDesc = {};
// bufferDesc.Usage = D3D11_USAGE_DEFAULT;
// bufferDesc.ByteWidth = sizeof(float) * 4; // 4个浮点数
// bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
// device->CreateBuffer(&bufferDesc, nullptr, &uniformBuffer);
// }
//private:
// ComPtr<ID3D11PixelShader> pixelShader; // 像素着色器
// //ComPtr<ID3D11Buffer> uniformBuffer;
// mutable ComPtr<ID3D11Buffer> uniformBuffer;
// bool initialized = false; // 是否已初始化
//};
class BlurEffect {
public:
static void draw(ImDrawList* drawList, float alpha) noexcept
{
instance()._draw(drawList, alpha);
}
static void clearTextures() noexcept
{
if (instance().blurTexture1) {
instance().blurTexture1->Release();
instance().blurTexture1 = nullptr;
}
if (instance().blurTexture2) {
instance().blurTexture2->Release();
instance().blurTexture2 = nullptr;
}
}
private:
ID3D11Texture2D* blurTexture1 = nullptr; // 第一个模糊纹理
ID3D11Texture2D* blurTexture2 = nullptr; // 第二个模糊纹理
ID3D11RenderTargetView* rtBackup = nullptr; // 备份的渲染目标
ID3D11RenderTargetView* blurTexture1RTV = nullptr; // 第一个模糊纹理的RTV
ID3D11RenderTargetView* blurTexture2RTV = nullptr; // 第二个模糊纹理的RTV
ID3D11SamplerState* samplerState = nullptr; // 采样器状态
ID3D11Buffer* projectionBuffer = nullptr; // 投影矩阵缓冲区
ShaderProgram blurShaderX; // 水平模糊着色器
ShaderProgram blurShaderY; // 垂直模糊着色器
static constexpr auto blurDownsample = 4; // 模糊下采样比例
BlurEffect() {
// 创建采样器状态
D3D11_SAMPLER_DESC samplerDesc = {};
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
device->CreateSamplerState(&samplerDesc, &samplerState); // 创建采样器状态
// 创建投影矩阵缓冲区
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(XMMATRIX); // 大小为矩阵的大小
bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
device->CreateBuffer(&bufferDesc, nullptr, &projectionBuffer); // 创建缓冲区
// 创建模糊纹理RTV
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 纹理格式
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0;
// 创建第一个模糊纹理的RTV
device->CreateRenderTargetView(blurTexture1, &rtvDesc, &blurTexture1RTV);
// 创建第二个模糊纹理的RTV
device->CreateRenderTargetView(blurTexture2, &rtvDesc, &blurTexture2RTV);
}
BlurEffect(const BlurEffect&) = delete; // 禁止复制构造
~BlurEffect()
{
if (rtBackup) rtBackup->Release(); // 释放备份的渲染目标
if (blurTexture1) blurTexture1->Release(); // 释放第一个模糊纹理
if (blurTexture2) blurTexture2->Release(); // 释放第二个模糊纹理
if (blurTexture1RTV) blurTexture1RTV->Release(); // 释放第一个模糊纹理的RTV
if (blurTexture2RTV) blurTexture2RTV->Release(); // 释放第二个模糊纹理的RTV
if (samplerState) samplerState->Release(); // 释放采样器状态
if (projectionBuffer) projectionBuffer->Release(); // 释放投影矩阵缓冲区
}
static BlurEffect& instance() noexcept
{
static BlurEffect blurEffect;
return blurEffect;
}
void _draw(ImDrawList* drawList, float alpha) noexcept
{
createTextures(); // 创建模糊纹理
createShaders(); // 创建模糊着色器
if (!blurTexture1 || !blurTexture2) return; // 检查纹理是否有效
Vector p;
Vector pos = me->GetPos();
Functions.WorldToScreen(&pos, &p);
/*std::string g_scriptpath = XorString("D:\\");*/
Vector MapPos2 = Engine::worldToMap(pos);
Vector size = Vector(25, 25, 0);
drawList->AddCallback(&begin, nullptr);
for (int i = 0; i < 8; ++i) {
drawList->AddCallback(&firstPass, nullptr); // 第一阶段模糊处理
drawList->AddImage(reinterpret_cast<ImTextureID>(blurTexture1), ImVec2(pos.X, pos.Y), ImVec2(pos.X + size.X, pos.Y + size.Y)); // 显示第一模糊纹理
drawList->AddCallback(&secondPass, nullptr); // 第二阶段模糊处理
//drawList->AddImage(reinterpret_cast<ImTextureID>(blurTexture2), { -1.0f, -1.0f }, { 1.0f, 1.0f }); // 显示第二模糊纹理
}
drawList->AddCallback(&end, nullptr);
drawList->AddCallback(ImDrawCallback_ResetRenderState, nullptr); // 重置状态
/*drawList->AddImage(reinterpret_cast<ImTextureID>(blurTexture1), { 0.0f, 0.0f }, { backbufferWidth * 1.0f, backbufferHeight * 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f }, IM_COL32(255, 255, 255, 255 * alpha));*/
}
void createTextures() noexcept
{
if (!blurTexture1) {
blurTexture1 = createTexture(backbufferWidth / blurDownsample, backbufferHeight / blurDownsample);
}
if (!blurTexture2) {
blurTexture2 = createTexture(backbufferWidth / blurDownsample, backbufferHeight / blurDownsample);
}
}
void createShaders() noexcept
{
blurShaderX.init(blur_x, sizeof(blur_x)); // 确保传入正确的大小
blurShaderY.init(blur_y, sizeof(blur_y)); // 确保传入正确的大小
}
static void begin(const ImDrawList*, const ImDrawCmd*) noexcept { instance()._begin(); }
static void firstPass(const ImDrawList*, const ImDrawCmd*) noexcept { instance()._firstPass(); }
static void secondPass(const ImDrawList*, const ImDrawCmd*) noexcept { instance()._secondPass(); }
static void end(const ImDrawList*, const ImDrawCmd*) noexcept { instance()._end(); }
void _begin() noexcept
{
printf("备份当前渲染目标");
// 备份当前渲染目标
context->OMGetRenderTargets(1, &rtBackup, nullptr);
printf("_begin -> Backup render target: %p\n", rtBackup); // 打印备份的渲染目标
// 复制后台缓冲区到模糊纹理
copyBackbufferToTexture(blurTexture1); // 调用复制函数
printf("_begin -> Successfully copied back buffer to blurTexture1: %p\n", blurTexture1);
// 设置采样器状态
context->PSSetSamplers(0, 1, &samplerState); // 设置采样器状态
printf("_begin -> Sampler state set successfully.\n");
// 禁用剪裁测试
// 在 DX11 中,这里不需要显式设置剪裁状态,但可以通过其他方式进行控制
// 打印一条说明
printf("_begin -> Clip testing disabled (DX11 does not require explicit state change).\n");
// 设置投影矩阵
XMMATRIX projection = XMMATRIX(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
-1.0f / (backbufferWidth / blurDownsample),
1.0f / (backbufferHeight / blurDownsample),
0.0f, 1.0f
);
printf("_begin -> Projection matrix created.\n");
// 更新常量缓冲区并设置
context->UpdateSubresource(projectionBuffer, 0, nullptr, &projection, 0, 0);
printf("_begin -> Updated projection buffer.\n");
context->VSSetConstantBuffers(0, 1, &projectionBuffer); // 将投影矩阵设置给顶点着色器
printf("_begin -> Constant buffer set successfully.\n");
}
void _firstPass() noexcept
{
printf("_firstPass-> Start!\n");
// 使用水平模糊着色器
blurShaderX.use(1.0f / (backbufferWidth / blurDownsample), 0); // 在 DX9 中使用: blurShaderX.use
// 设置渲染目标为第二个模糊纹理
printf("_firstPass-> blurShaderX.use\n");
context->OMSetRenderTargets(1, &blurTexture2RTV, nullptr); // 在 DX9 中使用: setRenderTarget(blurTexture2);
printf("_firstPass-> context->OMSetRenderTargets(1, &blurTexture2RTV, nullptr); \n");
}
void _secondPass() noexcept
{
// 使用垂直模糊着色器
blurShaderY.use(1.0f / (backbufferHeight / blurDownsample), 0); // 在 DX9 中使用: blurShaderY.use
// 设置渲染目标为第一个模糊纹理
printf("_secondPass-> blurShaderY.use\n");
context->OMSetRenderTargets(1, &blurTexture1RTV, nullptr); // 在 DX9 中使用: setRenderTarget(blurTexture1);
printf("_secondPass-> context->OMSetRenderTargets\n");
}
void _end() noexcept
{
// 恢复到备份的渲染目标
context->OMSetRenderTargets(1, &rtBackup, nullptr); // 在 DX9 中使用: device->SetRenderTarget(0, rtBackup);
printf("_end-> context->OMSetRenderTargets\n");
if (rtBackup) rtBackup->Release(); // 释放备份渲染目标
printf("_end-> rtBackup->Release(); \n");
// 重置像素着色器
context->PSSetShader(nullptr, nullptr, 0); // 在 DX9 中使用: device->SetPixelShader(nullptr);
// 重置状态(如需要)
printf("_end-> context->PSSetShader\n");
}
};
}
#ifdef _WIN32
void PostProcessing::setDevice9(IDirect3DDevice9* device) noexcept
{
dx9::device = device;
}
void PostProcessing::setDevice11(ID3D11Device* device,ID3D11DeviceContext* context) noexcept
{
dx11::device = device;
dx11::context = context;
}
void PostProcessing::clearBlurTextures() noexcept
{
dx11::BlurEffect::clearTextures();
}
void PostProcessing::onDeviceReset() noexcept
{
dx11::BlurEffect::clearTextures();
//dx11::ChromaticAberration::clearTexture();
}
#endif
void PostProcessing::newFrame() noexcept
{
if (const auto [width, height] = ImGui::GetIO().DisplaySize; backbufferWidth != static_cast<int>(width) || backbufferHeight != static_cast<int>(height)) {
dx11::BlurEffect::clearTextures();
//dx11::ChromaticAberration::clearTexture();
//dx11::MonochromeEffect::clearTexture();
backbufferWidth = static_cast<int>(width);
backbufferHeight = static_cast<int>(height);
}
}
void PostProcessing::performFullscreenBlur(ImDrawList* drawList, float alpha) noexcept
{
dx11::BlurEffect::draw(drawList, alpha);//高斯模糊
}
怎么使用这个代码