简体   繁体   English

如何使用SharpDX工具包绘制透明的3D对象?

[英]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. 我正在开发一个使用SharpDX和SharpDX Toolkit绘制简单3D形状的应用程序,而Geometrics.Desktop示例对于入门非常有用。 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. 对于不熟悉Geometrics.Desktop示例的人,它可以在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. 作为一个示例应用程序,它非常简单,因此它成为了试验SharpDX“工具包”库的3D功能的不错的便笺簿。

I've added this to the LoadContent method (which runs once at startup time), in an effort to prepare Direct3D to do blending: 我已将其添加到LoadContent方法(在启动时运行一次),以准备Direct3D进行混合:

        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. 在Draw方法(以帧速率运行并遍历一小组3D模型并绘制每个模型)中,我添加了以下代码。 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.) (注释和对Draw的最终调用是原始示例代码的一部分。)

But alas, the result is a big opaque teapot among the other objects: 但可惜的是,结果是其他物体之间出现了一个巨大的不透明茶壶:

在此处输入图片说明

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. 为了完整起见,我还尝试使用Alpha通道为50%的图像对对象进行纹理处理,但这仍然会导致对象不透明。

Thanks in advance for any assistance! 在此先感谢您的协助!

I have SourceAlphaBlend and DestinationAlphaBlend set to Zero and it works as it should. 我将SourceAlphaBlend和DestinationAlphaBlend设置为零,它可以正常工作。 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. 另外,请确保在blendstate中禁用了AlphaToCoverage,否则您将感到其他事情有些奇怪。

Also make sure that you set the BlendState before drawing each frame. 还要确保在绘制每帧之前设置BlendState。

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

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