-
Автор темы
- #1
Пожалуйста, авторизуйтесь для просмотра ссылки.
blur.cpp:
#include <d3d9.h>
#include <wrl/client.h>
#include "blur.h"
#include "blur_x.h"
#include "blur_y.h"
using Microsoft::WRL::ComPtr;
static int backbufferWidth = 0;
static int backbufferHeight = 0;
static IDirect3DDevice9* device;
[[nodiscard]] static IDirect3DTexture9* createTexture(int width, int height) noexcept
{
if (!device)
return nullptr;
IDirect3DTexture9* texture;
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr);
return texture;
}
static void copyBackbufferToTexture(IDirect3DTexture9* texture, D3DTEXTUREFILTERTYPE filtering) noexcept
{
if (!device)
return;
ComPtr<IDirect3DSurface9> backBuffer;
if (device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, backBuffer.GetAddressOf()) == D3D_OK) {
ComPtr<IDirect3DSurface9> surface;
if (texture->GetSurfaceLevel(0, surface.GetAddressOf()) == D3D_OK)
device->StretchRect(backBuffer.Get(), nullptr, surface.Get(), nullptr, filtering);
}
}
static void setRenderTarget(IDirect3DTexture9* rtTexture) noexcept
{
if (!device)
return;
ComPtr<IDirect3DSurface9> surface;
if (rtTexture->GetSurfaceLevel(0, surface.GetAddressOf()) == D3D_OK)
device->SetRenderTarget(0, surface.Get());
}
class ShaderProgram {
public:
~ShaderProgram()
{
}
void use(float uniform, int location) const noexcept
{
device->SetPixelShader(pixelShader.Get());
const float params[4] = { uniform };
device->SetPixelShaderConstantF(location, params, 1);
}
void init(const BYTE* pixelShaderSrc) noexcept
{
if (initialized)
return;
initialized = true;
if (!device)
return;
device->CreatePixelShader(reinterpret_cast<const DWORD*>(pixelShaderSrc), pixelShader.GetAddressOf());
}
private:
ComPtr<IDirect3DPixelShader9> pixelShader;
bool initialized = false;
};
class BlurEffect {
public:
static void draw(ImDrawList* drawList, ImVec2 min, ImVec2 max, float alpha) noexcept
{
if (!device || !drawList)
return;
instance()._draw(drawList, min, max, alpha);
}
static void clearTextures() noexcept
{
if (instance().blurTexture1) {
instance().blurTexture1->Release();
instance().blurTexture1 = nullptr;
}
if (instance().blurTexture2) {
instance().blurTexture2->Release();
instance().blurTexture2 = nullptr;
}
}
private:
IDirect3DSurface9* rtBackup = nullptr;
IDirect3DTexture9* blurTexture1 = nullptr;
IDirect3DTexture9* blurTexture2 = nullptr;
ShaderProgram blurShaderX;
ShaderProgram blurShaderY;
static constexpr auto blurDownsample = 8;
BlurEffect() = default;
BlurEffect(const BlurEffect&) = delete;
~BlurEffect()
{
if (rtBackup)
rtBackup->Release();
if (blurTexture1)
blurTexture1->Release();
if (blurTexture2)
blurTexture2->Release();
}
static BlurEffect& instance() noexcept
{
static BlurEffect blurEffect;
return blurEffect;
}
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 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);
blurShaderY.init(blur_y);
}
void _begin() noexcept
{
device->GetRenderTarget(0, &rtBackup);
copyBackbufferToTexture(blurTexture1, D3DTEXF_LINEAR);
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
const D3DMATRIX projection{ {{
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
}} };
device->SetVertexShaderConstantF(0, &projection.m[0][0], 4);
}
void _firstPass() noexcept
{
blurShaderX.use(1.0f / (backbufferWidth / blurDownsample), 0);
setRenderTarget(blurTexture2);
}
void _secondPass() noexcept
{
blurShaderY.use(1.0f / (backbufferHeight / blurDownsample), 0);
setRenderTarget(blurTexture1);
}
void _end() noexcept
{
device->SetRenderTarget(0, rtBackup);
rtBackup->Release();
device->SetPixelShader(nullptr);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, true);
}
void _draw(ImDrawList* drawList, ImVec2 min, ImVec2 max, float alpha) noexcept
{
createTextures();
createShaders();
if (!blurTexture1 || !blurTexture2)
return;
drawList->AddCallback(&begin, nullptr);
for (int i = 0; i < 8; ++i) {
drawList->AddCallback(&firstPass, nullptr);
drawList->AddImage(reinterpret_cast<ImTextureID>(blurTexture1), { -1.0f, -1.0f }, { 1.0f, 1.0f });
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->AddImageRounded(reinterpret_cast<ImTextureID>(blurTexture1), min, max, { min.x / backbufferWidth, min.y / backbufferHeight }, { max.x / backbufferWidth, max.y / backbufferHeight }, IM_COL32(255, 255, 255, 255 * alpha), ImGui::GetStyle().WindowRounding);
}
};
void blur::set_device(IDirect3DDevice9* device) noexcept
{
::device = device;
}
void blur::clear_blur_textures() noexcept
{
BlurEffect::clearTextures();
}
void blur::device_reset() noexcept
{
BlurEffect::clearTextures();
}
void blur::new_frame() noexcept
{
const int width = ImGui::GetIO().DisplaySize.x;
const int height = ImGui::GetIO().DisplaySize.y;
if (backbufferWidth != static_cast<int>(width) || backbufferHeight != static_cast<int>(height)) {
BlurEffect::clearTextures();
backbufferWidth = static_cast<int>(width);
backbufferHeight = static_cast<int>(height);
}
}
void blur::add_blur(ImDrawList* drawList, ImVec2 min, ImVec2 max, float alpha) noexcept
{
BlurEffect::draw(drawList, min, max, alpha);
}
blur.h:
#pragma once
#include "../../dependencies/imgui/imgui.h"
struct ImDrawList;
struct IDirect3DDevice9;
namespace blur
{
extern void set_device(IDirect3DDevice9* device) noexcept;
extern void clear_blur_textures() noexcept;
extern void device_reset() noexcept;
extern void new_frame() noexcept;
extern void add_blur(ImDrawList* drawList, ImVec2 min, ImVec2 max, float alpha = 1.f) noexcept;
}
blur_x.h + blur_y.h:
#include <Windows.h>
const BYTE blur_x[ ] =
{
0, 2, 255, 255, 254, 255,
44, 0, 67, 84, 65, 66,
28, 0, 0, 0, 131, 0,
0, 0, 0, 2, 255, 255,
2, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
124, 0, 0, 0, 68, 0,
0, 0, 3, 0, 0, 0,
1, 0, 0, 0, 80, 0,
0, 0, 0, 0, 0, 0,
96, 0, 0, 0, 2, 0,
0, 0, 1, 0, 0, 0,
108, 0, 0, 0, 0, 0,
0, 0, 116, 101, 120, 83,
97, 109, 112, 108, 101, 114,
0, 171, 4, 0, 12, 0,
1, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0,
116, 101, 120, 101, 108, 87,
105, 100, 116, 104, 0, 171,
0, 0, 3, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 112, 115,
95, 50, 95, 48, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 49, 48,
46, 49, 0, 171, 81, 0,
0, 5, 1, 0, 15, 160,
20, 59, 177, 63, 24, 231,
161, 62, 198, 121, 104, 62,
236, 196, 78, 64, 81, 0,
0, 5, 2, 0, 15, 160,
220, 233, 143, 61, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 31, 0,
0, 2, 0, 0, 0, 128,
0, 0, 3, 176, 31, 0,
0, 2, 0, 0, 0, 144,
0, 8, 15, 160, 1, 0,
0, 2, 0, 0, 9, 128,
1, 0, 228, 160, 4, 0,
0, 4, 1, 0, 1, 128,
0, 0, 0, 160, 0, 0,
0, 128, 0, 0, 0, 176,
1, 0, 0, 2, 1, 0,
2, 128, 0, 0, 85, 176,
4, 0, 0, 4, 0, 0,
1, 128, 0, 0, 0, 160,
0, 0, 0, 129, 0, 0,
0, 176, 1, 0, 0, 2,
0, 0, 2, 128, 0, 0,
85, 176, 4, 0, 0, 4,
2, 0, 1, 128, 0, 0,
0, 160, 0, 0, 255, 129,
0, 0, 0, 176, 1, 0,
0, 2, 2, 0, 2, 128,
0, 0, 85, 176, 4, 0,
0, 4, 3, 0, 1, 128,
0, 0, 0, 160, 0, 0,
255, 128, 0, 0, 0, 176,
1, 0, 0, 2, 3, 0,
2, 128, 0, 0, 85, 176,
66, 0, 0, 3, 1, 0,
15, 128, 1, 0, 228, 128,
0, 8, 228, 160, 66, 0,
0, 3, 0, 0, 15, 128,
0, 0, 228, 128, 0, 8,
228, 160, 66, 0, 0, 3,
4, 0, 15, 128, 0, 0,
228, 176, 0, 8, 228, 160,
66, 0, 0, 3, 2, 0,
15, 128, 2, 0, 228, 128,
0, 8, 228, 160, 66, 0,
0, 3, 3, 0, 15, 128,
3, 0, 228, 128, 0, 8,
228, 160, 5, 0, 0, 3,
0, 0, 7, 128, 0, 0,
228, 128, 1, 0, 85, 160,
4, 0, 0, 4, 0, 0,
7, 128, 4, 0, 228, 128,
1, 0, 170, 160, 0, 0,
228, 128, 4, 0, 0, 4,
0, 0, 7, 128, 1, 0,
228, 128, 1, 0, 85, 160,
0, 0, 228, 128, 4, 0,
0, 4, 0, 0, 7, 128,
2, 0, 228, 128, 2, 0,
0, 160, 0, 0, 228, 128,
4, 0, 0, 4, 4, 0,
7, 128, 3, 0, 228, 128,
2, 0, 0, 160, 0, 0,
228, 128, 1, 0, 0, 2,
0, 8, 15, 128, 4, 0,
228, 128, 255, 255, 0, 0
};
#include <Windows.h>
const BYTE blur_y[ ] =
{
0, 2, 255, 255, 254, 255,
44, 0, 67, 84, 65, 66,
28, 0, 0, 0, 131, 0,
0, 0, 0, 2, 255, 255,
2, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
124, 0, 0, 0, 68, 0,
0, 0, 3, 0, 0, 0,
1, 0, 0, 0, 80, 0,
0, 0, 0, 0, 0, 0,
96, 0, 0, 0, 2, 0,
0, 0, 1, 0, 0, 0,
108, 0, 0, 0, 0, 0,
0, 0, 116, 101, 120, 83,
97, 109, 112, 108, 101, 114,
0, 171, 4, 0, 12, 0,
1, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0,
116, 101, 120, 101, 108, 72,
101, 105, 103, 104, 116, 0,
0, 0, 3, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 112, 115,
95, 50, 95, 48, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 49, 48,
46, 49, 0, 171, 81, 0,
0, 5, 1, 0, 15, 160,
20, 59, 177, 63, 24, 231,
161, 62, 198, 121, 104, 62,
236, 196, 78, 64, 81, 0,
0, 5, 2, 0, 15, 160,
220, 233, 143, 61, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 31, 0,
0, 2, 0, 0, 0, 128,
0, 0, 3, 176, 31, 0,
0, 2, 0, 0, 0, 144,
0, 8, 15, 160, 1, 0,
0, 2, 0, 0, 9, 128,
1, 0, 228, 160, 4, 0,
0, 4, 1, 0, 2, 128,
0, 0, 0, 160, 0, 0,
0, 128, 0, 0, 85, 176,
1, 0, 0, 2, 1, 0,
1, 128, 0, 0, 0, 176,
4, 0, 0, 4, 0, 0,
2, 128, 0, 0, 0, 160,
0, 0, 0, 129, 0, 0,
85, 176, 1, 0, 0, 2,
0, 0, 1, 128, 0, 0,
0, 176, 4, 0, 0, 4,
2, 0, 2, 128, 0, 0,
0, 160, 0, 0, 255, 129,
0, 0, 85, 176, 1, 0,
0, 2, 2, 0, 1, 128,
0, 0, 0, 176, 4, 0,
0, 4, 3, 0, 2, 128,
0, 0, 0, 160, 0, 0,
255, 128, 0, 0, 85, 176,
1, 0, 0, 2, 3, 0,
1, 128, 0, 0, 0, 176,
66, 0, 0, 3, 1, 0,
15, 128, 1, 0, 228, 128,
0, 8, 228, 160, 66, 0,
0, 3, 0, 0, 15, 128,
0, 0, 228, 128, 0, 8,
228, 160, 66, 0, 0, 3,
4, 0, 15, 128, 0, 0,
228, 176, 0, 8, 228, 160,
66, 0, 0, 3, 2, 0,
15, 128, 2, 0, 228, 128,
0, 8, 228, 160, 66, 0,
0, 3, 3, 0, 15, 128,
3, 0, 228, 128, 0, 8,
228, 160, 5, 0, 0, 3,
0, 0, 7, 128, 0, 0,
228, 128, 1, 0, 85, 160,
4, 0, 0, 4, 0, 0,
7, 128, 4, 0, 228, 128,
1, 0, 170, 160, 0, 0,
228, 128, 4, 0, 0, 4,
0, 0, 7, 128, 1, 0,
228, 128, 1, 0, 85, 160,
0, 0, 228, 128, 4, 0,
0, 4, 0, 0, 7, 128,
2, 0, 228, 128, 2, 0,
0, 160, 0, 0, 228, 128,
4, 0, 0, 4, 4, 0,
7, 128, 3, 0, 228, 128,
2, 0, 0, 160, 0, 0,
228, 128, 1, 0, 0, 2,
0, 8, 15, 128, 4, 0,
228, 128, 255, 255, 0, 0
};
const BYTE default_vs[ ] =
{
0, 2, 254, 255, 254, 255,
34, 0, 67, 84, 65, 66,
28, 0, 0, 0, 91, 0,
0, 0, 0, 2, 254, 255,
1, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
84, 0, 0, 0, 48, 0,
0, 0, 2, 0, 0, 0,
4, 0, 0, 0, 68, 0,
0, 0, 0, 0, 0, 0,
112, 114, 111, 106, 101, 99,
116, 105, 111, 110, 77, 97,
116, 114, 105, 120, 0, 171,
171, 171, 3, 0, 3, 0,
4, 0, 4, 0, 1, 0,
0, 0, 0, 0, 0, 0,
118, 115, 95, 50, 95, 48,
0, 77, 105, 99, 114, 111,
115, 111, 102, 116, 32, 40,
82, 41, 32, 72, 76, 83,
76, 32, 83, 104, 97, 100,
101, 114, 32, 67, 111, 109,
112, 105, 108, 101, 114, 32,
49, 48, 46, 49, 0, 171,
31, 0, 0, 2, 0, 0,
0, 128, 0, 0, 15, 144,
31, 0, 0, 2, 10, 0,
0, 128, 1, 0, 15, 144,
31, 0, 0, 2, 5, 0,
0, 128, 2, 0, 15, 144,
5, 0, 0, 3, 0, 0,
15, 128, 0, 0, 85, 144,
1, 0, 228, 160, 4, 0,
0, 4, 0, 0, 15, 128,
0, 0, 228, 160, 0, 0,
0, 144, 0, 0, 228, 128,
2, 0, 0, 3, 0, 0,
15, 192, 0, 0, 228, 128,
3, 0, 228, 160, 1, 0,
0, 2, 0, 0, 15, 208,
1, 0, 228, 144, 1, 0,
0, 2, 0, 0, 3, 224,
2, 0, 228, 144, 255, 255,
0, 0
};