alpha 混合无法正常工作
alpha blending is not working as it supposed to be
我创建了一个新的 DirectX 项目并渲染了 2 个颜色组件,现在当我从着色器传递透明度时它没有改变任何东西,我是 c++ 和 DirectX 的新手,我使用了来自 [=39= 的标准模板] 创建项目
项目link:https://github.com/AbhishekSharma-SEG/TestAlphaBlending
混合状态
D3D11_BLEND_DESC blendDesc;
blendDesc.RenderTarget[0].BlendEnable = true;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_COLOR;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;;
blendDesc.IndependentBlendEnable = false;
blendDesc.AlphaToCoverageEnable = false;
auto hr = m_d3dDevice->CreateBlendState(&blendDesc, &AlphaEnableBlendingState);
if (SUCCEEDED(hr))
{
blendDesc.RenderTarget[0].BlendEnable = false;
m_d3dDevice->CreateBlendState(&blendDesc, &AlphaDisableBlendingState);
TurnOnAlphaBlending();
}
}
void DX::DeviceResources::TurnOnAlphaBlending()
{
float input[4] = { 0,0,0,0 };
m_d3dContext->OMSetBlendState(AlphaEnableBlendingState, input, 1);
}
void DX::DeviceResources::TurnOffAlphaBlending()
{
float input[4] = { 0,0,0,0 };
m_d3dContext->OMSetBlendState(AlphaDisableBlendingState, input, 1);
}
交换链描述
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window.
swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Microsoft Store apps must use _FLIP_ SwapEffects.
swapChainDesc.Flags = 0;
swapChainDesc.Scaling = scaling;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
着色器
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 0.2f);
}
输出
我找不到问题所在,几个教程和网站只讲述了如何设置混合状态,我尝试了他们告诉我应用的大部分设置,但它不起作用我也不知道为什么黄色组件应该在后面,因为首先出现对黄色组件的渲染调用,但它打印在红色组件上方,如果有人可以提供帮助,请感谢
alpha 模式忽略后的新输出并按照直线设置混合模式
编辑:已修复
所以在一些挖掘之后,我发现我没有使用深度模板状态,它在使用它解决后导致了这个问题,显然感谢@chukWalbourn 的建议,我能够设置混合的写入配置现在它工作得很好这里是帮助它的变化
//Describe our Depth/Stencil Buffer
CD3D11_DEPTH_STENCIL_DESC depthStencilStateDesc;
depthStencilStateDesc.DepthEnable = false;
depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilStateDesc.StencilEnable = true;
depthStencilStateDesc.StencilReadMask = 0xFF;
depthStencilStateDesc.StencilWriteMask = 0xFF;
depthStencilStateDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilStateDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilStateDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilStateDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilState(
&depthStencilStateDesc,
&m_d3dDepthStencilState
)
);
m_d3dContext->OMSetDepthStencilState(m_d3dDepthStencilState.Get(), 1);
当将 DXGI swap-chain alpha 模式用作 Direct3D 渲染目标时,UWP 应设置为 DXGI_ALPHA_MODE_IGNORE
或 Win32 应设置为 DXGI_ALPHA_MODE_UNSPECIFIED
。这仅适用于某些 Direct2D / DirectComposition-related 场景。
对于straight-alpha,使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
对于预乘 alpha 使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
'additive' 混合使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
You may want to take a look at DirectX Tool Kit.
所以在一些挖掘之后,我发现我没有使用深度模板状态,它在使用它后解决了这个问题,显然感谢@chukWalbourn 的建议,我能够设置混合的写入配置现在它完全正常了这里是帮助它的变化
//Describe our Depth/Stencil Buffer
CD3D11_DEPTH_STENCIL_DESC depthStencilStateDesc;
depthStencilStateDesc.DepthEnable = false;
depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilStateDesc.StencilEnable = true;
depthStencilStateDesc.StencilReadMask = 0xFF;
depthStencilStateDesc.StencilWriteMask = 0xFF;
depthStencilStateDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilStateDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilStateDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilStateDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilState(
&depthStencilStateDesc,
&m_d3dDepthStencilState
)
);
m_d3dContext->OMSetDepthStencilState(m_d3dDepthStencilState.Get(), 1);
我创建了一个新的 DirectX 项目并渲染了 2 个颜色组件,现在当我从着色器传递透明度时它没有改变任何东西,我是 c++ 和 DirectX 的新手,我使用了来自 [=39= 的标准模板] 创建项目
项目link:https://github.com/AbhishekSharma-SEG/TestAlphaBlending
混合状态
D3D11_BLEND_DESC blendDesc;
blendDesc.RenderTarget[0].BlendEnable = true;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_COLOR;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;;
blendDesc.IndependentBlendEnable = false;
blendDesc.AlphaToCoverageEnable = false;
auto hr = m_d3dDevice->CreateBlendState(&blendDesc, &AlphaEnableBlendingState);
if (SUCCEEDED(hr))
{
blendDesc.RenderTarget[0].BlendEnable = false;
m_d3dDevice->CreateBlendState(&blendDesc, &AlphaDisableBlendingState);
TurnOnAlphaBlending();
}
}
void DX::DeviceResources::TurnOnAlphaBlending()
{
float input[4] = { 0,0,0,0 };
m_d3dContext->OMSetBlendState(AlphaEnableBlendingState, input, 1);
}
void DX::DeviceResources::TurnOffAlphaBlending()
{
float input[4] = { 0,0,0,0 };
m_d3dContext->OMSetBlendState(AlphaDisableBlendingState, input, 1);
}
交换链描述
// Otherwise, create a new one using the same adapter as the existing Direct3D device.
DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window.
swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Microsoft Store apps must use _FLIP_ SwapEffects.
swapChainDesc.Flags = 0;
swapChainDesc.Scaling = scaling;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
着色器
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 0.2f);
}
输出
我找不到问题所在,几个教程和网站只讲述了如何设置混合状态,我尝试了他们告诉我应用的大部分设置,但它不起作用我也不知道为什么黄色组件应该在后面,因为首先出现对黄色组件的渲染调用,但它打印在红色组件上方,如果有人可以提供帮助,请感谢
alpha 模式忽略后的新输出并按照直线设置混合模式
编辑:已修复
所以在一些挖掘之后,我发现我没有使用深度模板状态,它在使用它解决后导致了这个问题,显然感谢@chukWalbourn 的建议,我能够设置混合的写入配置现在它工作得很好这里是帮助它的变化
//Describe our Depth/Stencil Buffer
CD3D11_DEPTH_STENCIL_DESC depthStencilStateDesc;
depthStencilStateDesc.DepthEnable = false;
depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilStateDesc.StencilEnable = true;
depthStencilStateDesc.StencilReadMask = 0xFF;
depthStencilStateDesc.StencilWriteMask = 0xFF;
depthStencilStateDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilStateDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilStateDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilStateDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilState(
&depthStencilStateDesc,
&m_d3dDepthStencilState
)
);
m_d3dContext->OMSetDepthStencilState(m_d3dDepthStencilState.Get(), 1);
当将 DXGI swap-chain alpha 模式用作 Direct3D 渲染目标时,UWP 应设置为 DXGI_ALPHA_MODE_IGNORE
或 Win32 应设置为 DXGI_ALPHA_MODE_UNSPECIFIED
。这仅适用于某些 Direct2D / DirectComposition-related 场景。
对于straight-alpha,使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
对于预乘 alpha 使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
'additive' 混合使用:
D3D11_BLEND_DESC blendDesc = {};
blendDesc.RenderTarget[0].BlendEnable = TRUE;
blendDesc.RenderTarget[0].SrcBlend =
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend =
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget[0].BlendOp =
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
You may want to take a look at DirectX Tool Kit.
所以在一些挖掘之后,我发现我没有使用深度模板状态,它在使用它后解决了这个问题,显然感谢@chukWalbourn 的建议,我能够设置混合的写入配置现在它完全正常了这里是帮助它的变化
//Describe our Depth/Stencil Buffer
CD3D11_DEPTH_STENCIL_DESC depthStencilStateDesc;
depthStencilStateDesc.DepthEnable = false;
depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilStateDesc.StencilEnable = true;
depthStencilStateDesc.StencilReadMask = 0xFF;
depthStencilStateDesc.StencilWriteMask = 0xFF;
depthStencilStateDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilStateDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilStateDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilStateDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilStateDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
DX::ThrowIfFailed(
m_d3dDevice->CreateDepthStencilState(
&depthStencilStateDesc,
&m_d3dDepthStencilState
)
);
m_d3dContext->OMSetDepthStencilState(m_d3dDepthStencilState.Get(), 1);