Альфа-смесь SharpDX/DX11

Я пытаюсь использовать альфа-смешивание с SharpDX. Если я установлю свое состояние смешивания при слиянии вывода, вообще ничего не будет отображаться, и я совершенно не понимаю, почему. Если никогда не устанавливать состояние наложения, все работает нормально. Даже если я устанавливаю состояние наложения с описанием наложения по умолчанию, ничего не отображается. Я полагаю, что я пропустил какой-то шаг или делаю что-то в неправильном порядке, поэтому я просто вставлю то, что у меня есть, и надеюсь, что кто-нибудь может что-то указать...

У меня есть BlendState, настроенный с использованием следующего кода:

bs = new BlendState(Devices.Device11, new BlendStateDescription());

var blendDesc = new RenderTargetBlendDescription(
    true,
    BlendOption.SourceAlpha,
    BlendOption.InverseSourceAlpha,
    BlendOperation.Add,
    BlendOption.One,
    BlendOption.Zero,
    BlendOperation.Add,
    ColorWriteMaskFlags.All);

bs.Description.RenderTarget[0] = blendDesc;

...и вот содержимое моего цикла рендеринга. Если все, что я делаю, это комментирую context.OutputMerger.SetBlendState(bs), мои сетки отображаются нормально (то есть без какого-либо смешивания):

var context = Devices.Device11.ImmediateContext;

context.ClearDepthStencilView(DepthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0);
context.ClearRenderTargetView(RenderTargetView, new Color4());

context.OutputMerger.SetTargets(DepthStencilView, RenderTargetView);
context.OutputMerger.SetBlendState(bs);
context.Rasterizer.State = rs;
context.Rasterizer.SetViewport(Viewport);

context.VertexShader.SetConstantBuffer(0, viewProjBuffer);
context.UpdateSubresource(Camera.ViewProjection.ToFloatArray(), viewProjBuffer);

Dictionary<Mesh, Buffer> vBuffers = VertexBuffers.ToDictionary(k => k.Key, v => v.Value);
Dictionary<Mesh, Buffer> iBuffers = IndexBuffers.ToDictionary(k => k.Key, v => v.Value);

foreach (var mesh in vBuffers.Keys)
{
    if (mesh.MeshType == MeshType.LineStrip)
    {
        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineStrip;
        context.InputAssembler.InputLayout = Effects.LineEffect.InputLayout;
        context.VertexShader.Set(Effects.LineEffect.VertexShader);
        context.PixelShader.Set(Effects.LineEffect.PixelShader);
    }
    else
    {
        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        context.InputAssembler.InputLayout = Effects.FaceEffect.InputLayout;
        context.VertexShader.Set(Effects.FaceEffect.VertexShader);
        context.PixelShader.Set(Effects.FaceEffect.PixelShader);
    }

    context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vBuffers[mesh], GetMeshStride(mesh) * 4, 0));
    context.InputAssembler.SetIndexBuffer(iBuffers[mesh], Format.R32_UInt, 0);

    context.DrawIndexed(mesh.IndexUsage, 0, 0);
}

context.ResolveSubresource(RenderTarget, 0, SharedTexture, 0, Format.B8G8R8A8_UNorm);
context.Flush();

Я визуализирую текстуру, которая инициализируется с использованием следующего описания текстуры:

Texture2DDescription colorDesc = new Texture2DDescription
{
    BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
    Format = Format.B8G8R8A8_UNorm,
    Width = width,
    Height = height,
    MipLevels = 1,
    SampleDescription = new SampleDescription(8, 32),
    Usage = ResourceUsage.Default,
    OptionFlags = ResourceOptionFlags.Shared,
    CpuAccessFlags = CpuAccessFlags.None,
    ArraySize = 1
};

Для меня важно визуализировать текстуру и использовать этот формат. Я думал, что, возможно, смешивание работает с определенными форматами, но я не смог найти никакой информации, указывающей на что-то подобное.

Я также использую мультисэмплинг, поэтому я вызываю ResolveSubresource(...) в конце моего метода рендеринга. Текстура, в которую я копирую, имеет описание, идентичное RenderTarget, за исключением другого SampleDescription.

Говоря о мультисэмплинге, вот RasterizerState, который я использую:

rs = new RasterizerState(Devices.Device11, new RasterizerStateDescription()
{
    FillMode = FillMode.Solid,
    CullMode = CullMode.Back,
    IsFrontCounterClockwise = true,
    DepthBias = 0,
    DepthBiasClamp = 0,
    SlopeScaledDepthBias = 0,
    IsDepthClipEnabled = true,
    IsScissorEnabled = false,
    IsMultisampleEnabled = true,
    IsAntialiasedLineEnabled = true
});

Я визуализирую с помощью шейдера, который в основном представляет собой шейдер «Hello World», плюс матрицу камеры и базовое нормальное направленное освещение. Я убедился, что альфа-значения моих вершин являются такими, какими они должны быть, как раз в тот момент, когда они заполняются в свои вершинные буферы... и даже если я жестко запрограммирую их альфа-канал равным 1 в конце пиксельного шейдера, я все равно ничего не получить, пока я использую этот BlendState. Без использования BlendState все отображается непрозрачным, как и ожидалось, независимо от значений альфа-канала. Я даже пытался реализовать состояние смешивания в самом шейдере, но, похоже, это не дало никакого эффекта. Все выглядит так, как если бы смешивание вообще не было определено.

Если это имеет значение, я использую FeatureLevel.Level.Level_11_0 со своим устройством.

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


person Nasai    schedule 22.07.2014    source источник
comment
Похоже на дубликат этого SharpDX: включение состояния наложения   -  person xoofx    schedule 23.07.2014
comment
Ах я вижу. Спасибо Александр!   -  person Nasai    schedule 24.07.2014
comment
Я предполагаю, что здесь уместно пометить мой вопрос как дубликат, но я не нашел способа сделать это. Я читал, что обычно это делают другие, которые имеют достаточную репутацию или являются модераторами... Есть ли какой-то особый способ сделать это для моего собственного вопроса без соблюдения этих требований?   -  person Nasai    schedule 24.07.2014


Ответы (1)


Просто хотел обновить это для всех, кто придет сюда в будущем. Что-то, что сработало для меня, было довольно просто:

            BlendStateDescription blendStateDescription = new BlendStateDescription
            {
                AlphaToCoverageEnable = false,
            };

            blendStateDescription.RenderTarget[0].IsBlendEnabled = true;
            blendStateDescription.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
            blendStateDescription.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
            blendStateDescription.RenderTarget[0].BlendOperation = BlendOperation.Add;
            blendStateDescription.RenderTarget[0].SourceAlphaBlend = BlendOption.Zero;
            blendStateDescription.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
            blendStateDescription.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
            blendStateDescription.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;

            this._context.OutputMerger.BlendState = new BlendState(_device,blendStateDescription);

Я также обрабатывал альфа-компонент в своем шейдере, если вы хотите вручную добавить прозрачность к модели, псевдокод:

float4 PixelShaderMain( PixelShaderArgs pixelShaderArgs ) 
    : SV_Target
{
    float u = pixelShaderArgs.col.x;
    float v = pixelShaderArgs.col.y;
    float4 color = ShaderTexture.Load(int3(convertUVToPixel(u,v),0));
    return float4(color.r,color.g,color.b,0.5); // 50% transparency
}

Надеюсь, это поможет кому-то вместо того, чтобы получить мертвую страницу, которая в основном никуда не указывает. Всем удачного кодирования!

person Krythic    schedule 10.06.2020