Rendering Transparent 3D Surfaces in WPF with C#(转载)

Rendering Transparent 3D Surfaces in WPF with C#

The primary problems that arise when rendering semi-transparent 3d objects in Windows Presentation Foundation have to do with false z-buffer occlusions. Specifically, when a transparent surface or polygon is rendered, it sets the z-buffer depth values to block objects that are behind it from being rendered, even though they should show through the transparent layer.

In WPF with C#, the z-buffer is not accessible. So, it can not be disabled during transparent rendering. Instead, we must render the transparent objects last so that they are layered over the rest of the scene and the objects behind them show through.

Below, I have a program for the single code file that I used to generate the spinning, transparent tetrahedron shown above. The C# project that I used is a simple Console Application project with the libraries PresentationCore,PresentationFramework, and WindowsBase references added to it as I showed in a prior post: Using WPF in a C# Console Application. The Main() function creates the Window for the program and calls TransparentScene() to do all of the rendering.

Inside the function TransparentScene(), I create the camera, the light, the animated rotation transformation, the tetrahedron geometry, and then use that geometry to specify three tetrahedrons. The first tetrahedron is called the Inner Tetrahedronbecause it is scaled to fit inside the others. The second tetrahedron is called the Outer Tetrahedron and is semi-transparent. The third tetrahedron is also part of the Outer Tetrahedron, but consists of the opaque back faces. Note that it only makes sense to render the back faces because the front faces are semi-transparent. Otherwise, the back would not be visible.

At the end the code, I use the following lines to add the tetrahedrons to the scene:

            qModelGroup.Children.Add(qBackGeometry);
            qModelGroup.Children.Add(qInnerGeometry);
            qModelGroup.Children.Add(qOuterGeometry);

Notice that the transparent “Outer Geometry” layer is added last. This is necessary to avoid false occlusions.

For comparison, I have included the image below with four different arrangements. The first (top-left) shows the scene with the transparent outer layer added before the inner and after the back. The second (top-right) shows the transparent outer layer added before both the inner and the back layers. The third (bottom-left) shows the transparent layer added before the back and after the inner layer. The last (bottom-right) shows the scene with the transparent layer added last as it is in the code.

Program.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;

namespace WpfTransparent {
    class Program {
        [STAThread]
        static void Main(string[] args) {
            Window qWindow = new Window();
            qWindow.Title = "Transparent Rendering";
            qWindow.Width = 400;
            qWindow.Height = 300;
            qWindow.Content = TransparentScene();
            qWindow.ShowDialog();
        }

