Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I draw a transparent 3D object with the SharpDX Toolkit?

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!

like image 439
NSFW Avatar asked Oct 30 '14 06:10

NSFW


1 Answers

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.

like image 129
Russell Trahan Avatar answered Sep 18 '22 04:09

Russell Trahan