6

I'm working on an application that uses SharpDX and the SharpDX Toolkit to draw simple 3D shapes, and the Geometrics.Desktop sample was very helpful in getting started. Now I'm trying to make some shapes transparent, and to keep things simple I'm just trying to make the teapot model in in that sample appear transparent (perhaps translucent would be more precise).

For those not familiar with the Geometrics.Desktop sample, it draws a few simple primitive geometric shapes in 3D. Being a sample app, it's pretty simple, so it makes a pretty good scratchpad for experimenting with the 3D features of the SharpDX "Toolkit" library.

I've added this to the LoadContent method (which runs once at startup time), in an effort to prepare Direct3D to do blending:

        var blendStateDescription = new BlendStateDescription();

        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;

        var blendState = SharpDX.Toolkit.Graphics.BlendState.New(this.GraphicsDevice, blendStateDescription);
        this.GraphicsDevice.SetBlendState(blendState);

I have set up the depth stencil as follows:

        var depthDisabledStencilDesc = new DepthStencilStateDescription()
        {
            IsDepthEnabled = false,
            DepthWriteMask = DepthWriteMask.All,
            DepthComparison = Comparison.Less,
            IsStencilEnabled = true,
            StencilReadMask = 0xFF,
            StencilWriteMask = 0xFF,
            // Stencil operation if pixel front-facing.
            FrontFace = new DepthStencilOperationDescription()
            {
                FailOperation = StencilOperation.Keep,
                DepthFailOperation = StencilOperation.Increment,
                PassOperation = StencilOperation.Keep,
                Comparison = Comparison.Always
            },
            // Stencil operation if pixel is back-facing.
            BackFace = new DepthStencilOperationDescription()
            {
                FailOperation = StencilOperation.Keep,
                DepthFailOperation = StencilOperation.Decrement,
                PassOperation = StencilOperation.Keep,
                Comparison = Comparison.Always
            }
        };

        // Create the depth stencil state.
        var depthDisabledStencilState = SharpDX.Toolkit.Graphics.DepthStencilState.New(this.GraphicsDevice, depthDisabledStencilDesc);
        //turn z-buffer off
        this.GraphicsDevice.SetDepthStencilState(depthDisabledStencilState, 1);

And in the Draw method (which run at the frame rate and iterates through a small array of 3D models, drawing each one), I've added the code below. It moves the teapot to the center of the viewport and make it large enough to occlude some of the other objects. The teapot is drawn last, so the other models have already been rendered, so I was really hoping this would draw a translucent teapot on top of them:

// Draw the primitive using BasicEffect
if (i == 6)
{
    basicEffect.Alpha = 0.5f;
    basicEffect.World *= Matrix.Translation(-x, -y, 0);
    basicEffect.World *= Matrix.Scaling(3);
}
else
{
    basicEffect.Alpha = 1;
}

primitive.Draw(basicEffect);

(The comment and the final call to Draw were part of the original sample code.)

But alas, the result is a big opaque teapot among the other objects:

enter image description here

What do I need to do to make that teapot transparent?

Am I missing something, or have I misconfigured the blend state?

And just for completeness, I have also tried texturing my objects with images that have the alpha channel at 50%, but that still results in opaque objects.

Thanks in advance for any assistance!

NSFW
  • 557
  • 4
  • 12

1 Answers1

2

I have SourceAlphaBlend and DestinationAlphaBlend set to Zero and it works as it should. Other than those the state description looks correct to me. Also, make sure that AlphaToCoverage is disabled in the blendstate or else you'll have other things acting weird.

Also make sure that you set the BlendState before drawing each frame.

NSFW
  • 557
  • 4
  • 12
Russell Trahan
  • 783
  • 4
  • 34
  • Are you sure those are the only changes you made? I just made those changes to my test app and the teapot is still opaque. That you have alpha working at all gives me great hope, though! – NSFW Nov 07 '14 at 05:19
  • 1
    Are you using Visual Studio? If so, use the "Debug->Graphics->Start Diagnostrics" tool to debug the D3D11 device and states at runtime. Perhaps a state isn't getting bound correctly. – Russell Trahan Nov 07 '14 at 16:29
  • I have a transparent teapot! The blendstate that appeared in the diagnostic tool is not the same as the one that I configured in the code. I moved that into the render loop and transparency works now. I'd like to move it out of the render loop, of course, but I'll look into that next. – NSFW Nov 08 '14 at 02:22
  • Actually it seems that I have to do this before every render, as it is not sufficient to do this only on the first render. I thought the problem was the settings I was using, but really the problem is that I wasn't applying the settings often enough. :) – NSFW Nov 08 '14 at 02:37
  • That is not typical directx behavior. The state should be persistent unless you are using deferred contexts, command lists, and such. Perhaps that is some quirk in the sharpdx toolkit which I am not familiar with. – Russell Trahan Nov 08 '14 at 20:48
  • Their Geometric Primitive example is based on their Game infrastructure, so their is definitely some extra code in between the application and the native Direct3D stuff. But it turns out that I need to use blending selectively in my application anyway, so I need to be enabling and disabling it with every frame regardless. – NSFW Nov 09 '14 at 01:23