        static Viewport3D TransparentScene() {
            // Define the camera
            PerspectiveCamera qCamera = new PerspectiveCamera();
            qCamera.Position = new Point3D(0, .25, 2.25);
            qCamera.LookDirection = new Vector3D(0, -.05, -1);
            qCamera.UpDirection = new Vector3D(0, 1, 0);
            qCamera.FieldOfView = 60;

            // Define a lighting model
            DirectionalLight qLight = new DirectionalLight();
            qLight.Color = Colors.White;
            qLight.Direction = new Vector3D(-0.5, -0.25, -0.5);

            // Define the animated rotation transformation
            RotateTransform3D qRotation =
                new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 1));
            DoubleAnimation qAnimation = new DoubleAnimation();
            qAnimation.From = 1;
            qAnimation.To = 361;
            qAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
            qAnimation.RepeatBehavior = RepeatBehavior.Forever;
            qRotation.Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, qAnimation);

            // Define the geometry
            const double kdSqrt2 = 1.4142135623730950488016887242097;
            const double kdSqrt6 = 2.4494897427831780981972840747059;
            // Create a collection of vertex positions
            Point3D[] qaV = new Point3D[4]{
                new Point3D(0.0, 1.0, 0.0),
                new Point3D(2.0 * kdSqrt2 / 3.0, -1.0 / 3.0, 0.0),
                new Point3D(-kdSqrt2 / 3.0, -1.0 / 3.0, -kdSqrt6 / 3.0),
                new Point3D(-kdSqrt2 / 3.0, -1.0 / 3.0, kdSqrt6 / 3.0)};
            Point3DCollection qPoints = new Point3DCollection();
            // Designate Vertices
            // My Scheme (0, 1, 2), (1, 0, 3), (2, 3, 0), (3, 2, 1)
            for (int i = 0; i < 12; ++i) {
                if ((i/3) % 2 == 0) {
                    qPoints.Add(qaV[i%4]);
                } else {
                    qPoints.Add(qaV[(i*3)%4]);
                }
            }
            // Designate Triangles
            Int32Collection qTriangles = new Int32Collection();
            for (int i = 0; i < 12; ++i ) {
                qTriangles.Add(i);
            }
            Int32Collection qBackTriangles = new Int32Collection();
            // Designate Back Triangles in the opposite orientation
            for (int i = 0; i < 12; ++i) {
                qBackTriangles.Add(3 * (i / 3) + (2 * (i % 3) % 3));
            }

            // Inner Tetrahedron: Define the mesh, material and transformation.
            MeshGeometry3D qFrontMesh = new MeshGeometry3D();
            qFrontMesh.Positions = qPoints;
            qFrontMesh.TriangleIndices = qTriangles;
            GeometryModel3D qInnerGeometry = new GeometryModel3D();
            qInnerGeometry.Geometry = qFrontMesh;
            // *** Material ***
            DiffuseMaterial qDiffGreen =
                new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(255, 0, 128, 0)));
            SpecularMaterial qSpecWhite = new
                SpecularMaterial(new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)), 30.0);
            MaterialGroup qInnerMaterial = new MaterialGroup();
            qInnerMaterial.Children.Add(qDiffGreen);
            qInnerMaterial.Children.Add(qSpecWhite);
            qInnerGeometry.Material = qInnerMaterial;
            // *** Transformation ***
            ScaleTransform3D qScale = new ScaleTransform3D(new Vector3D(.5, .5, .5));
            Transform3DGroup myTransformGroup = new Transform3DGroup();
            myTransformGroup.Children.Add(qRotation);
            myTransformGroup.Children.Add(qScale);
            qInnerGeometry.Transform = myTransformGroup;

            // Outer Tetrahedron (semi-transparent) : Define the mesh, material and transformation.
            GeometryModel3D qOuterGeometry = new GeometryModel3D();
            qOuterGeometry.Geometry = qFrontMesh;
            // *** Material ***
            DiffuseMaterial qDiffTransYellow =
                new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(64, 255, 255, 0)));
            SpecularMaterial qSpecTransWhite =
                new SpecularMaterial(new SolidColorBrush(Color.FromArgb(128, 255, 255, 255)), 30.0);
            MaterialGroup qOuterMaterial = new MaterialGroup();
            qOuterMaterial.Children.Add(qDiffTransYellow);
            qOuterMaterial.Children.Add(qSpecTransWhite);
            qOuterGeometry.Material = qOuterMaterial;
            // *** Transformation ***
            qOuterGeometry.Transform = qRotation;

            // Outer Tetrahedron (solid back) : Define the mesh, material and transformation.
            MeshGeometry3D qBackMesh = new MeshGeometry3D();
            qBackMesh.Positions = qPoints;
            qBackMesh.TriangleIndices = qBackTriangles;
            GeometryModel3D qBackGeometry = new GeometryModel3D();
            qBackGeometry.Geometry = qBackMesh;
            // *** Material ***
            DiffuseMaterial qDiffBrown =
                new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(255, 200, 175, 0)));
            qBackGeometry.Material = qDiffBrown;
            // *** Transformation ***
            qBackGeometry.Transform = qRotation;

            // Collect the components
            Model3DGroup qModelGroup = new Model3DGroup();
            qModelGroup.Children.Add(qLight);
            qModelGroup.Children.Add(qBackGeometry);
            qModelGroup.Children.Add(qInnerGeometry);
            qModelGroup.Children.Add(qOuterGeometry);
            ModelVisual3D qVisual = new ModelVisual3D();
            qVisual.Content = qModelGroup;
            Viewport3D qViewport = new Viewport3D();
            qViewport.Children.Add(qVisual);
            qViewport.Camera = qCamera;

            return qViewport;
        }
    }
}
时间: 2024-10-22 10:27:36

