OMSetRenderTargets()

本文深入解析了ID3D11DeviceContext::OMSetRenderTargets()函数,该函数用于在Direct3D 11管线的输出合并器阶段绑定渲染目标和深度模板缓冲区.通过此函数,可以有效地控制渲染流程,实现复杂场景的高效绘制.
ID3D11DeviceContext::OMSetRenderTargets() 
* 绑定一个或更多渲染目标和深度模板缓冲区到管线的输出合并器阶段 
* @param NumViews            将要绑定的渲染目标的数量  
* @param ppRenderTargetViews 将要绑定的渲染目标视图数组中的第一个元素的指针 
* @param pDepthStencilView   将要绑定到管线的深度/模板视图 

为后台缓冲区和深度缓冲区创建视图后,就可以将些视图绑定到管线的输出合并器阶段(output merger stage),使些资源成为管线的渲染目标和深度/模板缓冲区,使用OMSetRenderTargets函数。

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);//高斯模糊 } 怎么使用这个代码
06-16
// Main code int openui() { // Make process DPI aware and obtain main monitor scale ImGui_ImplWin32_EnableDpiAwareness(); float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY)); // Create application window WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr }; ::RegisterClassExW(&wc); HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, (int)(1280 * main_scale), (int)(800 * main_scale), nullptr, nullptr, wc.hInstance, nullptr); // Initialize Direct3D if (!CreateDeviceD3D(hwnd)) { CleanupDeviceD3D(); ::UnregisterClassW(wc.lpszClassName, wc.hInstance); return 1; } // Show the window ::ShowWindow(hwnd, SW_SHOWDEFAULT); ::UpdateWindow(hwnd); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsLight(); // Setup scaling ImGuiStyle& style = ImGui::GetStyle(); style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) // Setup Platform/Renderer backends ImGui_ImplWin32_Init(hwnd); ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); // Our state bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop bool done = false; while (!done) { // Poll and handle messages (inputs, window resize, etc.) // See the WndProc() function below for our to dispatch events to the Win32 backend. MSG msg; while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); if (msg.message == WM_QUIT) done = true; } if (done) break; // Handle window being minimized or screen locked if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED) { ::Sleep(10); continue; } g_SwapChainOccluded = false; // Handle window resize (we don't resize directly in the WM_SIZE handler) if (g_ResizeWidth != 0 && g_ResizeHeight != 0) { CleanupRenderTarget(); g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0); g_ResizeWidth = g_ResizeHeight = 0; CreateRenderTarget(); } // Start the Dear ImGui frame ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). if (show_demo_window) ImGui::ShowDemoWindow(&show_demo_window); // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. { static float f = 0.0f; static int counter = 0; ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state ImGui::Checkbox("Another Window", &show_another_window); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); ImGui::End(); } // 3. Show another simple window. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) ImGui::Text("Hello from another window!"); if (ImGui::Button("Close Me")) show_another_window = false; ImGui::End(); } // Rendering ImGui::Render(); const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr); g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); // Present HRESULT hr = g_pSwapChain->Present(1, 0); // Present with vsync //HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED); } // Cleanup ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); CleanupDeviceD3D(); ::DestroyWindow(hwnd); ::UnregisterClassW(wc.lpszClassName, wc.hInstance); return 0; }已经创建了一个原生窗口怎么在 case WM_PAINT: {完善上面这个窗口别闪退啊,也不要重复初始化
最新发布
12-13
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值