Приложение Windows 8 Store DirectX 11.1 Включение состояния Blendstate с загруженной текстурой PNG с альфа-каналом

Я загружаю PNG с прозрачностью в текстуру со следующим кодом:

ComPtr<IWICStream> stream;
ComPtr<IWICBitmapDecoder> bitmapDecoder;
ComPtr<IWICBitmapFrameDecode> bitmapFrame;
ComPtr<IWICFormatConverter> formatConverter;
unsigned int width, height
D3D11_SUBRESOURCE_DATA resourceData;

ZeroMemory(&resourceData, sizeof(resourceData));

DX::ThrowIfFailed( m_wicFactory->CreateStream(&stream) );
DX::ThrowIfFailed( stream->InitializeFromMemory( rawFileBytes->Data, rawFileBytes->Length) );
DX::ThrowIfFailed( m_wicFactory->CreateDecoderFromStream( stream.Get(), nullptr, WICDecodeMetadataCacheOnDemand, &bitmapDecoder ) );
DX::ThrowIfFailed( bitmapDecoder->GetFrame(0, &bitmapFrame) );
DX::ThrowIfFailed( m_wicFactory->CreateFormatConverter(&formatConverter) );
DX::ThrowIfFailed( formatConverter->Initialize( bitmapFrame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 1.0f /* some docs set this to 0.0f */, WICBitmapPaletteTypeCustom ) );
DX::ThrowIfFailed( bitmapFrame->GetSize(&width, &height) );

std::unique_ptr<byte[]> bitmapPixels(new byte[width * height * 4]);
DX::ThrowIfFailed( formatConverter->CopyPixels( nullptr, width * 4, width * height * 4, bitmapPixels.get() ) );

resourceData.pSysMem = bitmapPixels.get();
resourceData.SysMemPitch = width * 4;
resourceData.SysMemSlicePitch = 0;

CD3D11_TEXTURE2D_DESC textureDesc( DXGI_FORMAT_B8G8R8A8_UNORM, width, height, 1, 1 );
DX::ThrowIfFailed( m_d3dDevice->CreateTexture2D( &textureDesc, &resourceData, &texture2D ) );

if ( textureView != nullptr ) {
  CD3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc( texture2D.Get(), D3D11_SRV_DIMENSION_TEXTURE2D );
  DX::ThrowIfFailed( m_d3dDevice->CreateShaderResourceView( texture2D.Get(), &shaderResourceViewDesc, &shaderResourceView ) );
}

И настроить мое состояние смешивания в другом разделе кода:

Microsoft::WRL::ComPtr<ID3D11BlendState1> blendState;

D3D11_BLEND_DESC1 desc;
ZeroMemory( &desc, sizeof( desc ) );
desc.IndependentBlendEnable = FALSE;
desc.AlphaToCoverageEnable = FALSE;
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].LogicOpEnable = FALSE;
desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND::D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

direct3d.device->CreateBlendState1( &desc, blendState.GetAddressOf() );
direct3d.context->OMSetBlendState( blendState.Get(), NULL, 0xffffffff );

Со всей этой настройкой я все равно получаю черный фон там, где должна быть альфа.

Пояснение: у меня есть набор из 48 квадратных панелей, которые накладываются друг на друга от z 0,0f до 48,0f, но все, что я вижу, это самая передняя текстура 48,0f. Вместо того, чтобы прозрачные зоны были прозрачными, они отображаются как черные.

Изменить: вот мой пиксельный шейдер:

Texture2D Texture : register(t0);
SamplerState Sampler : register(s0);

struct sPSInput
{
    float4 pos : SV_POSITION;
    float3 norm : NORMAL;
    float2 tex : TEXCOORD0;
};

float4 SimplePixelShader(sPSInput input) : SV_TARGET
{
  float4 textured = Texture.Sample(Sampler, input.tex);
  return textured;
}

person OzBarry    schedule 13.02.2013    source источник


Ответы (2)


Этот

    desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_ONE;

