我已经在 Gamedev 上发布了这个,但是,已经几天了,没有被咬。我想看看是否有人知道我错过了什么。
通常我会将这些作为两个问题发布,但我感觉它们是相互交织的。简而言之,我有一个粒子系统,它为精灵生成数据以显示在透明表面上。然后将其发送到几何着色器(通过顶点着色器)以将单个顶点挤压成四边形,然后最终发送到像素着色器(下面的代码)。
像素颜色是从用作纹理图集(64x64 表面)的 32 位 DDS(使用 alpha 通道表示透明度)中采样的。
这两个问题如下:虽然单个精灵适当地尊重其透明度,但当该精灵经过另一个精灵时,其中一个四边形用透明矩形覆盖另一个四边形(您可以看到附加的图像:第一个图像是一个框架它们重叠,第二个是在一个稍微移开之后)。为了我的一生,我不能让 MSAA 合作。我已经设置了一个三重 Texture2D 系统来执行 output->ResolveSubresource->output_msaa->CopyResource->final_output,它渲染,它仍然是别名。
以下是设备、纹理和采样器状态的代码:
//Errors are checked in other places and the debug layer is showing no warnings
//Render Target Texture
D3D11_TEXTURE2D_DESC texd;
ZeroMemory(&texd, sizeof(texd));
texd.Width = config.width;
texd.Height = config.height;
texd.ArraySize = 1;
texd.SampleDesc.Count = 4;
texd.SampleDesc.Quality = D3D11_CENTER_MULTISAMPLE_PATTERN;
texd.MipLevels = 1;
texd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texd.BindFlags = D3D11_BIND_RENDER_TARGET;
texd.Usage = D3D11_USAGE_DEFAULT;
hr = dev->CreateTexture2D(&texd, NULL, &output_texture);
//Sampler State
D3D11_SAMPLER_DESC samplerdesc;
ZeroMemory(&samplerdesc, sizeof(samplerdesc));
samplerdesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerdesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerdesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerdesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = dev->CreateSamplerState(&samplerdesc, &samplerstate);
//MSAA Intermediary Texture
ZeroMemory(&texd, sizeof(texd));
texd.Height = config.height;
texd.Width = config.width;
texd.MipLevels = 1;
texd.ArraySize = 1;
texd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texd.SampleDesc.Count = 1;
texd.SampleDesc.Quality = 0;
texd.Usage = D3D11_USAGE_DEFAULT;
hr = dev->CreateTexture2D(&texd, NULL, &output_temp_msaa);
//Second Intermediary Texture
ZeroMemory(&texd, sizeof(texd));
texd.Height = config.height;
texd.Width = config.width;
texd.MipLevels = 1;
texd.ArraySize = 1;
texd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texd.SampleDesc.Count = 1;
texd.SampleDesc.Quality = 0;
texd.Usage = D3D11_USAGE_STAGING;
texd.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = dev->CreateTexture2D(&texd, NULL, &output_temp);
The texture loading:
hr = D3DX11CreateShaderResourceViewFromFile(
dev,
L"Atlas.dds",
&rtd,
NULL,
&res_texture,
NULL
);
//in the Render() function:
devcon->PSSetShaderResources(0, 1, &res_texture);
The blend state code:
D3D11_BLEND_DESC desc;
desc.AlphaToCoverageEnable = false;
desc.IndependentBlendEnable = false;
for (int i = 0; i < 8; i++)
{
desc.RenderTarget[i].BlendEnable = true;
desc.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
desc.RenderTarget[i].SrcBlend = D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[i].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
}
hr = dev->CreateBlendState(&desc, &blendstate);
这是从 output_texture 转换为 output_temp 纹理以进行复制的代码:
devcon->ResolveSubresource(
output_temp_msaa,
D3D11CalcSubresource(0, 0, 1),
output_texture,
D3D11CalcSubresource(0, 0, 1),
DXGI_FORMAT_B8G8R8A8_UNORM
);
devcon->CopyResource(output_temp, output_temp_msaa);
然后这样使用:
devcon->Map(output_temp, 0, D3D11_MAP_READ, 0, &output_subresource);
并一点一点地复制到另一个位置进行绘图。
这是当前的像素着色器:
//These are properly being set, AFAIK.
Texture2D Texture;
SamplerState ss;
struct PS_INPUT {
float4 p : SV_POSITION;
float2 t : TEXCOORD;
float opacity : OPACITY;
};
float4 PShader(PS_INPUT input) : SV_TARGET
{
float4 color = Texture.Sample(ss, input.t);
color.a = input.opacity;
return color;
}
最后,附上显示透明剪辑的图像(有问题的精灵位于屏幕中间)。
提前谢谢大家!
更新:剪辑问题实际上是因为我们的图形艺术家和我之间的沟通不畅。纹理使用黑色作为透明的指示,而不是传统的 alpha。考虑到这一点(通过在像素着色器中将纯黑色更改为 float4(0,0,0,1))解决了裁剪问题。MSAA 问题仍然存在。