Я разместил это на Gamedev, однако прошло несколько дней и никаких укусов. Я хотел посмотреть, есть ли у кого-нибудь идея, что я пропустил.
Обычно я бы публиковал их как два вопроса, но у меня есть ощущение, что они переплетены. Короче говоря, у меня есть система частиц, которая генерирует данные для отображения спрайта на прозрачной поверхности. Затем он отправляется в геометрический шейдер (через проход через вершинный шейдер) для выдавливания одной вершины в четырехугольники, а затем в пиксельный шейдер (код ниже).
Цвета пикселей выбираются из 32-битного DDS (с использованием альфа-канала для обозначения прозрачности), который используется в качестве текстурного атласа (поверхности 64×64).
Две проблемы заключаются в следующем:
Хотя один спрайт должным образом соблюдает прозрачность, когда этот спрайт переходит поверх другого, один из квадратов перезаписывает другой прозрачным прямоугольником (вы можете видеть прикрепленные изображения: первое изображение — это кадр с перекрытием их, второе — после один отошел немного).
Я не могу за свою жизнь заставить 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;
}
Наконец, прикрепляются изображения, показывающие прозрачную вырезку (спрайт-нарушитель находится в середине экрана).
Спасибо всем заранее!
Обновить:
Проблема с обрезанием была на самом деле из-за недопонимания между нашим художником-графиком и мной. Текстура использовала черный цвет в качестве индикатора прозрачности вместо традиционной альфы. Учет этого (путем изменения чистого черного на float4 (0,0,0,1) в пиксельном шейдере) решил проблему отсечения. Проблема MSAA остается.
Задача ещё не решена.
Других решений пока нет …