Rendering Transparent 3D Surfaces in WPF with C#(转载)的相关文章

WPF阴影效果(DropShadowEffect)(转载)

<TextBlock Text="阴影效果" FontSize="32"> <TextBlock.Effect> <DropShadowEffect Color="Black"></DropShadowEffect> </TextBlock.Effect> </TextBlock> <TextBlock Text="阴影效果" FontSize=&q

WPF 3D 知识点大全以及实例

原文:WPF 3D 知识点大全以及实例 引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当然还有体感游戏等等. 3D 用来增加视觉效果,给人以更加直观,真实的感觉. 3D如此美妙,那我们在WPF中又该从何处入手开启我们的3D编程旅程? WPF中3D开发技术的基础知识应该有以下几点: 3D开发基础知识 WPF中3D开发的基础元素(Elements)

WPF 3D 常用类(1)

原文:WPF 3D 常用类(1) 几何数据相关类 Geometry3D 抽象类, 用于定义物体的几何数据, 可用于计算HitTest和BoundingBox MeshGeometry3D Geometry3D的子类, 定义网格的顶点, 三角形顶点, 法线, Texture(纹理)的座标 常用属性: Positions, TriangleIndices, Noramls, TextureCoordinates 模型相关类 (模型=几何数据+变形(位置,旋转,尺寸)+材质) Model3D 抽象类,

优化WPF 3D性能

Maximize WPF 3D Performance .NET Framework 4.5 As you use the Windows Presentation Foundation (WPF) to build 3D controls and include 3D scenes in your applications, it is important to consider performance optimization. This topic provides a list of 3

WPF换肤之八:创建3D浏览效果

原文:WPF换肤之八:创建3D浏览效果 上节中,我们展示了WPF中的异步以及界面线程交互的方式,使得应用程序的显示更加的流畅.这节我们主要讲解如何设计一个具有3D浏览效果的天气信息浏览器. 效果显示 下面我们看截图: 是不是能够感受到一种与众不同的感觉.如果你能够感受到它的与众不同,这也是我本节所要达到的目标. 实现方式 上面的只是一个简单的3D图形,它的产生需要依赖于WPF中的MeshGeometry3D对象,这个对象按照微软官方的解释就是用于生成3D形状的三角形基元,它有三个比较重要的属性:

wpf做的3d滑动gallery

原文:wpf做的3d滑动gallery wpf做的3d滑动gallery 随着iphone\ipad的流行及热捧,现在做移动产品不管是什么平台的,领导总想做成像ios系统的样子.自从微软发布了window8预览版之后,领导就想着把公司的移动产品移殖到window8上去了.公司的移动产品的主界面是做成3d gallery的立体画册效果的,如下图: window8是不带这样的控件的,究竟有没有实现如此效果的控件我就不清楚了,我认为是没有的,因为我在vs上找不到,也不符合window8风格,我找遍了互

WPF 3D 小小小小引擎 - &#183;WPF 3D变换应用

原文:WPF 3D 小小小小引擎 - ·WPF 3D变换应用 WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手. 下面给大家演示的是使用在WPF 3D上实现视角变换,通过鼠标拖动来变换观察视角,通过滚轮来放缩视距. 有关3D的基础知识可以参考MSDN文档:三维图形概述 首先创建一个3D立方体,立方体是由六个面构成(F1, F2 ....F6)其XAML代码如下: <Viewport3

WPF特效-实现3D足球效果

原文:WPF特效-实现3D足球效果 WPF 实现 3D足球效果,效果图如下: ?每个面加载不同贴图. <UserControl x:Class="MediaBalll.Model3Ds.BuckyBall"? ? ? ? ? ? ?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"? ? ? ? ? ? ?xmlns:x="http://schemas.microsoft

WPF 3D model - Sphere, Cone, and Cylinder

原文:WPF 3D model - Sphere, Cone, and Cylinder ? Extending Visual3D - Sphere, Cone, and Cylinder http://blogs.msdn.com/b/danlehen/archive/2005/10/16/481597.aspx ? He?put together a short sample which derives a Sphere, a Cone, and a Cylinder primitive f