|
板凳
发表于 2025-4-24 10:51:40
|
只看该作者
江西省九江市
D2D 窗口渲染器 和 D3D使用D2D设备上下文 是一样的绘制图片方法
从文件加载图像,并将其转换为 Direct2D 支持的像素格式(GUID_WICPixelFormat32bppPBGRA)
这是我之前写的例子,转换为易语言太麻烦了,你将就着看
效果图
TestWindow.cpp
[C++] 纯文本查看 复制代码 //
// Created by konun on 2025/4/2.
//
#include <Dui/TestWindow.hpp>
#include <Dui/Image.hpp>
//D2D效果器
#include <Initguid.h>
#include <d2d1effectauthor.h>
#include <d2d1effecthelpers.h>
//D3D D2D
#include <Dui/d2d_factory.hpp>
//STL
#include <iostream>
#include <filesystem>
#include <wincodec.h>
//ATL
#define ATL_DLL
#include <atlbase.h> // 基本 ATL 功能
#include <atlconv.h>
namespace TestWindow
{
HINSTANCE hInstance;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//InitializeGraphics(hwnd);
InitializeGraphicsD3D(hwnd);
ValidateRect(hwnd, nullptr); // 避免重复触发 WM_PAINT
break;
case WM_SETCURSOR:
break;
case WM_PAINT:
//RenderScene();
RenderD3D();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default: ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
ATOM RegisterWindowClass()
{
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"Direct2DWindowClass";
wc.hCursor = LoadCursor(nullptr, IDC_ARROW); // 使用系统箭头光标
return RegisterClass(&wc);
}
D2D1_SIZE_U WindowSize= D2D1::SizeU(1000,700);
void create()
{
hInstance = GetModuleHandle(nullptr);
RegisterWindowClass();
// 创建窗口
HWND hwnd = CreateWindow(
L"Direct2DWindowClass", L"Direct2D Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, WindowSize.width, WindowSize.height,
nullptr, nullptr, hInstance, nullptr
);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
TestWindow::MessageLop();
dui_img_release();
}
using namespace D2D1;
ID2D1SolidColorBrush* pRedBrush;
ID2D1SolidColorBrush* pYellowBrush;
ID2D1SolidColorBrush* pGreenBrush;
ID2D1BitmapBrush* pBitmapBrush;
IWICBitmap* pWicBitmap1 = nullptr;
ID2D1Bitmap* pBitmap = nullptr; // 用于加载位图
D2D1_SIZE_U sizeU = SizeU(500, 300);
HRESULT InitializeGraphicsD3D(HWND hwnd)
{
CoInitialize(nullptr);
HRESULT hr = S_OK;
hr=d3d_InitializeGraphics(hwnd);
if (FAILED(hr)) {
std::cerr << "d3d Initialize Graphics Failed: 0x" << std::hex << hr << std::endl;
}
pDeviceContext->CreateSolidColorBrush(ColorF(ColorF::Red), &pRedBrush);
pDeviceContext->CreateSolidColorBrush(ColorF(ColorF::Yellow), &pYellowBrush);
pDeviceContext->CreateSolidColorBrush(ColorF(ColorF::Green), &pGreenBrush);
dui_img_initialize();
hr=dui_img_WicBitmap_CreateFromFile(L"BingWallpaper.jpg", &pWicBitmap1);
if (FAILED(hr)) {
std::cerr << "加载图片失败: 0x" << std::hex << hr << std::endl;
return hr;
}
IWICBitmap* pWicBitmap2 = nullptr;
hr = dui_img_ResizeWicBitmapInPlace(&pWicBitmap1, sizeU.width, sizeU.height);
if (FAILED(hr)) {
std::cerr << "缩放图片失败: 0x" << std::hex << hr << std::endl;
return hr;
}
hr=pDeviceContext->CreateBitmapFromWicBitmap(pWicBitmap1, &pBitmap);
return hr;
}
void RenderD3D()
{
// 定义矩形和圆形的位置和大小
D2D1_POINT_2F pointF = Point2F(10, 320);
D2D1_SIZE_F sizeF = SizeF(500,300);
D2D1_RECT_F rectF = RectF(pointF.x, pointF.y, pointF.x + sizeF.width, pointF.y + sizeF.height);
//模糊位图
D2D1_POINT_2F point2 = Point2F(10, 10);
D2D1_RECT_F rect2 = RectF(10,10,500,300);
D2D1_RECT_F rect3 = RectF(10,10,100,300);
pDeviceContext->BeginDraw();
//pDeviceContext->FillRectangle(rectF,pYellowBrush);
ID2D1Effect* gaussianBlurEffect;
pDeviceContext->CreateEffect(CLSID_D2D1GaussianBlur, &gaussianBlurEffect);
// 2. 设置模糊参数
gaussianBlurEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, 20.0f); // 调整模糊程度
gaussianBlurEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, D2D1_BORDER_MODE_HARD);
// 3. 获取背景内容作为输入
gaussianBlurEffect->SetInput(0, pBitmap);
ID2D1Image* bmp;
// 4. 绘制模糊效果
gaussianBlurEffect->GetOutput(&bmp);
pDeviceContext->DrawBitmap(pBitmap,rectF);
pDeviceContext->DrawImage(bmp,&point2,&rect2);
// 5. 添加亚克力色调层 (RGBA: 0.8透明度)
ID2D1SolidColorBrush* pAcrylicBrush = nullptr;
pDeviceContext->CreateSolidColorBrush(
D2D1::ColorF(0.01, 0.02, 0.02, 0.8f),
&pAcrylicBrush);
pDeviceContext->FillRectangle(rect3, pAcrylicBrush); // acrylicBrush是带有透明度的颜色
pDeviceContext->EndDraw();
pSwapChain->Present(1, 0);
}
void MessageLop()
{
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Image.cpp
[C++] 纯文本查看 复制代码 #include "Dui/Image.hpp"
#include <wincodec.h>
#pragma comment(lib, "windowscodecs.lib")
ID2D1HwndRenderTarget* pRenderTarget = nullptr;
IWICImagingFactory* pWICFactory = nullptr;
HRESULT dui_img_initialize()
{
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
reinterpret_cast<LPVOID*>(&pWICFactory)
);
return SUCCEEDED(hr) ? S_OK : hr;
}
HRESULT dui_img_release()
{
if (pWICFactory) pWICFactory->Release();
return S_OK;
}
HRESULT dui_img_WicBitmap_CreateFromFile(LPCWSTR fileName, IWICBitmap** ppWicBitmap)
{
if (!ppWicBitmap || !pWICFactory) return E_INVALIDARG;
IWICBitmapDecoder* pDecoder = nullptr;
IWICBitmapFrameDecode* pSource = nullptr;
IWICFormatConverter* pConverter = nullptr;
HRESULT hr = pWICFactory->CreateDecoderFromFilename(
fileName, nullptr, GENERIC_READ,
WICDecodeMetadataCacheOnLoad, &pDecoder
);
if (SUCCEEDED(hr)) hr = pDecoder->GetFrame(0, &pSource);
if (SUCCEEDED(hr)) hr = pWICFactory->CreateFormatConverter(&pConverter);
if (SUCCEEDED(hr))
hr = pConverter->Initialize(
pSource, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom
);
if (SUCCEEDED(hr))
hr = pWICFactory->CreateBitmapFromSource(
pConverter, WICBitmapCacheOnLoad, ppWicBitmap
);
if (pConverter) pConverter->Release();
if (pSource) pSource->Release();
if (pDecoder) pDecoder->Release();
return hr;
}
HRESULT dui_img_CreateResizedBitmap(IWICBitmap* srcWicBitmap, UINT newWidth, UINT newHeight, IWICBitmap** outWicBitmap)
{
if (!srcWicBitmap || !outWicBitmap || !pWICFactory) return E_INVALIDARG;
IWICBitmapScaler* pScaler = nullptr;
IWICFormatConverter* pConverter = nullptr;
HRESULT hr = pWICFactory->CreateBitmapScaler(&pScaler);
if (SUCCEEDED(hr))
hr = pScaler->Initialize(
srcWicBitmap, newWidth, newHeight,
WICBitmapInterpolationModeFant
);
if (SUCCEEDED(hr)) hr = pWICFactory->CreateFormatConverter(&pConverter);
WICPixelFormatGUID srcFormat;
srcWicBitmap->GetPixelFormat(&srcFormat);
if (SUCCEEDED(hr))
hr = pConverter->Initialize(
pScaler, srcFormat,
WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom
);
if (SUCCEEDED(hr))
hr = pWICFactory->CreateBitmapFromSource(
pConverter, WICBitmapCacheOnLoad, outWicBitmap
);
if (pScaler) pScaler->Release();
if (pConverter) pConverter->Release();
return hr;
}
HRESULT dui_img_ResizeWicBitmapInPlace(IWICBitmap** ppWicBitmap, UINT newWidth, UINT newHeight)
{
if (!ppWicBitmap || !*ppWicBitmap)
return E_INVALIDARG;
IWICBitmap* pOriginal = *ppWicBitmap;
IWICBitmap* pResized = nullptr;
// 创建缩放后的新位图
HRESULT hr = dui_img_CreateResizedBitmap(pOriginal, newWidth, newHeight, &pResized);
if (SUCCEEDED(hr))
{
// 释放原始位图并替换为新位图
pOriginal->Release();
*ppWicBitmap = pResized;
}
return hr;
}
d2d_factory.cpp
[C++] 纯文本查看 复制代码 //
// Created by konun on 2025/4/3.
//
#include <Dui\d2d_factory.hpp>
#include <d2d1_1.h>
#include <dxgi.h>
#include <d3d11.h>
#include <dxgi1_2.h> // IDXGIFactory2 等扩展接口
#include <iostream>
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
ID3D11Device* pD3DDevice = nullptr;
ID3D11DeviceContext* pD3DContext = nullptr;
IDXGIFactory2* pDxgiFactory = nullptr;
IDXGISwapChain1* pSwapChain = nullptr; // 修改为 IDXGISwapChain1
ID2D1Factory1* pFactory = nullptr; // 使用 ID2D1Factory1 而不是 ID2D1Factory
ID2D1Device* pD2DDevice = nullptr;
ID2D1DeviceContext* pDeviceContext = nullptr;
HRESULT D3D11_CreateDevice()
{
D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 };
D3D_FEATURE_LEVEL supportedFeatureLevel;
HRESULT hr = D3D11CreateDevice(
nullptr, // 默认适配器
D3D_DRIVER_TYPE_HARDWARE, // 使用硬件加速
nullptr, // 不适用软件驱动
D3D11_CREATE_DEVICE_BGRA_SUPPORT, // 必须支持 BGRA
featureLevels, // 特性级别数组
ARRAYSIZE(featureLevels), // 数组大小
D3D11_SDK_VERSION, // SDK 版本
&pD3DDevice, // 输出的 D3D 设备
&supportedFeatureLevel, // 支持的特性级别
&pD3DContext); // 设备上下文
return hr;
}
HRESULT CreateSwapChainForHwnd(HWND hwnd)
{
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
RECT clientRect;
GetClientRect(hwnd, &clientRect);
swapChainDesc.Width = clientRect.right-clientRect.left;
swapChainDesc.Height =clientRect.bottom-clientRect.top;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
return pDxgiFactory->CreateSwapChainForHwnd(
pD3DDevice,
hwnd,
&swapChainDesc,
nullptr,
nullptr,
&pSwapChain);
}
HRESULT D2D1_CreateFactory()
{
return D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory1),
reinterpret_cast<void**>(&pFactory));
}
HRESULT d3d_InitializeGraphics(HWND hwnd)
{
HRESULT hr = S_OK;
// 1. 创建 D3D 设备
hr = D3D11_CreateDevice();
if (FAILED(hr)) {
std::cerr << "Failed to create D3D11 device: 0x" << std::hex << hr << std::endl;
return hr;
}
// 2. 获取 DXGI 设备
IDXGIDevice* pDxgiDevice = nullptr;
hr = pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice));
if (FAILED(hr)) {
std::cerr << "Failed to get DXGI device: 0x" << std::hex << hr << std::endl;
return hr;
}
// 3. 获取适配器
IDXGIAdapter* pAdapter = nullptr;
hr = pDxgiDevice->GetAdapter(&pAdapter);
if (FAILED(hr)) {
std::cerr << "Failed to get adapter: 0x" << std::hex << hr << std::endl;
return hr;
}
// 4. 获取 DXGI 工厂
hr = pAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&pDxgiFactory));
if (FAILED(hr)) {
std::cerr << "Failed to get DXGI factory: 0x" << std::hex << hr << std::endl;
return hr;
}
// 5. 创建交换链
hr = CreateSwapChainForHwnd(hwnd);
if (FAILED(hr)) {
std::cerr << "Failed to create swap chain: 0x" << std::hex << hr << std::endl;
return hr;
}
// 6. 创建 D2D 工厂
hr = D2D1_CreateFactory();
if (FAILED(hr)) {
std::cerr << "Failed to create D2D factory: 0x" << std::hex << hr << std::endl;
return hr;
}
// 7. 创建 D2D 设备
hr = pFactory->CreateDevice(pDxgiDevice, &pD2DDevice);
if (FAILED(hr)) {
std::cerr << "Failed to create D2D device: 0x" << std::hex << hr << std::endl;
return hr;
}
// 8. 创建 D2D 设备上下文
hr = pD2DDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&pDeviceContext);
if (FAILED(hr)) {
std::cerr << "Failed to create D2D device context: 0x" << std::hex << hr << std::endl;
}
// 获取交换链的后缓冲区
IDXGISurface* pBackBuffer = nullptr;
pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
// 创建位图属性
D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)
);
// 创建位图作为渲染目标
ID2D1Bitmap1* pTargetBitmap = nullptr;
hr = pDeviceContext->CreateBitmapFromDxgiSurface(
pBackBuffer,
&bitmapProperties,
&pTargetBitmap
);
// 设置渲染目标
pDeviceContext->SetTarget(pTargetBitmap);
pTargetBitmap->Release();
pBackBuffer->Release();
return hr;
}
|
|