递归火山软件开发平台
标题:
尝试了很多次,无法封装D3D 截图,希望分享一下,谢谢!
[打印本页]
作者:
urenai
时间:
3 天前
标题:
尝试了很多次,无法封装D3D 截图,希望分享一下,谢谢!
大致分为2部分,
1、获取数据。
2、数据还原成bmp图片
不管怎么优化,普通截图速度都不可能降到50毫秒以下。
作者:
fengshangren
时间:
3 天前
D3D截图我一直不太清楚是什么,有什么优势,和DXGI有什么区别,哪个快
作者:
urenai
时间:
3 天前
fengshangren 发表于 2025-1-15 22:30
D3D截图我一直不太清楚是什么,有什么优势,和DXGI有什么区别,哪个快
兄弟分享一下 DXGI
作者:
uuyyhhjj
时间:
前天 20:46
Desktop Duplication API 我用AI试了下,始终是黑屏,没接触过D3D,表面上看不出来哪个环节出问题了
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h> // 仅用于异常处理,不用于智能指针
#include <iostream>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } }
// 窗口尺寸
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
// 全局变量
ID3D11Device* g_pD3DDevice = nullptr;
ID3D11DeviceContext* g_pD3DDeviceContext = nullptr;
IDXGIOutputDuplication* g_pDeskDupl = nullptr;
ID3D11Texture2D* g_pAcquiredDesktopImage = nullptr;
ID3D11Texture2D* g_pRenderTargetTexture = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
// 函数声明
bool InitializeDirect3D(HWND hwnd);
bool InitializeDesktopDuplication();
void CaptureFrame();
void RenderFrame();
void Cleanup();
// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
// 主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, nullptr, nullptr, nullptr, nullptr, L"ScreenCaptureClass", nullptr };
RegisterClassEx(&wc);
// 创建窗口
HWND hwnd = CreateWindow(wc.lpszClassName, L"DirectX Desktop Duplication API Example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, nullptr, nullptr, hInstance, nullptr);
if (!hwnd)
{
std::cerr << "Failed to create window!" << std::endl;
return -1;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 初始化 Direct3D
if (!InitializeDirect3D(hwnd))
{
std::cerr << "Failed to initialize Direct3D!" << std::endl;
Cleanup();
return -1;
}
// 初始化桌面复制
if (!InitializeDesktopDuplication())
{
std::cerr << "Failed to initialize desktop duplication!" << std::endl;
Cleanup();
return -1;
}
// 主消息循环
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
CaptureFrame();
RenderFrame();
}
}
Cleanup();
return static_cast<int>(msg.wParam);
}
// 初始化 Direct3D
bool InitializeDirect3D(HWND hwnd)
{
// 创建设备和交换链
DXGI_SWAP_CHAIN_DESC scd = {};
scd.BufferCount = 1;
scd.BufferDesc.Width = WINDOW_WIDTH;
scd.BufferDesc.Height = WINDOW_HEIGHT;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.RefreshRate.Numerator = 60;
scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hwnd;
scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 0;
scd.Windowed = TRUE;
HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &scd, &g_pSwapChain, &g_pD3DDevice, nullptr, &g_pD3DDeviceContext);
if (FAILED(hr))
{
std::cerr << "Failed to create device and swap chain!" << std::endl;
return false;
}
// 创建渲染目标视图
ID3D11Texture2D* pBackBuffer = nullptr;
hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
if (FAILED(hr))
{
std::cerr << "Failed to get back buffer!" << std::endl;
return false;
}
hr = g_pD3DDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
SAFE_RELEASE(pBackBuffer);
if (FAILED(hr))
{
std::cerr << "Failed to create render target view!" << std::endl;
return false;
}
g_pD3DDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
// 设置视口
D3D11_VIEWPORT vp = {};
vp.Width = static_cast<float>(WINDOW_WIDTH);
vp.Height = static_cast<float>(WINDOW_HEIGHT);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pD3DDeviceContext->RSSetViewports(1, &vp);
return true;
}
// 初始化桌面复制
bool InitializeDesktopDuplication()
{
// 获取 DXGI 设备
IDXGIDevice* pDxgiDevice = nullptr;
HRESULT hr = g_pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice));
if (FAILED(hr))
{
std::cerr << "Failed to get DXGI device!" << std::endl;
return false;
}
// 获取 DXGI 适配器
IDXGIAdapter* pDxgiAdapter = nullptr;
hr = pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter));
SAFE_RELEASE(pDxgiDevice);
if (FAILED(hr))
{
std::cerr << "Failed to get DXGI adapter!" << std::endl;
return false;
}
// 获取 DXGI 输出
IDXGIOutput* pDxgiOutput = nullptr;
hr = pDxgiAdapter->EnumOutputs(0, &pDxgiOutput);
SAFE_RELEASE(pDxgiAdapter);
if (FAILED(hr))
{
std::cerr << "Failed to get DXGI output!" << std::endl;
return false;
}
// 获取 DXGI 输出1
IDXGIOutput1* pDxgiOutput1 = nullptr;
hr = pDxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&pDxgiOutput1));
SAFE_RELEASE(pDxgiOutput);
if (FAILED(hr))
{
std::cerr << "Failed to get DXGI output1!" << std::endl;
return false;
}
// 创建桌面复制接口
hr = pDxgiOutput1->DuplicateOutput(g_pD3DDevice, &g_pDeskDupl);
SAFE_RELEASE(pDxgiOutput1);
if (FAILED(hr))
{
std::cerr << "Failed to create desktop duplication interface!" << std::endl;
return false;
}
return true;
}
// 捕获桌面帧
void CaptureFrame()
{
DXGI_OUTDUPL_FRAME_INFO frameInfo;
IDXGIResource* pDesktopResource = nullptr;
// 获取桌面帧
HRESULT hr = g_pDeskDupl->AcquireNextFrame(0, &frameInfo, &pDesktopResource);
if (FAILED(hr))
{
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
return; // 没有新的帧
}
std::cerr << "Failed to acquire next frame!" << std::endl;
return;
}
// 获取桌面纹理
hr = pDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&g_pAcquiredDesktopImage));
SAFE_RELEASE(pDesktopResource);
if (FAILED(hr))
{
std::cerr << "Failed to get desktop texture!" << std::endl;
g_pDeskDupl->ReleaseFrame();
return;
}
// 释放帧
g_pDeskDupl->ReleaseFrame();
}
// 渲染帧
void RenderFrame()
{
if (!g_pAcquiredDesktopImage)
{
return;
}
// 创建渲染目标纹理
D3D11_TEXTURE2D_DESC desc;
g_pAcquiredDesktopImage->GetDesc(&desc);
if (!g_pRenderTargetTexture)
{
desc.Width = WINDOW_WIDTH;
desc.Height = WINDOW_HEIGHT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
desc.MiscFlags = 0;
HRESULT hr = g_pD3DDevice->CreateTexture2D(&desc, nullptr, &g_pRenderTargetTexture);
if (FAILED(hr))
{
std::cerr << "Failed to create render target texture!" << std::endl;
return;
}
}
// 将桌面图像复制到渲染目标纹理
g_pD3DDeviceContext->CopyResource(g_pRenderTargetTexture, g_pAcquiredDesktopImage);
// 清除渲染目标
float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
g_pD3DDeviceContext->ClearRenderTargetView(g_pRenderTargetView, clearColor);
// 渲染纹理到窗口
g_pD3DDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);
g_pD3DDeviceContext->Draw(4, 0);
// 呈现交换链
g_pSwapChain->Present(0, 0);
// 释放桌面图像
SAFE_RELEASE(g_pAcquiredDesktopImage);
}
// 清理资源
void Cleanup()
{
SAFE_RELEASE(g_pRenderTargetTexture);
SAFE_RELEASE(g_pRenderTargetView);
SAFE_RELEASE(g_pSwapChain);
SAFE_RELEASE(g_pDeskDupl);
SAFE_RELEASE(g_pD3DDeviceContext);
SAFE_RELEASE(g_pD3DDevice);
}
复制代码
欢迎光临 递归火山软件开发平台 (https://bbs.voldp.com/)
Powered by Discuz! X3.4