должно быть это

   desc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_ALPHA;

также AlphaToCoverageEnable должен быть установлен false для ваших нужд

Кроме того, вы должны отключить буфер Z. Включенный Z-буфер предотвращает отрисовку всех объектов позади объекта впереди.

person thumbmunkeys    schedule 13.02.2013
comment
Я обновил приведенный выше фрагмент кода до того, как сейчас выглядит мой blendState, хотя это никак не повлияло на мою проблему :( - person OzBarry; 14.02.2013
comment
Итак, в итоге я смог увидеть все панели, которые я нарисовал между -0,9 и 0,9, и все они были округлены до 0,0f и появились на одном и том же слое z. Как только я перевожу любую модель из этого диапазона, они просто исчезают. - person OzBarry; 14.02.2013
comment
Да, я пытался отключить буфер z безрезультатно - кажется, где-то в моем коде что-то установлено, что мешает мне переводить z моих моделей. Не знаю, почему. Я могу опубликовать весь код инициализации, если вы думаете, что это поможет. - person OzBarry; 15.02.2013
comment
это помогло бы мне помочь вам :) вы уверены, что текстуры имеют альфа-канал? - person thumbmunkeys; 15.02.2013
comment
Вот мой код инициализации. Текстуры определенно имеют альфа-канал. На данный момент я сделал немного хакерское и статическое исправление, в котором я указал координаты z непосредственно в модели, поскольку в настоящее время они представляют собой просто плоские плоскости - я сделал это, потому что мне нужно продемонстрировать это приложение через две недели, поэтому мне просто нужно что-то пока это работает, и я всегда могу вернуться и исправить проблему с переводом. Вот мои соответствующие классы матриц. Камера и проекция работают нормально, поэтому я не загружал. - person OzBarry; 15.02.2013
comment
С жестко запрограммированным z в моделях альфа работает без нареканий. - person OzBarry; 15.02.2013
comment
так что ваши прямоугольники, вероятно, обрезаются, потому что они находятся за пределами усеченного обзора? - person thumbmunkeys; 15.02.2013
comment
Я устанавливаю свою камеру на -1000.0f, мои znear/far от 0.1f до 2000.0f, мои объекты находятся на z 0.0f. Я могу перевести x и y без каких-либо проблем. Я понятия не имею, почему они будут обрезаны, если они есть. - person OzBarry; 15.02.2013
comment
-1000 довольно далеко, если только у вас нет огромных объектов. но я думаю, что ваша проблема не в каком-то состоянии глубины/смешивания, а в матрице проекции вида. вы инвертируете его перед визуализацией объектов? также может помочь размещение кода вершинного шейдера. - person thumbmunkeys; 15.02.2013
comment
Да, инвертированную камеру можно увидеть в соответствующих классах матриц Я ссылался на него ранее, а также на вершинный шейдер. Я только что загрузил сюда свой класс матрицы камеры. - person OzBarry; 15.02.2013
comment
Я действительно не уверен в этом, но попробовать стоит: перемножьте матрицы в вашем вершинном шейдере в обратном порядке. Я думаю, что это необходимо, потому что вы переставляете матрицы перед умножением (A * B) T = BT * AT. - person thumbmunkeys; 16.02.2013
comment
Когда я обращаю это, я не вижу ничего, что отображается. - person OzBarry; 16.02.2013
comment
хм, тогда у меня нет идей. Но я почти уверен, что порядок ваших умножений неправильный. - person thumbmunkeys; 16.02.2013

Вам нужно нормализовать ваши Z-значения в диапазоне 0.0f (близко) - 1.0f (далеко).

Правильно ли вы настраиваете свой ViewPort?

D3D11_VIEWPORT Viewport =
{
    0.0f,                           // TopLeftX
    0.0f,                           // TopLeftY
    <width>,                        // Width
    <height>,                       // Height
    0.0f,                           // MinDepth
    1.0f };                         // MaxDepth
person d7samurai    schedule 07.02.2015