SharpDX/DX11 Alpha 混合

Posted

技术标签:

【中文标题】SharpDX/DX11 Alpha 混合【英文标题】:SharpDX/DX11 Alpha Blend 【发布时间】:2014-09-13 23:30:27 【问题描述】:

我正在尝试将 Alpha 混合与 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”着色器加上一个相机矩阵和基本的法线方向照明。我已经验证了我的顶点 alpha 值是它们应该是的,就像它们被填充到它们的顶点缓冲区一样......即使我在像素着色器的末尾将它们的 alpha 硬编码为 1,我仍然只要我使用那个 BlendState,什么都得不到。如果不使用 BlendState,无论 alpha 值如何,一切都会按预期呈现不透明。我什至尝试在着色器本身中实现混合状态,但这似乎没有任何效果。一切似乎都呈现为好像根本没有定义混合。

如果重要的话,我在我的设备上使用 FeatureLevel.Level.Level_11_0。

不幸的是,这已经是我必须继续进行的事情了。就像我说的,这个问题目前对我来说完全是个谜。

【问题讨论】:

看起来像这个"SharpDX: Enabling blend state"的副本 啊,我明白了。谢谢亚历山大! 我想在这里做的适当的事情是将我的问题标记为重复,但我还没有找到一种方法来做到这一点。我读过,通常它是由其他人完成的,他们有足够的声誉或者是版主......有没有什么特殊的方法可以在不满足这些要求的情况下为我自己的问题做到这一点? 【参考方案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);

我还在我的着色器中处理了 alpha 组件,如果你想手动为模型添加透明度,伪代码:

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

希望这对某人有所帮助,而不是得到一个基本上无处可去的死页。祝大家编码愉快!

【讨论】:

以上是关于SharpDX/DX11 Alpha 混合的主要内容,如果未能解决你的问题,请参考以下文章

带有 Alpha 混合控件的 C# Alpha 混合表单

图形混合概念

Alpha 混合 - 反复混合 RGBA 颜色会产生黑色

alpha通道与混合技术

如何在 SDL 中进行硬件加速 Alpha 混合?

渲染管道像素阶段“Alpha混合”