使用WPF学习图形学——3D图形平台入门
发布于 2021-10-17 13:54
《计算机图形学原理及实践》第六章学习笔记
概述
WPF的3D功能可以让你在不编写任何c#代码的情况下就能进行各种图形学的实验,你只需要使用xaml可扩展标记语言就可以进行3D图形学的学习,是一个很友好的图形学实验平台。
本文将介绍如何使用WPF的3D功能来构建一个3D场景、配置光照、并通过其照相机功能来生成图像。
3D场景绘制流程
开始动手实践之前首先需要理解3D场景绘制的流程:
1. 首先需要建模,从简单的几何体到复杂的游戏角色等,它们是在场景坐标系中构建的,构建的内容称为场景;
2. 接下来需要设置照相机,所谓照相机就是观察者,拍照总是会寻找好的构图、玩3D游戏时我们探索游戏世界时时刻通过鼠标调整视野,这些都是调整照相机的例子;总之,照相机的作用就是获取观察世界的区域;下图中照相机辐射出的金字塔状的范围被称为视域体。
3. 场景中位于视域体中的部分,被投影到2D平面上(通常就是指显示屏幕)就完成3D场景的绘制。(本书第二章一个古老的绘制器,针对投影进行了讲解)
4. 3D场景绘制中还有个非常关键的东西就是光源,没有光我们看到的将是一片黑暗;后面会单独写一篇文章介绍,这里只需要了解光源包括泛光、方向光、几何光源(点光源、聚光灯)。
如果你曾经使用过3D建模软件就会理解地更深刻些,像开源3D软件blender中的渲染步骤其实就是通过不断调整场景中光照、相机位置,最终来生成一张逼真的2D图像。
WPF 3D平台实践
本书官网链接
https://sklardevelopment.com/graftext/ChapWPF3D/提供第六章实现的练习程序,下载解压并运行PyramidTextbook.exe可以跟着书本的知识逐一进行实践练习,其中也提供了xaml的代码可供学习。
接下来我们使用WPF来实现一个简单的金字塔几何体,主要目的是熟悉3D场景代码的基本结构,熟悉了基本结构之后就可以参考上面应用提供的代码自行扩展练习了。
打开visual studio开发工具新建一个WPF应用(.NET Framework)项目,打开MainWindow.xaml,本示例只需要在这一个文件中编写代码,整体的代码结构如下:
<Window x:Class="_3D_demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_3D_demo"
mc:Ignorable="d"
Title="MainWindow">
<!--Page是WPF提供的布局元素,类似于Grid-->
<Page xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Page.Resources>
<!-- 物体模型、材质的定义在Resources中,类似于模板,不会显示到屏幕上 -->
</Page.Resources>
<Viewport3D Width="640" Height="480">
<!-- Viewport3D类似与2D中的canvas画布,为3D场景的显示提供绘制区域,照相机、物体、光源在这里设置
-->
<Viewport3D.Camera>
<!-- 照相机的设置放在这里,相机不会在场景中显示 -->
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<!-- 场景中的物体模型和光源在这里设置 -->
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Page>
</Window>
下面为金字塔几何体的建模,注意三角形是WPF 3D支持的唯一几何图元,所有的物体建模都是通过三角形来逼近的,我们要建模的金字塔几何体各个三角形面的定义及组成三角形的顶点序号定义如下(本次示例忽略了正方形的底面,如果需要补充也需要用两个三角形来拼接):
完整的xaml代码:
<Window x:Class="_3D_demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_3D_demo"
mc:Ignorable="d"
Title="MainWindow">
<!--Page是WPF提供的布局元素,类似于Grid-->
<Page xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Page.Resources>
<!-- 物体模型、材质的定义在Resources中,类似于模板,不会显示到屏幕上 -->
<!-- 金字塔几何体模型定义 Positions为顶点坐标,TriangleIndices为三角形网格的顶点索引 -->
<MeshGeometry3D x:Key="RSRCmeshPyramid"
Positions="0,75,0 -50,0,50 50,0,50 0,75,0 50,0,50 50,0,-50 0,75,0 50,0,-50 -50,0,-50 0,75,0 -50,0,-50 -50,0,50"
TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11">
</MeshGeometry3D>
<!-- 物体正面材质,使用简单的黄色 -->
<DiffuseMaterial x:Key="RSRCmaterialFront" Brush="Yellow"></DiffuseMaterial>
<!--定义一个动画模板,沿y轴旋转360°-->
<Storyboard x:Key='TurntableStoryboard'>
<ParallelTimeline RepeatBehavior='Forever'>
<DoubleAnimation From='0'
To='360'
Storyboard.TargetName='yAxisRotate'
Storyboard.TargetProperty='Angle'
Duration='0:0:4'/>
</ParallelTimeline>
</Storyboard>
</Page.Resources>
<Page.Triggers>
<!--鼠标进入触发动画-->
<EventTrigger RoutedEvent='Mouse.MouseEnter'>
<BeginStoryboard x:Name='StartTurntable' Storyboard='{StaticResource TurntableStoryboard}'></BeginStoryboard>
</EventTrigger>
<!--鼠标进入停止动画-->
<EventTrigger RoutedEvent='Mouse.MouseLeave'>
<StopStoryboard BeginStoryboardName='StartTurntable'/>
</EventTrigger>
</Page.Triggers>
<Viewport3D Width="640" Height="480">
<!-- Viewport3D类似与2D中的canvas画布,为3D场景的显示提供绘制区域
照相机、物体、光源在这里设置
-->
<Viewport3D.Camera>
<!-- 照相机的设置放在这里,相机不会在场景中显示 -->
<PerspectiveCamera
Position="108.7, 409.3, 0.4"
LookDirection="-0.21,-0.89,-0.09"
UpDirection="0,1,0"
NearPlaneDistance="0.02"
FarPlaneDistance="990000"
FieldOfView="45">
</PerspectiveCamera>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<!-- 场景中的物体模型和光源在这里设置 -->
<!--泛光,场景中所有面颜色相同,这里未使用泛光-->
<!--<AmbientLight Color="White"></AmbientLight>-->
<!--方向光,颜色为白光 direction表示光照方向,对应x,y,z坐标-->
<DirectionalLight Color="#FFFFFF" Direction="1, -1, -1"></DirectionalLight>
<Model3DGroup x:Name="StuffOnTurntable">
<!--金字塔几何体模型-->
<GeometryModel3D
Geometry="{StaticResource RSRCmeshPyramid}"
Material="{StaticResource RSRCmaterialFront}">
</GeometryModel3D>
<!--旋转变换,沿y轴旋转,初始角度为0-->
<Model3DGroup.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name='yAxisRotate'
Axis='0,1,0'
Angle='0'/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</Model3DGroup.Transform>
</Model3DGroup>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Page>
</Window>
运行应用鼠标移动到几何体上面会触发旋转动画,截图如下
本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。
相关素材