LoginSignup
2
4

More than 1 year has passed since last update.

DirectX12使用時にウィンドウを透過させる

Last updated at Posted at 2022-08-06

はじめに

DirectX12を使っているときにウィンドウの背景を透過させようとしたのですが,
情報が少なすぎて苦しんだので記録を残します.

筆者はプログラミング初心者なので,間違ったことを言うかもしれません.
間違いがあれば指摘していただけると幸いです.

問題

なぜかSetLayeredWindowAttributesでは透過させられず,
UpdateLayeredWindowレイヤード ウィンドウを定義するサーフェスの DC へのハンドルというものが分からなかったので試すことが出来ませんでした...

ID3D12GraphicsCommandList::ClearRenderTargetViewでアルファ値を0に設定したものを併用してもダメでした.

解決法

DirectCompositionを使用することで解決できました.
これを使用することで,諸々の描画結果を全て合成したものを描画できるようになるようです.

以下が関係ありそうな部分の疑似コード?です.

main.cpp
// スワップチェインの初期化
ComPtr<IDXGISwapChain3> m_swapChain;

DXGI_SWAP_CHAIN_DESC1 desc = {};
desc.Width = m_windowWidth;
desc.Height = m_windowHeight;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Stereo = false;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2;
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

ComPtr<IDXGISwapChain1> tmpSwapChain;

auto hr = m_dxgiFactory->CreateSwapChainForComposition(
		m_commandQueue.Get(),
		&desc,
		nullptr,
		tmpSwapChain.GetAddressOf()
	);

if (FAILED(hr))
{
    return false;
}

hr = tmpSwapChain.As(&m_swapChain);

if (FAILED(hr))
{
    return false;
}
main.cpp
// 以下をインクルード
#include<dcomp.h>
#pragma comment(lib, "dcomp")

// DirectCompositionの初期化
ComPtr<IDCompositionDevice> m_dcompDevice;
ComPtr<IDCompositionTarget> m_dcompTarget;
ComPtr<IDCompositionVisual> m_dcompVisual;

auto hr = DCompositionCreateDevice(nullptr,
        IID_PPV_ARGS(&m_dcompDevice));

if (FAILED(hr))
{
    return false;
}

hr = m_dcompDevice->CreateTargetForHwnd(
    m_hwnd,
    true,
    &m_dcompTarget
);
if (FAILED(hr))
{
    return false;
}

hr = m_dcompDevice->CreateVisual(&m_dcompVisual);

if (FAILED(hr))
{
    return false;
}

hr = m_dcompVisual->SetContent(m_swapChain.Get());

if (FAILED(hr))
{
    return false;
}

hr = m_dcompTarget->SetRoot(m_dcompVisual.Get());

if (FAILED(hr))
{
    return false;
}

hr = m_dcompDevice->Commit();

if (FAILED(hr))
{
    return false;
}

レンダーターゲット生成については平時と特に変わりませんが,
D3D12_RENDER_TARGET_VIEW_DESC を使用する場合は フォーマット
スワップチェインのものと揃える ことを忘れないでください.

main.cpp
// PSOの初期化
// ここでもフォーマットに気を付けてください
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {};

D3D12_RENDER_TARGET_BLEND_DESC renderTargetBlendDesc = {};
renderTargetBlendDesc.BlendEnable = TRUE;
renderTargetBlendDesc.LogicOpEnable = FALSE;
renderTargetBlendDesc.SrcBlend = D3D12_BLEND_ONE;
renderTargetBlendDesc.DestBlend = D3D12_BLEND_ZERO;
renderTargetBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
renderTargetBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
renderTargetBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
renderTargetBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_MIN;
renderTargetBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
renderTargetBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;

desc.BlendState.RenderTarget[0].BlendEnable = TRUE;
desc.BlendState.AlphaToCoverageEnable = TRUE;
desc.BlendState.IndependentBlendEnable = FALSE;
desc.BlendState.RenderTarget[0] = renderTargetBlendDesc;

desc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM;

// 以下省略

これで,レンダーターゲットのクリア時に

main.cpp
const float clearColor[4] = {};

を渡すと...
スクリーンショット (427).png

無事透過させることができました!!!!

あとがき

拙い文章だったかもしれませんが,ここまでお読みいただきありがとうございました.
次回はボーンアニメーションの予定です.

それでは良きDirectX12ライフを.アデュー

P.S. 現在,結果をhrに代入するかSUCCEEDED/FAILEDに直接入れるか滅茶苦茶迷っています.

参考資料

https://github.com/PJayB/DirectCompositionDirectX12Sample
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2014/june/windows-with-c-high-performance-window-layering-using-the-windows-composition-engine

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4