简体   繁体   English

SharpDX/DX11 Alpha 混合

[英]SharpDX/DX11 Alpha Blend

I am attempting to use alpha blending with SharpDX.我正在尝试将 alpha 混合与 SharpDX 一起使用。 If I set my blend state on my output merger, nothing renders at all, and I have absolutely no idea why.如果我在输出合并上设置混合状态,则根本不会渲染,而且我完全不知道为什么。 When never setting the blend state, everything works fine.当从不设置混合状态时,一切正常。 Even if I set a blend state with the default blend description, nothing renders.即使我使用默认的混合描述设置混合状态,也不会呈现任何内容。 I figure there's some step I'm missing or I am doing something in the wrong order, so I'll just paste what I've got and hope somebody can point something out...我想我遗漏了一些步骤,或者我做错了一些事情,所以我会粘贴我所拥有的,希望有人能指出一些东西......

I have a BlendState set up using the following code:我使用以下代码设置了 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;

...and here are the contents of my render loop. ...这里是我的渲染循环的内容。 If all I do is comment out context.OutputMerger.SetBlendState(bs), my meshes render fine (without any blending, that is):如果我所做的只是注释掉 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();

I am rendering to a texture, which is initialized using the following texture description:我正在渲染一个纹理,该纹理使用以下纹理描述进行初始化:

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
};

It is important for me to render to a texture and for me to use that format.渲染到纹理并对我使用该格式很重要。 I thought that maybe blending worked with particular formats, but I could not find any info suggesting anything of that sort.我认为混合可能适用于特定格式,但我找不到任何暗示此类内容的信息。

I am also multisampling, which is why I call ResolveSubresource(...) at the end of my render method.我也是多重采样,这就是为什么我在渲染方法的末尾调用 ResolveSubresource(...)。 The texture I am copying to has an identical description to RenderTarget, except with a different SampleDescription.我复制到的纹理与 RenderTarget 具有相同的描述,除了不同的 SampleDescription。

Speaking of multisampling, here's the RasterizerState I am using:说到多重采样,这是我正在使用的 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
});

I am rendering with a shader, which is basically a "Hello World" shader plus a camera matrix and basic normal direction lighting.我正在使用着色器进行渲染,它基本上是一个“Hello World”着色器加上一个相机矩阵和基本的法线方向照明。 I've verified that my vertex alpha values are what they're supposed to be just as they're being populated into their vertex buffers... and even if I hardcode their alpha to 1 at the end of the pixel shader, I still get nothing, so long as I use that BlendState.我已经验证我的顶点 alpha 值是它们应该是什么,就像它们被填充到它们的顶点缓冲区一样......即使我在像素着色器的末尾将它们的 alpha 硬编码为 1,我仍然只要我使用那个 BlendState,什么也得不到。 Without using BlendState, everything renders opaque as expected, regardless of alpha values.如果不使用 BlendState,无论 alpha 值如何,一切都会按预期呈现不透明。 I've even tried implementing the blend state in the shader itself, but that seems to have no effect whatsoever.我什至尝试在着色器本身中实现混合状态,但这似乎没有任何效果。 Everything appears to render as if no blending was defined at all.一切似乎都渲染得好像根本没有定义混合。

If it matters, I'm using FeatureLevel.Level.Level_11_0 with my Device.如果重要的话,我将 FeatureLevel.Level.Level_11_0 与我的设备一起使用。

Unfortunately this is about as much as I have to go on.不幸的是,这与我必须继续的差不多。 Like I said this problem is a total mystery to me at this point.就像我说的,这个问题在这一点上对我来说是个谜。

Just wanted to update this for anyone who comes here in the future.只是想为将来来到这里的任何人更新此内容。 Something that worked for me was quite simply:对我有用的东西很简单:

            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);

I also handled the alpha component in my shader, as well, in case you want to manually add transparency to a model, pseudo code:我还在我的着色器中处理了 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
}

Hope this helps someone instead of getting a dead page that basically points nowhere.希望这可以帮助某人而不是获得一个基本上无处可去的死页。 Happy coding everyone!祝大家编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM