当前位置:文档之家› VB.NET三维程序设计

VB.NET三维程序设计

VB.NET三维程序设计
VB.NET三维程序设计

VB.NET三维程序设计

目前流行的各种大型网络游戏,以及各种高端的图形图像应用设计,大部分都使用了3D技术。流行的三维设计编程接口(API)有两大类,一类是OpenGL,主要用于Java编程;另一类是DirectX,主要用于Windows环境下的各类三维软件编程。

DirectX其实是一个组件套件,是由微软公司开发的应用程序编程接口,包含有Direct Graphics、Direct Input、Direct Play(针对游戏/网络)、Direct Sound(针对3D声音功能)、Direct Show等多个组件,它提供了一整套的多媒体接口方案。而今已发展成为对整个多媒体系统的各个方面都有决定性影响的接口。

DirectX是1995年诞生的,1996年在DirectX中加入了Direct3D,用于访问3D硬件加速的高级图形功能,通过提供通用的COM(Component Object Model,组件对象模型)编程接口使硬件和设计分离,随后很快发展到DirectX8.0,并从DirectX9.0开始支持托管代码。自2002年.NET和C#诞生以后,DirectX的应用也迅速得到提升,很多优秀的性能也逐步加入到托管DirectX中。由于DirectX的使用非常普遍,所以目前所有的显卡无一例外的都支持DirectX编程接口,给各类三维应用设计带来了很大方便。

注意,本章的所有例子全部是在安装DirectX9.0c SDK December 2005后调试通过的。要调试本章的所有例子,必须先安装VS2005,然后再安装DirectX9.0 SDK December 2005(几百MB),如果仅仅为了直接运行已经编译后的.exe 文件,而不进行调试,也可以只安装DirectX9.0c(几十MB)。例子中调试使用的具体版本为: Microsoft.DirectX.dll 版本1.0.2902.0

Microsoft.DirectX.Direct3D.dll 版本1.0.2902.0

Microsoft.DirectX.Direct3DX.dll 版本1.0.2908.0

使用DirectX编写程序,首先必须在资源管理器中添加对它的引用。步骤为:【项目】?【添加引用】,然后在弹出窗口的.NET选项中选择上面列出的版本,单击【确定】。选择时要仔细观察引用的是哪个版本,不要选错。一定要注意,本章的例子必须在引用上面列出的版本下才能正常调试,在低版本下或者高版本下,由于SDK提供的属性及方法不一定相同,所以不保证能正常运行。

由于三维设计涉及面很广,而且包含很多复杂的模型计算以及数学处理等方面的内容,因此这里不准备在短短一章中把Direct3D的内容全部介绍,而是只关心简单的、最基本的三维设计思路,并通过介绍DirectX提供的Primitive和Mesh对象的基本用法,为复杂的三维设计入门起到一个抛砖引玉的作用。

1 简单的3D设计入门

与一般Windows应用程序不同,为了提高显示速率和展现真实的三维效果,三维设计有一个特定的基本编程模式。为了让读者首先有一个感性认识,这一节先不介绍DirectX提供的各种功能,而是通过一个简单例子介绍利用DirectX编程接口进行三维设计的一般方法,然后再介绍涉及到的相关概念和技术。

【例1】使用DirectX设计一个能够旋转的三角形,并将本机显卡和显示器的相关参数显示出来。

(1) 新建一个名为SimpleDirect3DExample的Windows应用程序,使用默认的窗体名称。

(2) 在【项目】?【添加引用】?在【.net】选项下同时选中Microsoft.DirectX、Microsoft.DirectX.Direct3D 和Microsoft.DirectX.Direct3DX,注意选择的版本要和本章开头列出的版本一致,单击【确定】。

(3) 在命名空间的上方,添加引用代码:

Imports Microsoft.DirectX

Imports Microsoft.DirectX.Direct3D

(4) 在构造函数上方添加字段声明:

Dim device As Device 'Device指显卡适配器,一个显卡至少有一个适配器

Dim VertexBuffer As VertexBuffer

Dim d3dfont As Microsoft.DirectX.Direct3D.Font

Dim adapterInformationString As String

Dim showAdapterString As Boolean = True

Dim angle As Single = 0.0F

Dim incrementAngle As Single = 0.1F

Dim enableRotator As Boolean = True

这段代码中,Device对象代表一个显卡适配器,如果显卡驱动程序正确并支持3D,就不会出现异常。然后就利用这个Device对象和显存交换信息,也可以通过这个对象获取或设置显卡适配器的相关配置信息。

顺便提一下,由于目前很多显卡都支持多显示器,即一块显卡可以连接一个以上的显示器,这就相当于一块显卡有多个适配器。在编写3D程序时,要支持多显示器,就必须为同一块显卡的每一个适配器各创建一个Device。在本章的所有例子中,均假定只有一个显卡适配器,所以只创建了一个Device。

(6) 在窗体的Load事件中添加代码:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim presentParams As PresentParameters = New PresentParameters

presentParams.Windowed = True'窗口模式

presentParams.SwapEffect = SwapEffect.Discard '交换

device = New Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, presentParams)

'设置窗体显示方式

Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)

'为了能响应键盘事件,该属性必须设为true

Me.KeyPreview = True

adapterInformationString = "F1:显示/隐藏提示信息" + vbLf + _

":旋转/不旋转" + vbLf + _

"上箭头:提高转速" + vbLf + _

"下箭头:降低转速" + vbLf + _

":退出"

Dim AdapterDetails As AdapterDetails = https://www.doczj.com/doc/af9881578.html,rmation

adapterInformationString += String.Format("显卡驱动程序:{0}" & vbLf, AdapterDetails.DriverName)

adapterInformationString += String.Format("显卡驱动程序版本:{0}" & vbLf, AdapterDetails.DriverVersion) Dim DisplayMode As DisplayMode = Manager.Adapters.Default.CurrentDisplayMode

adapterInformationString += String.Format("显示器当前分辨率:{0} X {1}" & vbLf, DisplayMode.Width, DisplayMode.Height)

adapterInformationString += String.Format("显示器当前颜色质量:{0}" & vbLf, DisplayMode.Format)

adapterInformationString += String.Format("显示器当前刷新频率(Hz):{0}" & vbLf, DisplayMode.RefreshRate) '创建D字体对象,显示字符用,这两句不能放在场景中,否则会很慢

Dim winFont As New System.Drawing.Font("Arial", 9, FontStyle.Regular)

d3dfont = New Microsoft.DirectX.Direct3D.Font(device, winFont)

d3dfont.PreloadText(adapterInformationString)

'创建顶点缓冲

VertexBuffer = New VertexBuffer(GetType(CustomVertex.PositionColored), _

3, device, Usage.Dynamic Or Usage.WriteOnly, _

CustomVertex.PositionColored.Format, Pool.Default)

AddHandler VertexBuffer.Created, AddressOf OnVertexBufferCreate

OnVertexBufferCreate(VertexBuffer, Nothing)

End Sub

代码中首先设置窗体样式,目的是为了重绘窗体时能得到连续变化的窗体图像;然后利用Manager命名空间下提供的类判断显卡和显示器相关的配置参数;第三步是定义一个三维字体对象,以便显示配置信息;最后在显存中创建了可以容纳3个顶点的顶点缓冲,并添加了OnVertexBufferCreate事件,该事件在每次重建顶点缓冲时都会自动触发,但是第一次需要直接调用。

为什么必须通过事件实现呢?这是因为在运行时,如果改变窗口的大小,设备就会自动重置。当创建的资源位于默认的内存池时(比如顶点缓冲),重置设备会释放缓冲。所以当改变窗口大小的时候,重置了device,释放了顶点缓冲。虽然Managed DirectX在重置device之后会自动的重建顶点缓冲。但是,由于原来的顶点缓冲已经被

释放,所以重建的顶点缓冲中已经没有了数据,也就无法将原来的内容重新绘制出来。

在重建顶点缓冲并准备好填充数据时,会自动触发顶点缓冲的Created事件,所以可以利用这个事件,让其重建缓冲时自动调用OnVertexBufferCreate重建顶点数据。这样就能看到连续的图像了。

(7) 直接添加代码:

Private Sub OnVertexBufferCreate(ByVal sender As Object, ByVal e As EventArgs)

'锁定顶点缓冲-->定义顶点-->解除锁定。

Dim buffer As VertexBuffer = CType(sender, VertexBuffer)

Dim verts As CustomVertex.PositionColored() = CType(buffer.Lock(0, 0), CustomVertex.PositionColored())

verts(0).Position = New Vector3(0.0F, 1.0F, 1.0F)

verts(0).Color = Color.BlueViolet.ToArgb()

verts(1).Position = New Vector3(-1.0F, -1.0F, 1.0F)

verts(1).Color = Color.GreenYellow.ToArgb()

verts(2).Position = New Vector3(1.0F, -1.0F, 1.0F)

verts(2).Color = Color.Red.ToArgb()

buffer.Unlock()

End Sub

在这个事件中,首先通过VertexBuffer对象的Lock方法锁定顶点缓冲,然后在顶点缓冲中构造一个三角形,三角形的三个顶点分别定义了不同的颜色,构造完成后再调用Unlock方法解除顶点缓冲。

每次顶点缓冲需要重新构造其数据时,系统都会自动触发这个事件。

(8) 添加设置矩阵参数的代码:

Private Sub SetupCamera()

'--------设置世界矩阵

Dim world As New Vector3(angle, angle / 2.0F, angle / 4.0F)

device.Transform.World = Matrix.RotationAxis(world, angle)

If enableRotator Then

angle += incrementAngle / (Math.PI)

End If

'--------设置投影矩阵

'纵横比

Dim aspectRatio As Single = 1

'只能显示nearPlane到farPlane之间的场景

Dim nearPlane As Single = 1

Dim farPlane As Single = 100

'视界

Dim fieldOfView As Single = Math.PI / 4.0F

device.Transform.Projection = Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, nearPlane, farPlane) '--------设置视图矩阵

Dim cameraPosition As New Vector3(0, 0, -5)

Dim cameraTarget As New Vector3(0, 0, 0)

Dim upDirection As New Vector3(0, 1, 0)

device.Transform.View = Matrix.LookAtLH(cameraPosition, cameraTarget, upDirection)

'--------不进行背面剔除

device.RenderState.CullMode = Cull.None

'--------不要灯光

device.RenderState.Lighting = False

End Sub

这段代码中用到了世界矩阵、投影矩阵和视图矩阵,不进行背面剔除,不使用灯光。

(9) 在窗体的Paint事件中添加代码:

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

device.Clear(ClearFlags.Target, System.Drawing.Color.AliceBlue, 1.0F, 0)

SetupCamera()

'--------------场景处理

device.BeginScene()

device.VertexFormat = CustomVertex.PositionColored.Format

device.SetStreamSource(0, VertexBuffer, 0)

device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1)

If showAdapterString Then

d3dfont.DrawText(Nothing, adapterInformationString, 25, 30, Color.Green)

End If

device.EndScene()

'---------------发送场景

device.Present()

'---------------强制重新调用Form1_Paint事件

If WindowState <> FormWindowState.Minimized Then

Me.Invalidate()

End If

End Sub

在介绍GDI+时,我们已经知道很多图形图像操作都是在窗体的Paint事件中处理的,在三维设计中,一样可以让所有操作都在Paint事件中处理。和GDI+编程不同,三维编程不是直接在屏幕坐标上绘制,而是和录像相似,首先要确定拍摄对象,设置好摄像机位置,选择拍摄的场景视界,然后才可以录制场景信息,此时在显示器上观察到的内容就相当于拍摄场景时在摄像机中观察到的内容。与实际拍摄不同的是显示的场景是我们自己设计的。实际上,在摄像机中看到的场景就是向顶点缓冲发送的内容。

在Paint事件中,使用Clear方法清除窗口的所有内容,并将其填充为实心的颜色。该方法的第一个参数指定了要填充的对象,第二个参数是要填充的颜色。

例子中使用了DrawPrimitives方法绘制场景,DrawPrimitives方法有三个参数,第一个参数是要绘制的基本图形的类型,以便知道每个基本图形需要几个顶点,例子中指定绘制的类型为三角形列,这样它就知道每个三角形需要三个顶点来绘制;第二个参数是从哪个顶点开始绘制,这个例子指定从第一个顶点开始(索引号为0);第三个参数是要绘制的基本图形的数量,由于本例中只画一个三角形,所以设为1。

设置场景后,必须使用Present方法更新显示。

调用EndSence方法的目的是通知Direct3D不再绘图了。每次调用BeginSence之后,在结束绘图前都必须调用这个方法。

这个事件的最后一句调用了Invalidate方法,这是三角形旋转后更新显示的关键。每个场景发送后,通过Invalidate方法使其不停地触发Paint事件,从而可以周而复始的重绘窗体。再利用不断变换角度,完成连续旋转的目的。

还有一个关键的地方,在默认模式下,Invalidate方法只会重新绘制代码中指定的部分,例子中使用的是this,即告诉系统只需要重新绘制当前窗体部分就行了。为了提高绘制效率,它不会重新处理其他的绘制过程。因此在默认模式下,看到的效果是闪烁的、不连续的。为了解决这个问题,必须修改默认模式,即在Form1的Load事件中添加:

Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)

这样就得到希望的效果了。

(10) 添加窗体的KeyDown事件代码:

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown Select Case (e.KeyCode)

Case Keys.Escape

Me.Close()

Case Keys.F1

showAdapterString = Not showAdapterString

Case Keys.F2

enableRotator = Not enableRotator

Case Keys.Up

If enableRotator Then

incrementAngle += 0.01F

End If

Case Keys.Down

If enableRotator And incrementAngle > 0.02F Then

incrementAngle -= 0.01F

End If

End Select

End Sub

(11) 按键编译并运行,一个漂亮的不停旋转的三角形就展现出来了。运行效果如图7-1所示。鼠标拖动右下角改变一下窗体的大小,观察三角形有什么变化。

观察运行的程序界面,可以看到显示器颜色位数显示的是一个字符串,字符串的字母和数字交替出现。字母表示了数据的类型,数字表示这种类型的数据所占的位数。常见字母有:

A―alpha、B―blue、X―unused、L―luminance、R―red、P―palette、G―green

每种类型所占的位数加起来,就是这种格式的总大小。比如X8R8G8B8,就是32

位的格式,红、绿、蓝各占8位,还有8位没有使用。

我们可能已经从这个例子中感觉到了,三维设计涉及到的新概念比较多,学习3D 技术的关键是要先搞清楚这些常用的概念及其用法,否则的话,就很难看懂代码,或者说很难入门,自然也就不知道编写3D 程序时应该如何下手了。

2 DirectX 基础知识

从例7-1中可以看出,理解三维设计中涉及的概念是非常重要的。如果对这些概念似懂非懂,即使花费再多的时间,也很难真正掌握实际的设计方法,进一步提高编写三维程序的能力也就成了一句空话。

本节从数学和Direct3D 相结合的角度,介绍需要掌握的基本知识。

2.1 左手坐标系与右手坐标系

3D 系统中的每一个点都由x,y,z 三个值组成。一般情况下,x 轴的正方向向右,y 轴的正方向向上。然后根据z 轴的正方向划分为两种坐标系,如果z 轴正方向为远离观察者而去的方向,即朝着屏幕里面的方向,这种坐标系叫左手坐标系,反之叫做右手坐标系。

Direct3D 默认使用左手坐标系。

在Direct3D 中,用Vector3表示一个三维向量,例如:

Vector3 a As new Vector3(1, 2, 2)

图7-1 例7-1的运行效果

7.2.2 设备

在Direct3D中,设备(Device)是指显卡提供的接口,可以把这个类假想为显卡中的某个适配器。场景的所有图形对象都依赖于Device对象。一台计算机中至少有一个Device对象,在Managed Direct3D里,可以控制任意多个Device对象。所有三维图形图像等信息均可以通过Device对象处理,该类常用的构造函数为: Public Sub New(ByVal adapter As Integer, _

ByVal deviceType As Microsoft.DirectX.Direct3D.DeviceType, _

ByVal renderWindow As System.Windows.Forms.Control, _

ByVal behaviorFlags As Microsoft.DirectX.Direct3D.CreateFlags, _

ByVal ParamArray presentationParameters() As Microsoft.DirectX.Direct3D.PresentParameters) 各参数的含义如下:

参数

adapter:表示使用显卡的第几个适配器,一般使用第一个(索引号为0)。

deviceType:告诉Direct3D要创建哪种类型的Device。一般用DeviceType.Hardware。

renderWindow:表示设备绑定到的对象窗口。一般使用当前窗口。

behaviorFlags:描述创建device之后处理顶点的方式。常用方式有两种,一种是使用HardwareVertexProcessing,即使用显卡自带的图形处理器(GPU,Graphic Processing Unit),使用这个选项处理速度非常快,不过这类显卡价格较贵,一般的显卡没有这个功能;另一种是使用SoftwareVertexProcessing,即利用本机内存模拟显卡图形处理功能,这个选项对显卡的要求不高,使用一般的显卡即可,但是执行速度要慢一些。 presentationParameters:表示设备把数据呈现到显示器的方式。这个选项比较多,目前我们只关心Windowed属性和SwapEffect属性。

1) Windowed属性:呈现形式是全屏还是窗口模式。

2) SwapEffect属性:控制显存中缓冲区处理的方式。常用的是SwapEffect.Discard,即如果上次要显示的缓冲区数据还没有处理完毕,就自动丢弃,并直接填充新内容。

另一个常用的方式是SwapEffect.Flip,运行时会创建一个后缓冲区,在显示场景时采用前后缓冲区快速翻动方式。

为了能理解前后缓冲区的作用,我们先看看电影播放的原理,电影本来是一幅幅图片组成的,当它以每秒24幅的速度连续播放时,如果每幅图像之间的差别很小,由于人眼的滞留作用,人们看到的画面就是连续的。DirectX 的工作原理与此类似。可以事先定义两个缓冲区页面,一个叫前缓冲区页面,用于显示,另一个叫后缓冲区页面,用于在显示前缓冲区的同时填充下一个将要显示的内容。当把前缓冲区的页面内容送显示器时,系统同时将下一幅要显示的内容绘制到后缓冲区页面中,然后快速的把它翻动到前缓冲区,并重复这个过程。这样在显示器上看到的就是连续的图像了。与电影不同的是,计算机每秒能绘制的页面数要远远大于24幅。

所以,程序需要不停地循环填充后缓冲区的内容,每次循环都要清除后缓冲区,并把应该绘制的内容绘制到该缓冲区,然后由系统自动把它翻动到前缓冲区,再进入下一次循环,直到结束。

2.3 顶点与顶点缓冲

在数学上,一般只需要描述点的位置,但是在Direct3D中,除了点的位置外,还需要保存该点的颜色以及法线(Normal)、纹理(Texture)等其他信息,为了与数学上一般的点区分,Direct3D把坐标系中的每一个点称之为顶点(Vertex)。

顶点缓冲指在显存或内存中开辟的用于保存顶点的缓冲区。顶点缓冲可以保存任何的顶点类型。将顶点保存在顶点缓冲区中后,显卡就可以根据提供的参数对其进行各种变换、绘制等操作。

创建顶点缓冲的常用形式为:

Public Sub New ( _

typeVertexType As Type, _

numVerts As Integer, _

device As Device, _

usage As Usage, _

vertexFormat As VertexFormats, _

pool As Pool _

)

其中:

vertexType:指定要创建的顶点类型。该值可以是CustomVertex类中的顶点结构类型,也可以是自定义的顶

点类型;

numVerts:顶点个数。

device:使用的显卡对象。

usage:如何使用顶点缓冲。

vertexFormat:定义储存在顶点缓冲中的顶点格式。

pool:定位顶点缓冲使用的内存池位置。

7.2.4 Mesh对象

有了顶点,再通过顶点之间封闭的连线,就可以构成面了。任何一个物体,无论表面多么平滑,其视图都可以用三角形构成的面组合得到。如果只画出三角形的连线,就可以看出一个物体的框架是由许多个三角形构成的网格组成,Direct3D把由三角形网格组成的对象叫做Mesh对象。

7.2.5 法线

在数学上,法线(Normal)指垂直于面的向量。在Direct3D中,每个顶点也都可以有对应的法线,而且还可以设置每个顶点法线的方向。顶点法线和面法线对计算光照以及着色模式(Shading mode)非常重要。面法线一般用于Flat着色,得到物体的立体感效果;而顶点法线则一般用于Gouraud着色,用于控制光照及纹理,使物体看起来很圆滑。

7.2.6 纹理与纹理映射

在20世纪80年代和90年代初的3D程序中,很多物体的外表看起来都是发亮的塑胶质感的样子,感觉很不真实。在Direct3D中,使用纹理(Texture)可以轻松地解决这个问题,甚至物体很小的细节部分,例如子弹孔、不规则表面、生锈的部分、裂缝、指纹、钉在木板上的图钉等等都可以通过纹理实现。通过纹理,还可以将一幅图贴在几何体的表面提供复杂的视觉效果。从一般概念上讲,纹理指由各种色彩的像素构成的简单位图。但是在Direct3D 中,纹理则指可以映射到一个或者多个面上的特殊的图像。把纹理映射到目标几何体上的过程叫纹理映射(Texture-Mapping)。

因为纹理是二维的,所以仅需要两个坐标值:u和v。u是横向坐标值,v是纵向坐标值,u和v的取值应该在0和1之间,左上角是(0,0),右下角是(1,1)。

7.2.7 世界矩阵、投影矩阵与视图矩阵

矩阵是由数字组成的矩形数组,矩阵中的每个元素都有一个数字或表达式。通过矩阵的加减乘除运算,可以对3D对象中的顶点进行移动、旋转、缩放等操作。

在DirectX中,每个矩阵都由4行4列组成。构造一个向量前,必须先构造一个变换矩阵。将一个4×4的矩阵乘以一个表示3D数据的向量,比如与一个顶点向量相乘,即得到新的变换后的向量。

如果需要进行一系列变换,可以为每一个动作(缩放、旋转、平移)各创建一个临时矩阵,然后对向量分别进行相应的变换;还有一个办法就是先将这些矩阵相乘,然后把乘积的结果作为变换矩阵。

为了简化编程,DirectX中已经分别提供了缩放、旋转、平移等方法,我们只需要调用这些方法得到变换后的向量即可。

完成既缩放又旋转这种复合变换,则需要两个矩阵:一个用来旋转,一个用来缩放;然后把两个矩阵相乘,得到一个新的复合矩阵;最后利用这个新的矩阵来变换顶点。

注意,矩阵相乘不满足交换律。

在DirectX中,有三种特殊类型的矩阵:世界矩阵(World Matrix)、视图矩阵(View Matrix)和投影矩阵(Projection Matrix)。

我们可以通过修改对象在世界矩阵中的坐标实现旋转、缩放或平移操作。所有这些变换都是相对于原点(0, 0, 0)的。单一的变换(例如平移或缩放等)可以组合起来,形成更复杂的变换;但要注意各种变换的顺序,矩阵1乘以矩阵2和矩阵2乘以矩阵1结果是不同的。

要旋转两个对象,一个关于x轴,一个关于y轴,则应该先完成x轴的变换,然后渲染第一个对象;再完成y 轴的变换,然后渲染第二个对象。

与屏幕坐标相比,可以把世界坐标设想为一个无限大的三维笛卡儿坐标。对象可以被放到这个“世界”的任意位置。

视图矩阵指摄像机拍摄的场景,或者说人们在摄像机前看到的图像。摄像机在世界空间中有一个位置,还有一个观察点。例如,可以把摄像机悬置于某个对象的上面(摄像机位置),把镜头对准那个对象的中心(观察点)。也可以指定哪面是上面,例如指定y轴的正方向是上面。

投影矩阵可以被想象成摄像机的镜头,该矩阵指定了观察区域和前、后裁剪平面。

投影变换定义了场景被怎样投影到显示器。最简单的产生投影矩阵的方法就是使用Matrix类的PerspectiveFovLH方法。即使用左手坐标系创建一个正对场景的透视投影变换。

投影变换描绘了场景的视界,即可见部分。视界是可视角度和前裁剪面(Near Plane)与后裁剪面(Far Plane)中间的一段区域,在这个区域内的即是可见部分。

例如图7-2,摄像机位于“o”点,可见部分为ABCD--A'B'C'D',ABCD为后裁剪面,A'B'C'D'为前裁剪面。farPlane 就是锥体的底面,而nearPlane则是横截面。fieldOfView参数描绘了锥体的角度。

aspectRatio类似于电视的高宽比,比如,宽银幕电视的高宽比是1:85。可以用可视区域的宽度来比上高度得出这个值。DirectX3D只绘制在这个可见区域中的物体。

图7-2 前剪裁面与后剪裁面

7.2.8 背面剔除

在介绍Mesh对象时已经提过,所有的几何形状都可以由三角形顶点构成的面组成。背面剔除(Backface Culling)的实际含义就是如何剔除每一个由顶点按照顺时针或逆时针方向依次连线构成的三角形面。剔除方式有三种:一种是不剔除,即全部渲染;第二种方式是剔除顺时针构成的面;第三种方式是剔除逆时针构成的面。

如果不指定剔除方式,Direct3D默认剔除逆时针方向构成的面,即只渲染按顺时针方向排列的顶点构成的三角形面。

例如,对于图7-3,如果采用逆时针剔除,则只显示1、2、3构成的三角形面;如果采用顺时针剔除,则只显示2、3、4构成的三角形面;如果不剔除,则全部显示。

背面剔除在Direct3D中有什么用呢?我们知道,当观察一个不透明的物体时,背面的部分是看不见的。系统在渲染物体的表面时,在正面是顺时针的三角形,旋转到背面时就变成了逆时针的,因此也就不需要再渲染,即可以被剔除掉,从而节省了大量内存,提高了程序执行的效率。

7.3 Primitive

Primitive指Dirct3D支持的最基本的图形,这些基本图形是构成其他各种复杂图形的基本元素,因此也叫图元。在Direct3D中,有六种Primitive,分别是:点列、线列、线带、三角形列、三角形带和三角扇形。

PointList:点列。顶点序列中的每个顶点均单独绘制。

LineList:线列。绘制时顶点序列中的每两个顶点作为一组连成一条单独的直线,序列中的每个顶点只使用一次。

LineStrip:线带。绘制时从第一个顶点开始,依次将顶点序列中的各个顶点用直线连接起来。除第一个顶点和最后一个顶点只使用一次外,中间的其他顶点均使用两次。

TriangleList:三角形列。绘制时顶点序列中的每三个顶点作为一组组成一个单独的三角形,序列中的每个顶点只使用一次。

TriangleStrip:三角形带。绘制的结果为一系列相连的三角形,每两个相邻的三角形共享两个顶点。

TriangleFan:三角扇形。与三角形带相似,不过所有的三角形都共享一个顶点。

图7-4直观的画出了由六个顶点组成的各类图元的形式。

图7-4 Direct3D中的六种Primitive

【例2】演示Primitive的绘制方法。

(1) 新建一个Windows应用程序,使用默认的窗体名称。

(2) 在【项目】?【添加引用】?在【.net】选项下同时选中Microsoft.DirectX、Microsoft.DirectX.Direct3D 和Microsoft.DirectX.Direct3DX,注意选择的版本要和本章开头列出的版本一致,单击【确定】。

(3) 在命名空间的上方,添加引用代码:

Imports Microsoft.DirectX

Imports Microsoft.DirectX.Direct3D

(4) 在构造函数上方添加字段声明:

Dim device As Device

Dim vertexBuffer As VertexBuffer

Const vertexNumber As Integer = 18

Dim primitivesType As String = "点列"

'3D字体,用于显示提示信息的字体

Dim d3dfont As Microsoft.DirectX.Direct3D.Font

'要显示的字符串

Dim helpString As String

'是否在窗体中显示字符串

Dim showHelpString As Boolean = True

Dim angle As Single = 0.0F

Dim enableRotator As Boolean = False

Dim rotatorXYZ As Integer = 0

Dim enableCullMode As Boolean = False

在这个例子中,我们选择的顶点个数是24,选择的原则是顶点的个数要同时能被2和3整除。以保证无论那种图元都能都被正确渲染。

(5) 直接添加代码:

Private Sub SetupCamera()

'设置投影矩阵

Dim fieldOfView As Single = Math.PI / 4

Dim aspectRatio As Single = Me.Width / Me.Height

Dim nearPlane As Single = 1.0F

Dim farPlane As Single = 100.0F

device.Transform.Projection = _

Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, nearPlane, farPlane)

'设置视图矩阵

Dim cameraPosition As New Vector3(0, 0, -30.0F)

Dim cameraTarget As New Vector3(0, 0, 0)

Dim upDirection As New Vector3(0, 1, 0)

device.Transform.View = Matrix.LookAtLH(cameraPosition, cameraTarget, upDirection)

'点的大小

device.RenderState.PointSize = 4.0F

'不要灯光

device.RenderState.Lighting = False

'背面剔除

If enableCullMode Then

device.RenderState.CullMode = Cull.CounterClockwise

Else

device.RenderState.CullMode = Cull.None

End If

End Sub

Private Sub OnVertexBufferCreate(ByVal sender As Object, ByVal e As EventArgs)

'锁定顶点缓冲-->定义顶点-->解除锁定。

Dim buffer As VertexBuffer = CType(sender, VertexBuffer)

Dim verts As CustomVertex.PositionColored() = CType(buffer.Lock(0, 0), CustomVertex.PositionColored()) Dim random As New Random()

For i As Integer = 0 To 17

Dim x As Single = vertexNumber * (random.NextDouble() - 0.5F)

Dim y As Single = vertexNumber * (random.NextDouble() - 0.5F)

Dim z As Single = vertexNumber * (random.NextDouble() - 0.5F)

verts(i).Position = New Vector3(x, y, z)

Dim color As Color = Drawing.Color.FromArgb(random.Next(Byte.MaxValue), _

random.Next(Byte.MaxValue), random.Next(Byte.MaxValue))

verts(i).Color = color.ToArgb()

Next

buffer.Unlock()

End Sub

(6) 在窗体的Load事件中添加代码:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim presentParams As New PresentParameters()

presentParams.Windowed = True

presentParams.SwapEffect = SwapEffect.Discard

device = New Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, presentParams) Me.Width = 570

Me.Height = 430

Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)

Me.KeyPreview = True

helpString = ":退出" + vbLf + ":显示/隐藏提示信息" + vbLf + _

":变换顶点" + vbLf + _

":旋转/不旋转" + vbLf + _

":旋转轴(x轴、y轴、z轴)" + vbLf + _

":背面剔除/不剔除" + vbLf + _

"<1>:点列" + vbLf + _

"<2>:线列" + vbLf + _

"<3>:线带" + vbLf + _

"<4>:三角形列" + vbLf + _

"<5>:三角形带" + vbLf + _

"<6>:三角扇形"

Dim winFont As System.Drawing.Font = New System.Drawing.Font("宋体", 9, FontStyle.Regular)

d3dfont = New Microsoft.DirectX.Direct3D.Font(device, winFont)

d3dfont.PreloadText(helpString)

'创建顶点缓冲

vertexBuffer = New VertexBuffer(GetType(CustomVertex.PositionColored), _

vertexNumber, _

device, Usage.Dynamic Or Usage.WriteOnly, _

CustomVertex.PositionColored.Format, Pool.Default)

AddHandler vertexBuffer.Created, AddressOf OnVertexBufferCreate

OnVertexBufferCreate(vertexBuffer, Nothing)

End Sub

(7) 在窗体的Paint事件中添加代码:

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint SetupCamera()

device.Clear(ClearFlags.Target, System.Drawing.Color.AliceBlue, 1.0F, 0)

device.BeginScene()

device.VertexFormat = CustomVertex.PositionColored.Format

device.SetStreamSource(0, vertexBuffer, 0)

Select Case primitivesType

Case"点列"

device.DrawPrimitives(PrimitiveType.PointList, 0, vertexNumber)

Case"线列"

device.DrawPrimitives(PrimitiveType.LineList, 0, vertexNumber / 2)

Case"线带"

device.DrawPrimitives(PrimitiveType.LineStrip, 0, vertexNumber - 2)

Case"三角形列"

device.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexNumber / 3)

Case"三角形带"

device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, vertexNumber - 2)

Case"三角扇形"

device.DrawPrimitives(PrimitiveType.TriangleFan, 0, vertexNumber - 2)

End Select

If showHelpString Then

d3dfont.DrawText(Nothing, helpString, 25, 30, Color.Green)

End If

If enableRotator Then

Dim world As Vector3

If rotatorXYZ = 0 Then

world = New Vector3(angle, 0, 0)

ElseIf rotatorXYZ = 1 Then

world = New Vector3(0, angle, 0)

Else

world = New Vector3(0, 0, angle)

End If

device.Transform.World = Matrix.RotationAxis(world, angle)

angle += 0.05F / Math.PI

End If

device.EndScene()

device.Present()

If WindowState <> FormWindowState.Minimized Then

Me.Invalidate()

End If

End Sub

(8) 在窗体的KeyDown事件中添加代码:

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown Select Case e.KeyCode

Case Keys.Escape

Me.Close()

Case Keys.F1

showHelpString = Not showHelpString

Case Keys.F2

OnVertexBufferCreate(vertexBuffer, Nothing)

Case Keys.F3

enableRotator = Not enableRotator

Case Keys.F4

rotatorXYZ = (rotatorXYZ + 1) Mod 3

Case Keys.F5

enableCullMode = Not enableCullMode

Case Keys.D1

primitivesType = "点列"

Case Keys.D2

primitivesType = "线列"

Case Keys.D3

primitivesType = "线带"

Case Keys.D4

primitivesType = "三角形列"

Case Keys.D5

primitivesType = "三角形带"

Case Keys.D6

primitivesType = "三角扇形"

End Select

End Sub

(9) 按键编译并运行。选择数字1-6观察绘制的基本图形,每次均用鼠标拖动右下角改变一下窗体的大小,观察图形有什么变化。

图7-5为运行该程序得到的部分图形效果。

(a) 点列(b) 线列

这时,如果让绘制的图形旋转起来,然后分别选择4、5、6观察旋转效果,我们会发现一个问题:绘制的图形在旋转时看起来眼花缭乱,感觉层次感不是很强,看不清到底是如何旋转的。

为了解决这个问题,需要引入一个新概念:深度缓冲。

深度缓冲(Depth Buffer)也就是通常所说的z-buffer。深度信息用于在光栅化时决定像素之间的替代关系,平常我们都是用视点到观察点的距离来衡量“深度”,这样带有较大深度值的像素就会被带有较小深度值的像素替代,即远处的物体被近处的物体遮挡住了。在Direct3D 中,“深度”的方向为从摄像机位置到观察点的方向,一般为从z 轴的负坐标到正坐标的方向,即指向显示器屏幕里面的方向。

在本章以前的例子中,程序都没有使用深度缓冲,即光栅化时没有遮挡住任何象素,当然没有层次感了。 (10) 将Form1_Load 方法的代码修改为如下形式:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase .Load Dim presentParams As New PresentParameters()

presentParams.Windowed = True

presentParams.SwapEffect = SwapEffect.Discard

presentParams.AutoDepthStencilFormat = DepthFormat.D16

presentParams.EnableAutoDepthStencil = True

……

然后将Form1_Paint 中的device.Clear 方法改为:

device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.AliceBlue, 1.0F, 0)

键重新运行程序,观察各个基本图形旋转的效果。

可见,把EnableAutoDepthStencil 设置为true 就可以为device 打开深度缓冲,使用DepthFormat 指定AutoDepthStencilFormat 枚举成员。在DepthFormat 枚举中,有很多枚举选项,选择的深度缓冲越大,能存储的深度数据也越多,但这是以牺牲性能为代价的。一般情况下,使用最小的值就可以了。由于目前大部分显卡都支持最小的16位深度缓冲,所以只需要使用DepthFormat.D16即可。

图7-5 六种基本的Primitive 运行效果

(a) 点列 (b) 线列 (c) 线带 (d) 三角形列 (e) 三角形带 (f) 三角扇形 (e) 三角形带 (f) 三角扇形

(c) 线带 (d) 三角形列

加入深度缓冲后,还应该在调用device的clear方法时同时清除深度缓冲,这样才能得到希望的效果。

7.4 Mesh

任何一个物体,不论是表面多么平滑的物体,其视图都可以用三角形构成的面组合得到。如果只画出三角形的连线,可以看出一个物体的框架是由许多个三角形构成的网格组成,Direct3D把由三角形网格组成的对象叫做Mesh 对象。

在Direct3D中,有一个Mesh类,使用它可以存储任何类型的图形数据,但一般主要用它封装复杂的模型。Mesh 类提供了构造几何体的方法,同时也提供了用来提高渲染物体性能的方法。

在本章开头介绍的版本中,Mesh对象位于Direct3D扩展库中。要使用Mesh类,必须添加对Direct3DX.dll 程序集的引用。

Mesh类中提供了几个静态方法,可以用来直接创建或加载不同的Mesh对象模型。

1) TextFromFont方法。创建包含指定文本的Mesh对象。常用形式为:

Public Shared Function TextFromFont(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal font As System.Drawing.Font, ByVal text As String, ByVal deviation As Single, ByVal extrusion As Single) As Microsoft.DirectX.Direct3D.Mesh

其中:

device:代表显卡适配器的Device对象;

font:创建Mesh的System.Drawing.Font字体对象;

text:文本字符串;

deviation:立体字偏转大小;

extrusion:立体字阴影部分的大小。

2) Box方法。创建立方体盒子。常用形式为:

Public Shared Function Box(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal width As Single, ByVal height As Single, ByVal depth As Single) As Microsoft.DirectX.Direct3D.Mesh

其中:

device:代表显卡适配器的Device对象;

width:x轴坐标大小;

height:y轴坐标大小;

depth:z轴坐标大小。

3) Cylinder方法。创建圆筒。常用形式为:

Public Shared Function Cylinder(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal radius1As Single, ByVal radius2 As Single, ByVal length As Single, ByVal slices As Integer, ByVal stacks As Integer) As Microsoft.DirectX.Direct3D.Mesh 其中:

device:代表显卡适配器的Device对象;

radius1:z轴负方向端点的半径,该值必须大于或等于零;

radius2:z轴正方向端点的半径,该值必须大于或等于零;

length:沿z轴方向的圆筒长度;

slices:垂直于z轴方向绕z轴构成圆筒面的线的条数;

stacks:沿z轴方向构成圆筒面的线的条数。

4) Polygon方法。创建多边形。常用形式为:

Public Shared Function Polygon(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal length As Single, ByVal sides As Integer) As Microsoft.DirectX.Direct3D.Mesh

其中:

device:代表显卡适配器的Device对象;

length:每条边的长度;

sides:边数,该值必须大于或等于3。

5) Sphere方法。创建球形。常用形式为:

Public Shared Function Sphere(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal radius As Single, ByVal slices As Integer, ByVal stacks As Integer) As Microsoft.DirectX.Direct3D.Mesh

其中:

device:代表显卡适配器的Device对象;

radius:小球半径;

slices:垂直于z轴方向绕z轴构成球表面的线的条数;

stacks:沿z轴方向构成球表面的线的条数。

6) Torus方法。创建圆环。常用形式为:

Public Shared Function Torus(ByVal device As Microsoft.DirectX.Direct3D.Device, ByVal innerRadius As Single, ByVal outerRadius As Single, ByVal sides As Integer, ByVal rings As Integer) As Microsoft.DirectX.Direct3D.Mesh

其中:

device:代表显卡适配器的Device对象;

innerRadius:圆环内半径;

outerRadius:圆环外半径;

sides:边数,该值必须大于或等于3;

rings:环数,该值必须大于或等于3。

如何渲染mesh呢?在渲染Mesh对象时,系统会自动根据属性缓冲的大小,将Mesh对象划分为一系列的子集(subsets),同时使用一个叫做DrawSubset的方法来渲染该对象。例如:

mesh.DrawSubset(0);

注意,使用Mesh类直接创建的基本图形只有一个索引号为零的子集。

【例3】演示Mesh对象的绘制方法。

(1) 新建一个Windows应用程序,使用默认的窗体名称。

(2) 在【项目】?【添加引用】?在【.net】选项下同时选中Microsoft.DirectX、Microsoft.DirectX.Direct3D 和Microsoft.DirectX.Direct3DX,注意选择的版本要和本章开头列出的版本一致,单击【确定】。

Imports Microsoft.DirectX

Imports Microsoft.DirectX.Direct3D

Public Class Form1

Dim device As Device

Dim boxMesh As Mesh

Dim cylinderMesh As Mesh

Dim polygonMesh As Mesh

Dim sphereMesh As Mesh

Dim teapotMesh As Mesh

Dim torusMesh As Mesh

Dim textMesh As Mesh

Dim d3dfont As Microsoft.DirectX.Direct3D.Font

Dim helpString As String

Dim showHelpString As Boolean = True

Dim angle As Single = 0.0F

Dim rotatorXYZ As Integer = 0

Dim enableRotator As Boolean = True

Dim enableCullMode As Boolean = False

Dim enableSolidMode As Boolean = False

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '创建Device对象

Dim presentParams As New PresentParameters()

presentParams.Windowed = True

presentParams.SwapEffect = SwapEffect.Discard

device = new Device(0, DeviceType.Hardware, me, CreateFlags.SoftwareVertexProcessing, presentParams) '设置窗体

Me.Width = 575

Me.Height = 475

Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)

Me.KeyPreview = True

'绘制帮助文本

helpString = ":退出" + vbLf + _

":显示/隐藏提示信息" + vbLf + _

":实心/线框" + vbLf + _

":旋转/不旋转" + vbLf + _

":旋转轴(x轴、y轴、z轴)" + vbLf + _

":背景剔除/不剔除"

Dim winFont As New System.Drawing.Font("宋体", 12, FontStyle.Regular)

d3dfont = New Microsoft.DirectX.Direct3D.Font(device, winFont)

d3dfont.PreloadText(helpString)

'创建Mesh对象

textMesh = Mesh.TextFromFont(device, New System.Drawing.Font("宋体", 12), "Mesh对象展示", 1.0F, 0.3F) '创建一个文本网络

boxMesh = Mesh.Box(device, 2.0F, 2.0F, 2.0F) '创建一个立方体网络

cylinderMesh = Mesh.Cylinder(device, 1.0F, 0.5F, 2.0F, 10, 10) '创建一个圆柱体网格

polygonMesh = Mesh.Polygon(device, 0.4F, 20) '创建一个多边形网络

sphereMesh = Mesh.Sphere(device, 1.0F, 20, 10) '创建一个球体网络

teapotMesh = Mesh.Teapot(device) '创建一个茶壶网络

torusMesh = Mesh.Torus(device, 0.3F, 1.0F, 20, 20) '创建一个圆环网络

End Sub

Private Sub SetupCamera()

'设置投影转换矩阵

Dim fieldOfView As Single = Math.PI / 4

Dim aspectRatio As Single = Me.Width / Me.Height

Dim nearPlane As Single = 1.0F

Dim farPlane As Single = 100.0F

device.Transform.Projection = Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, nearPlane, farPlane) '设置视图转换矩阵

Dim cameraPosition As New Vector3(0, 0, -18.0F)

Dim cameraTarget As New Vector3(0, 0, 0)

Dim upDirection As New Vector3(0, 1, 0)

device.Transform.View = Matrix.LookAtLH(cameraPosition, cameraTarget, upDirection)

device.RenderState.Lighting = False'设置打开光照

device.RenderState.CullMode = IIf(enableCullMode, Cull.CounterClockwise, Cull.None) '设置剔除背影

device.RenderState.FillMode = IIf(enableSolidMode, FillMode.Solid, FillMode.WireFrame) '设置填充模式 End Sub

'设置世界转换矩阵

Private Sub SetWorldTransform(ByVal x As Single, ByVal y As Single, ByVal z As Single)

Dim world As Vector3

If rotatorXYZ = 0 Then

world = New Vector3(angle, 0, 0)

ElseIf rotatorXYZ = 1 Then

world = New Vector3(0, angle, 0)

Else

world = New Vector3(0, 0, angle)

End If

'定义围绕轴旋转矩阵

device.Transform.World = Matrix.RotationAxis(world, angle) * Matrix.Translation(x, y, z) If enableRotator = True Then

angle += 0.03F / Math.PI

End If

End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint SetupCamera()

device.Clear(ClearFlags.Target, Color.DarkSeaGreen, 1.0F, 0) '填充背景

device.BeginScene()

'绘制文本

SetWorldTransform(0, 5, 0)

textMesh.DrawSubset(0)

' 绘制立方体

SetWorldTransform(-5, 0, 0)

boxMesh.DrawSubset(0)

' 绘制圆筒

SetWorldTransform(0, 0, 0)

cylinderMesh.DrawSubset(0)

'绘制多边形

SetWorldTransform(5, 0, 0)

polygonMesh.DrawSubset(0)

'绘制球形

SetWorldTransform(-5, -5, 0)

sphereMesh.DrawSubset(0)

'绘制茶壶

SetWorldTransform(0, -5, 0)

teapotMesh.DrawSubset(0)

' 绘制圆环

SetWorldTransform(5, -5, 0)

torusMesh.DrawSubset(0)

'绘制帮助文本

If showHelpString = True Then

d3dfont.DrawText(Nothing, helpString, 25, 30, Color.Tomato)

End If

device.EndScene()

device.Present()

If WindowState <> FormWindowState.Minimized Then

Me.Invalidate()

End If

End Sub

Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown Select Case (e.KeyCode)

Case Keys.Escape

Me.Close()

Case Keys.F1

showHelpString = Not showHelpString

Case Keys.F2

enableSolidMode = Not enableSolidMode

Case Keys.F3

enableRotator = Not enableRotator

Case Keys.F4

rotatorXYZ = (rotatorXYZ + 1) Mod 3

Case Keys.F5

enableCullMode = enableCullMode

End Select

End Sub

End Class

(3) 按键编译并运行,图7-6为运行该程序得到的界面效果。分别选择功能键观察绘制的基本图形有什么变化。

图7-6 例7-3的运行界面

如果按键将Mesh对象变为实心,即渲染各个表面,我们会发现显示的效果就非常差了,几乎看不出球形是如何旋转的,而且所有Mesh对象的颜色也全部是白色的,在代码中也找不到更改的办法。

因此,我们还必须再学习一个新的概念:灯光与材质。

7.5 灯光与材质

在DirectX中,我们可以给场景创建不同类型的光,使场景看起来更真实。当然,DirectX中的光只是在近似地模拟自然界的光。

自然界中,光由光源(如灯泡)发出,然后沿直线传播,直到光能消耗完毕或传入眼睛;光在遇到物体时会发生反射,每次反射都会有能量的消耗;实际上,光可以在物体间反射千百万次,而且光滑表面会比不光滑的表面反射更多的光。这一切如果全算进来的话,计算量是巨大的。所以,为了提高效率和速度,DirectX只是在近似地模仿自然界的光。

1. 光的类型

在DirectX中,有四种类型的光,分别是环境光、直射光、点光源和聚光灯。

人们看到的物体的颜色可以认为是光线照射到物体上后反射到人的眼睛的颜色。如果没有任何光线,我们看到

的将是漆黑一片。为了能看见计算机屏幕上显示的物体,Direct3D首先需要提供一种没有位置、没有方向、没有衰减、所有光线都均匀不变地从各个方向照射到物体上的光,这就是环境光。

在DirectX中,默认情况下Device对象的灯光是打开的,但是为了使程序看起来更清晰,一般在代码中加上: device.RenderState.Lighting = true

灯光打开后,系统默认提供的光就是黑色的环境光,即相当于夜晚。这种情况下,如果物体本身不发光,不论物体本身的颜色是什么,我们看到的都会是黑色。当然,我们希望看到的是类似于白天的情况,因此,需要设置环境色为白色,例如:

device.RenderState.Ambient = Color.White

为了体现各种光照效果,系统默认的环境光比较暗,类似于在没有其他灯光的房间里感觉的光线效果。在实际环境中,如果希望房间内比较亮一些,还要打开日光灯。在DirectX中,与实际环境相似,要得到较好的效果,还需要设置其他类型的光,可选的灯光类型有:直射光、点光源和聚光灯。灯光的个数可以根据亮度需要使用一个或者多个,具体可以同时使用多少个灯光,则受材质个数限制。

三种类型的光中,均有以下两种属性:

◆ Diffuse属性:表示漫射光颜色,是一种有方向的光,其方向就是Direction属性指定的方向。例如:

device.Lights(0).Diffuse = Color.White

◆ Ambient属性:环境光颜色,是一种无方向的光,例如:

device.Lights(0).Ambient = Color.Black

注意:如果指定了灯光的环境光颜色,则实际光的颜色为灯光的环境光颜色和通用的环境光颜色的混合色,至于混合后是什么颜色,由三基色原理决定。

为了避免使用复杂,一般情况下,不论是哪种类型的光,我们均设置其颜色为白色。这样,物体的实际颜色就由它自身提供的反射色决定了。否则,我们就必须要知道哪种颜色和哪种颜色混合,从而得到什么颜色,这样才能正确的使用。

除了以上两种颜色外,对不同类型的灯光,还需要设置与类型相关的其他属性。

1) 直射光

直射光有方向,没有位置,也没有范围和衰减。场景中的所有对象都会从同样的方向接收到同样的直射光。一般情况下,只需要为直射光设置Direction属性,例如:

device.Lights(0).Direction = new Vector3(0, 0, 1)

该语句的意思是设置首个直射光的方向为z轴正方向。

2) 点光源

点光源没有方向,但是有光照范围,有光的衰减。例如灯泡发出的光就可以认为是点光源。

一般情况下,只需要为点光源设置位置属性,例如:

device.Lights(0).Position = new Vector3(0, 0, 0)

该语句的意思是设置首个点光源的位置为世界坐标的原点。

3) 聚光灯

聚光灯有位置、方向、范围、发光内径和发光外径,光照强度还会随距离而衰减。聚光灯的恰当的例子就是手电筒或者剧场里用来照亮舞台上人物的灯光。

注意,三种类型的光中,不论使用哪种光,都会增加系统的计算复杂度,按照复杂度从小到大排序分别为:直射光、点光源、聚光灯。

2. 材质

材质(Material)用于描述物体的反光性能,使它的表面看起来有没有光泽和带有什么颜色。可以认为材质的颜色就是人们在自然界中看到的物体的颜色。在不同类型的光照射下,使用的材质不同,物体反射的光也不同。例如,如果把红色的灯光照在淡蓝色的表面上,它就会呈献出柔和的紫色。

创建一个材质并设置光照射到物体表面上反射的颜色后,就可以设置Device对象的Material属性,让其使用创建的材质。这样Direct3D就知道渲染时使用哪种材质数据。

材质的环境反射色(Ambient)表示物体本身在光照射下反射的颜色,其他灯光照射到物体表面上后,物体实际的颜色则是灯光颜色、环境颜色和材质颜色的混合色。

注意,当材质的环境反射色为黑色时,表示物体的颜色由物体本身的颜色决定,其他光不影响材质本身的颜色;当环境反射色变浅时,其他光就会照亮材质,并将光的颜色和材质的颜色混和起来,从而得到人们看到的混合后的颜色。

描述材质的常见属性有:

Diffuse:物体的漫反射色,如果灯光为白色,则漫反射色就是灯光照射部分物体的颜色。

Ambient:物体的环境反射色,如果环境色为白色,反射色为非黑色的其他颜色,则物体的颜色由环境反射色决定。

Specular:物体的镜面反射与高光强度。设用这个属性可以使物体看起来发亮。

Emission:物体自发光颜色。

【例4】灯光、材质、Primitive和Mesh综合举例。

(1) 新建一个名为LineSphereExample的Windows应用程序,使用默认的窗体名称。

(2) 在【项目】?【添加引用】?在【.net】选项下同时选中Microsoft.DirectX、Microsoft.DirectX.Direct3D 和Microsoft.DirectX.Direct3DX,注意选择的版本要和本章开头列出的版本一致,单击【确定】,将对三个文件的引用加入到当前项目中。

(3) 在命名空间的上方,添加引用代码:

Imports Microsoft.DirectX

Imports Microsoft.DirectX.Direct3D

(4) 在构造函数上方添加字段声明:

Dim device As Device

Dim d3dfont As Microsoft.DirectX.Direct3D.Font

Dim helpString As String

Dim showHelpString As Boolean = True

Dim angle As Single = 0

Dim enableRotator As Boolean = True

Dim rotatorXYZ As Integer = 0

Dim rotateSpeed As Single = 0.01F '旋转速度

Dim enableSolidMode As Boolean = True

Dim enableCullMode As Boolean = True

Dim sphereMeshs As Mesh()

Dim sphereRadius As Single = 1.5F '小球半径

Dim sphereNumber As Integer = 18

Dim spherePositions As Matrix() '原始位置变换矩阵

Dim xRadius As Single = 15.0F 'x方向圆的半径

Dim ySpacing As Integer = 10 'y方向相对空间大小

Dim vertexBuffer As VertexBuffer '顶点缓冲

Dim sphereMaterial As Material() '小球材质

Dim lineMaterial As Material() '线的材质

Dim enableEmissive As Boolean = False'是否允许物体本身发光

Dim commonSphereMaterial As New Material()

Dim commonLineMaterial As New Material()

Dim multiMaterial As Boolean = True

Dim isPointLight As Boolean = False

Dim enableLight As Boolean = True

(5) 直接添加代码:

Public Sub BuildScene()

Me.buildMeshs() '创建Mesh对象

Me.BuildspherePositions() '构造小球位置

Me.BuildLineVertexBuffer() '创建小球间的连线顶点缓冲

BuildMaterials() '创建材质

End Sub

Private Sub buildMeshs()

'一定要及时释放资源,不能靠垃圾回收自动回收,

'否则退出后会很长时间无反应,像死机一样

图像三维重建技术

1概述 随着计算机软硬件技术的快速发展,大规模复杂场景的实时绘制已经成为可能,这也加快了虚拟现实技术的发展,又对模型的复杂度和真实感提出了新的要求。虚拟场景是虚拟现实系统的重要组成部分,它的逼真度将直接影响整个虚拟现实系统的沉浸感。客观世界在空间上是三维的,而现有的图像采集装置所获取的图像是二维的。尽管图像中含有某些形式的三维空间信息,但要真正在计算机中使用这些信息进行进一步的应用处理,就必须采用三维重建技术从二维图像中合理地提取并表达这些 三维信息。 三维建模工具虽然日益改进,但构建稍显复杂的三维模型依旧是一件非常耗时费力的工作。而很多要构建的三维模型都存在于现实世界中,因此三维扫描技术和基于图像建模技术就成了人们心目中理想的建模方式;又由于前者一般只能获取景物的几何信息,而后者为生成具有照片级真实感的合成图像提供了一种自然的方式,因此它迅速成为目前计算机图形学领域中的研究热点。 2三维建模技术 三维重建技术能够从二维图像出发构造具有真实感的三维图形,为进一步的场景变化和组合运算奠定基础,从而促进图像和三维图形技术在航天、造船、司法、考古、 工业测量、 电子商务等领域的深入广泛的应用。3基于图像的三维重建技术 基于图像的建模最近几年兴起的一门新技术,它使用直接拍摄到的图像,采用尽量少的交互操作,重建场 景。 它克服了传统的基于几何的建模技术的许多不足,有无比的优越性。传统的三维建模工具虽然日益改进,但构建稍显复杂的三维模型依旧是一件非常耗时费力的工作。考虑到我们要构建的很多三维模型都能在现实世界中找到或加以塑造,因此三维扫描技术和基于图像建模技术就成了人们心目中理想的建模方式;又由于前者一般只能获取景物的几何信息,而后者为生成具有照片级真实感的合成图像提供了一种自然的方式,因此它迅速成为目前计算机图形学领域中的研究热点。 4 基于图像重建几何模型的方法 4.1 基于侧影轮廓线重建几何模型 物体在图像上的侧影轮廓线是理解物体几何形状的 一条重要线索1当以透视投影的方式从多个视角观察某一空间物体时,在每个视角的画面上都会得到一条该物体的侧影轮廓线,这条侧影轮廓线和对应的透视投影中心共同确定了三维空间中一个一般形状的锥体1显然,该物体必将位于这个锥体之内;而所有这些空间锥体的交则构成了一个包含该物体的空间包络1这个空间包络被称为物体的可见外壳,当观察视角足够多时,可见外壳就可以被认为是该物体的一个合理的逼近。鉴于此类算法一般需要大量的多视角图像,因此图像的定标工作就变得非常复杂。 4.2采用立体视觉方法重建几何模型 基于立体视觉重建三维几何是计算机视觉领域中的经典问题,被广泛应用于自动导航装置。近年来,立体视觉 图像三维重建技术 康皓,王明倩,王莹莹 (装甲兵技术学院电子工程系,吉林长春130117) 摘要:基于图像的三维重建属于计算机视觉中的一个重要的研究方向,从提出到现在已有十多年的历史。文章首先对三维重建技术做了详细阐述,并着重从计算机图形学的研究角度对基于图像建模技术进行了综述,介绍了 具有代表性的基于图像建模的方法及其最新研究进展,给出了这些方法的基本原理, 并对这些方法进行分析比较,最后对基于图像建模技术的未来研究给出了一些建议和应解决的问题。关键词:三维建模技术;图像建模技术;计算机图形学;虚拟现实中图分类号:TP271文献标识码:A 文章编号1006-8937(2009)11-0042-02 Three-dimensional image reconstruction technique KANG Hao,WANG Ming-qian,WANG Ying-ying (DepartmentofElectronicEngineering,ArmoredInstituteofTechnology,Changchun,Jilin130117,China) Abstract:Image-based Three-dimensional reconstruction is an important research direction in computer vision ,from now more than ten years'history.This article first describes three-dimensional reconstruction technique in detail and review image-based modeling techniques from the perspective of computer graphics research,introduce a representative of the method of image-based modeling and the latest research progress,give the basic principles of these methods,analysis and compare these methods,finally,give a number of recommendations and problems which should be solved on image-based modeling technology for future research. Keywords:three-dimensional modeling techniques;image modeling techniques;computer graphics;virtual reality 收稿日期:2009-03-19 作者简介:康皓(1978-),女,吉林长春人,硕士研究生,讲师,研 究方向:计算机辅助设计与编程。 TECHNOLOGICAL DEVELOPMENT OF ENTERPRISE 2009年6月Jun.2009 企业技术开发 第28卷

vb程序设计实验教程习题答案

实验教材实验一 1:单项选择题: A A C C C D C B B C 2:填空题: (1).bas (2).vbp,.frm (3)视图工具箱 (4)对象 (5)属性对象事件方法 (6)Windows (7)事件行为 (8)窗体模块 实验二 1:单项选择题: A D C C A B A B D C B B C B C B A B D C 2:基本运算题: (1)27 (2)3.33333333333333 (3)3 (4)0 (5)-3 (6)2 (7)ab33 (8)类型不匹配 (9)3 (10)AB3 实验三 1:单项选择题: B C B D C 2:填空题: (1)300 (2)321456 (3)Shanghai (4)6 7 6 (5)True (6)2+3=5 (7)”area=” 12.56 (8)VISUAL 实验四 1:单项选择题: C A A C A 2:填空题: (1)7 (2)3 5

(3)输入的数小于0 (4)3 (5)False (6)2010 is not leap year. 试验五 1:单项选择题: A C C A B A C C C B 2:填空题: (1)9 (2)①n ②1 (3)①Len(a) ②n\2 ③Mid(a,(n-i+1),1) ④Mid(a,(n-i+1),1) (4)①n Mod 3=1 And n Mod 5=1 And n Mod 7=1 ②While CountN<5 (5)Mid(c1,1,i) 实验六 1:单项选择题: D B D C D A C A D D 2:填空题: (1)30 (2)3 (3)①a(2) ②a(3) ③a(1) (4)①1 ②2 ③a(i)=a(6-i) (5)①i+j ②0 ③a(i,j) (6)①Print ②k ③a(k,j)=a(j,k) ④a(k,j); 实验七 1:单项选择题: A B B A C B 2:填空题: (1)15 (2)①Preserve a(n+1) ②a(i+1)=a(i) ③Exit For ④a(i+1)=m⑤0 to n+1 (或LBound(a) to UBound(a)) (3)d,c,b,a 实验八 1:单项选择题: C A D B D C A C B 2:填空题: (1)a=9 b=4 (2) 36 25 16 9 4 1 (3)①a ②UBound(b) ③

《.NET程序设计》课程设计报告

《.NET程序设计》课程设计报告 班级:计算机1403 学号:1411640305 姓名:黄世增

一、实验名称 作者信息管理系统 二、实验目的 1.进一步掌握并加深“.NET程序设计”课程的基本知识,理解“.NET程序设计”课程中重点讲解的https://www.doczj.com/doc/af9881578.html,技术在项目开发中的应用。 2.培养正确的程序设计思想,提高分析问题、解决问题的能力。 3.提高学生进行技术总结和撰写说明书的能力。 三、系统设计描述 实验设计内容: 本次实验设计的内容是使用https://www.doczj.com/doc/af9881578.html,技术为某出版社设计并实现一个小型作者信息管理系统。出版社的工作人员登录该系统后,可以查看该社出版的各类书籍的作者的信息,并可以对作者信息进行各类查询,便于工作人员对作者信息进行管理。 系统数据库设计: 在SQL Server Express中为作者信息管理系统建立一个名为作者信息管理系统的数据库,并设计以下2张数据表: 1.系统管理员表 该表用来记录使用本系统的管理员的基本信息,包括管理员账户及密码。 【思考题】 (1)数据库中的一条记录中有若干个属性,若其中某一个属性(注

意是组)能唯一标识一条记录,该属性组就可以成为一个主键。 统管理员表中用户名应设为主键。 (2)用户名和密码都设为varchar字符型。 2.作者个人信息表 该表用来记录作者个人的基本信息,包括作者编号、姓名、联系地址、电话、email。 【思考题】 (1)表中作者编号应设为主键。 (2)表中作者ID、电话号码和Email为nchar字符串型,姓名和联系人地址为nvarchar字符串型。 设计好数据库的两个表后,分别在两个表中输入数据,如下图所示:

利用Alice三维虚拟世界进行程序设计入门教学

利用Alice三维虚拟世界进行程序设计入门教学 摘要:本文提出了一个对于程序设计入门教学的改革方法,利用Alice三维虚拟世界帮助学生理解程序设计的流程及基本概念。同时根据教学实践总结并分析了Alice作为初学程序设计环境的利与弊,并对如何将Alice课程同计算机现有课程体系的整合进行了探讨。 关键词:Alice;虚拟世界;面向对象;对象优先;三维动画 1引言 如何对基础相对薄弱的高职高专学生实施程序设计的入门教学,一直受到计算机教育者的关注。目前,在教学过程中所面临的主要困难,是在讲解烦琐的语法知识同时帮助学生学会抽象算法,通过程序的函数、方法去实现功能。在过去的几十年,国外计算机教育者开发了许多软件帮助初学者学习程序设计,其中包括最早的Karel the Robot,以及持续到今日的Jeroo,Greenfoot等。其中,三维虚拟世界的图形程序设计环境——Alice,在国外大学程序设计入门教学中的应用日益得到关注[1]。2006年美国国家科学基金(NSF) 关于应用Alice进行教学的会议吸引了来自各地的学者,Alice相关出版物也陆续出现。国外计算机教育领域对Alice所带来的积极因素表示了肯定[2][3],虽然在国内尚未普及,但是我们相信在未来几年Alice将受到国内计算机教育领域的关注。 2Alice的概述 Alice是由美国卡耐基·梅隆(Carnegie Mellon) 大学开发的以学习者为中心,支持面向对象程序设计的三维虚拟世界动画教学工具软件,由https://www.doczj.com/doc/af9881578.html,提供免费下载。Alice的显著特点是支持图形化程序设计,能够生成三维虚拟世界中的对象,将场景的设计同程序设计结合起来。学生可以创建不同的对象和它们的行为构建虚拟世界中的不同场景。其中,虚拟世界的组成对象(人物、动物、场景等)可以从扩展的三维对象图库中进行选择。 Alice提供拖放的图形用户界面,使得学生集中精力于程序设计的核心——程序结构的组成。图形界面提供了组织对象、和对象成员(接口和数据)和方法的图形化的提示。Alice界面根据功能分为5个区域(如图1所示),其中包括对象树,显示的是场景中出现的对象;World窗口,将对象添加到该窗口中进行场景的设计;事件区,对事件的响应进行编程,函数方法细节区,显示各个对象的属性、方法和函数;代码编辑区,通过将对象的属性、方法、函数拖拉到该区,根据提示自动生成代码。

.net程序设计报告1

《.Net程序设计》实验报告 电子商务专业班姓名:实验时间:13年05月16日 一、实验目的: https://www.doczj.com/doc/af9881578.html,简单程序程序设计,了解https://www.doczj.com/doc/af9881578.html,程序的基本过程 二、实验内容: 参考第二、三章实例编写简单的https://www.doczj.com/doc/af9881578.html,程序,要求具备一定的功能和界面。 三、操作步骤: 1.新建项目——“windows应用程序”。 2.选择form1在其属性中设置“BackGroundImage”,导入图片“发射场.jpg”;“Text” 设置为“火箭发射”。 3.在所有windows窗体中选择“Timer1”,添加到form1上,在其属性中设置:“Interval” 为“200”,“Enabled”为“False”。 4.在所有windows窗体中选择“PictureBox”添加,在属性中“Image”,导入图片“火 箭.jpg”. 5.在所有windows窗体中选择“Label1”添加,属性“Text”设置为“6”,“BorderStyle” 设置为“Fixed3D”。 6.在所有windows窗体中选择“Button1”添加,属性“Text”设置为“准备”。 实现需要相应代码:Public Class Form1 Private Sub PictureBox3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox3.Click End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load x = 400 i1 = Val(TextBox1.Text) i2 = Val(TextBox2.Text) i3 = Val(TextBox3.Text) i0 = i1 + i2 + i3 + i2 Timer1.Interval = 100 End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick Static i As Integer, dx% Dim k%

2020年MATLAB编程与应用实验报告(三维图形绘制)

1 三维图形绘制 实验报告 所属课程名称 MATLAB编程与应用 实验地点 实验日期 2112 班级 学号 姓名 指导老师 一、实验目的 实现手工难以绘制的函数或实验数据的图形可视化,绘制三维图形,通过控制线型、色彩等属性控制对数据内在特征进行表现。 二、实验内容 【实验过程及成果】(程序说明、实验代码、实验数据、实验结果) 程序说明 mesh函数用来绘制三维网格,surf函数用来绘制三维曲面图,surfl函数是具有光照效果的曲面,meshz函数绘制带底座的三维网格曲面,title进行图形标注,meshgrid(x,y)创建网格矩阵。 实验代码 >> [x,y]=meshgrid(-8:.5:8); z=sin(sqrt(x.^2+y.^2)) subplot(2,2,1);

mesh(x,y,z);title('mesh(x,y,z)') subplot(2,2,2); meshz(x,y,z);title('meshz(x,y,z)') subplot(2,2,3); surf(x,y,z);title('surfc(x,y,z)') subplot(2,2,4); surfl(x,y,z);title('surfl(x,y,z)') 实验数据 >> [x,y]=meshgrid(-8:.5:8); z=sin(sqrt(x.^2+y.^2)) 实验结果 【实验小结】(收获体会) 了解了mesh、meshc、meshz、surf、surfc、surfl函数来绘制三维曲线、面,mesh函数用来绘制三维网格,而surf函数用来绘制三维曲面图,各线条之间的补面用颜色来填充,meshc函数是带等高线的三维网格曲面,meshz函数是带底座的三维网格曲面,surfc函数具有等高线的曲面和surfl函数具有光照效果的曲面。通过学习可以基本绘制三维图形并且对三维图形有了全面的认识,可以基本利用三维曲线的基本函数plot3和三维曲线、面的函数,三维等高线的绘制等。 三、指导教师评语及成绩 评语 评语等级 优 良 中

VB语言程序设计实验

VB语言程序设计实验.txt蜜蜂整日忙碌,受到赞扬;蚊子不停奔波,人见人打。多么忙不重要,为什么忙才重要。 课程号:10010402 适用专业:全校非计算机专业 制定人: 教研室:计算机公共基础教研室 计算机科学与信息工程学院 2007 年5 月 前言 VB语言是一种被广泛学习、普遍使用的计算机程序设计语言。它的高级语言行式、低级语言功能具有特殊的魅力。由于VB语言具有完整的编程语言特点,因而被大多数高等院校作为典型的计算机教学语言。在计算机等级、全国计算机应用证书考试等多种计算机知识考试中都有VB语言。此外,VB语言作为一门实用的、功能强大的程序语言,被程序设计人员广泛使用。因此,VB语言是一门十分重要的程序设计语言。 《VB语言程序设计》课程,面向全校非计算机专业的本科生开设计算机基础课。以VB 语言为平台,介绍程序设计的思想和方法。通过学习,不仅使学生掌握高级编程语言的知识、编程技术和基本算法,更重要的是掌握程序设计的思想和方法,具备利用计算机求解实际问题的基本能力,能灵活应用高级语言进行程序设计。 本实验指导书中详细介绍了每个实验的目的、实验内容,并在方法上给出了指导,希望对同学们的学习能够有所帮助。 另外希望同学们对书中的错误和遗漏多提宝贵意见。可以登录网站:https://www.doczj.com/doc/af9881578.html,/netteach。 实验要求 VB语言程序设计实验是VB语言程序设计课程的重要组成部分,属于学科基础实验范畴,是与相关教学内容配合的实践性教学环节。学生通过实验,验证课堂学习的知识,掌握算法设计、编程实现和程序调试的方法,从而形成一定的编程能力。

在《VB语言程序设计》的课程实验过程中,要求学生做到: (1)预习实验指导书有关部分,认真做好实验内容的准备,就实验可能出现的情况提前作出思考和分析。 (2)仔细观察上机和上网操作时出现的各种现象,记录主要情况,作出必要说明和分析。 (3)认真书写实验报告。实验报告包括实验目的和要求,实验情况及其分析。对需编程的实验,写出程序设计说明,给出源程序框图和清单。 (4)遵守机房纪律,服从辅导教师指挥,爱护实验设备。 (5)实验课程不迟到。如有事不能出席,所缺实验一般不补。 实验的验收将分为两个部分。第一部分是上机操作,包括检查程序运行和即时提问。第二部分是提交书面的实验报告。 目录 实验一Visual Basic的集成开发环境 5 实验二数据类型9 实验三顺序结构程序设计11 实验四选择控制结构16 实验五选择控制结构(2)20 实验六循环控制结构21 实验七数组22 实验八过程25 实验九界面设计和使用设计多窗体界面26 实验十文件操作编程30 实验十一图形编程31 实验十二数据库编程 32 实验十三小规模实用软件的设计33 实验一Visual Basic的集成开发环境 【实验目的】 1.了解Visual Basic的集成开发环境 2.学会Visual Basic帮助系统的使用 3.了解可视化编程的一般步骤 4.掌握窗体界面风格设计方法 【实验内容】 1.设计一个窗体,包含两个标签和两个文本框,若在"输入"框中输入任意文字,将在"显示"框中同时显示相同的文字 2.编写一个简单的应用程序:只有一个窗体,窗体上有一个文本框和三个命令按钮,要求如下:

计算机图形学课程设计-三维真实感图形设计与绘制

计算机图形学 课程设计报告 一、实验题目 三维真实感图形设计与绘制 (1)题目容说明: 本题目要求应用OpenGL的光照技术和纹理技术实现一个简单的三维真实感图形的程序设计。具体要现功能: 1)通过对话方式实现交互式设计光照模型功能。 2)实现三维模型纹理映射功能 3)用鼠标跟踪球方法实现三维模型的空间旋转 2)实现鼠标跟踪球方法程序 二、需求分析 真实感图形的设计与绘制,是计算机图形学中的一个重要研究领域,也是三维实体造型系统和特征造型系统的重要组成部分。一般地,三维实体在计算机显示屏上有三种表现形式:

简单线框图、线框消隐图和真实感图形。其中,简单线框图能够粗略表达实体的形状,但由于简单线框图的二义性,从而导致表达其的实体形状具有不确定性。而线框消隐图虽然能反映实体各表面间的相互遮挡关系,从而达到消除简单线框图产生的二义性的目的,但是这两者一样地只能反映实体的几何形状和实体间的相互关系,而不能反映实体表面的特征,如表面的颜色、材质、纹理等。所以,只有真实感图形才能表现实体的这些特征,因此,在三维实体造型中,生成三维实体的光照模型,进行实体的真实感绘制与显示占有重要的地位,是很有必要的,也是我做此设计的初衷。 在设计中,我主要使用Opengl绘制真实感图形,它作为一种强大的三维图形开发工具,通过便捷的编程接口提供了处理光照和物体材质、颜色属性等通用功能。真实感图形学是计算机图形的核心容之一,是最能直接反映图形学魅力的分支。 寻求能准确地描述客观世界中各种现象与景观的数学模型,并逼真地再现这些现象与景观,是图形学的一个重要研究课题。很多自然景物难以用几何模型描述,如烟雾、植物、水波、火焰等。本文所讨论的几种建模及绘制技术都超越了几何模型的限制,能够用简单的模型描述复杂的自然景物。 在计算机的图形设备上实现真实感图形必须完成的四个基本任务。 1. 三维场景的描述。三维造型。 2. 将三维几何描述转换成为二维透视图。透视变换。 3. 确定场景中的所有可见面。消隐算法,可见面探测算法。 4. 计算场景中可见面的颜色。根据基于光学物理的光照模型计算可见面投射到观察者眼中的光亮度大小和色彩组成。 三、设计简介及设计方案论述

实验四VBNET程序设计基础和常用控件

实验四 https://www.doczj.com/doc/af9881578.html,程序设计基础和常用控件 一、实验目的 本实验主要了解面向对象程序设计语言https://www.doczj.com/doc/af9881578.html,基本语言元素包括集成开发环境、语言基础、基本控制结构、过程、常用控件和界面设计。通过本实验,读者将学会一些主要的面向对象的设计方法并可以利用https://www.doczj.com/doc/af9881578.html,完成简单的应用程序开发。 二、实验环境 Microsofe Visual Studio .NET 2008 三、实验内容 1.设计一个Visual 的应用程序,窗体上有一个多行文本框和3个命令按钮,程序界面如图1所示。要求应用程序运行时,当单击窗体上【显示文本信息】按钮,文本框中显示红色文字“我喜欢https://www.doczj.com/doc/af9881578.html,,因为它简单易学,使用方便。”当单击窗体上【改变背景色】按钮,文本框的背景色变为黄色。当单击窗体上【结束】按钮,程序结束。保存该应用程序。【实验步骤】: 1)创建工程:打开Visual Studio 后,点击左上角的新建项目,选中“模板”,展开选择Visual Basic,再选中Windows桌面,再在左边的类型中选择“Windows窗体应用程序”,在下方为此项目命名为“Win dowsApplication4.1”

2)先打开“工具箱”:展开左上角的“视图”,点击工具箱。 3)修改Form1的名称:右键选中From1,点击“属性”,在新弹出的属性菜单栏中,找到“Text”这个属性,将右边的“From1”改为“第一个https://www.doczj.com/doc/af9881578.html,实验”即可。 4)设置一个普通文本框:在工具栏中,选中公共空间中的TextBox,然后拖入右边的设计窗口中,然后鼠标移到TextBox后,鼠标左键按住不放可以移动此控件。 5)调整文本框的大小:鼠标移动到文本框的左右边缘,鼠标箭头会变成一个左右的箭头,

report4郭小明 三维图形程序设计 电子科技大学

实 验 报 告 课程名称:三维图形程序设计 学院:计算机科学与工程 专业:计算机科学与技术 指导教师:曹跃 学生姓名:郭小明 学号:2011060100010 实验成绩: 日期:2013年 5 月 3 日

电子科技大学 实验报告 实验四OpenGL纹理映射编程实验 实验室名称:A2—412 实验时间:2013.5.3 一.实验目的 1、理解OpenGL纹理映射的相关原理; 2、掌握与纹理映射相关的OpenGL API函数及其用法; 3、熟悉纹理映射设置的基本步骤。 二.实验内容 (一)编程任务1——绘制一个具有纹理和光照的房间

为在第三次实验中生成的房间(如上图)添加数字图像生成的纹理。 要求: 1、使用纹理对象; 2、墙壁、地板和天花板的数字图像生成的纹理要不相同; 3、屋内至少有一个点光源; 4、可用右键菜单交互式的开启或关闭场景光照和纹理; 5、可用右键菜单设置纹理环境(GL_REPLACE和GL_MODULATE)。分析 这两种方式中哪种适宜于有光照的环境下。 6、 三.实验要求 1.实验前要做好充分准备; 2.实验中独立完成源程序编辑、编译、链接过程,运行并记录程序运行结 果; 3.对程序结果进行分析。 四.实验报告 1.OpenGL纹理映射的基本原理和思想; 2.OpenGL纹理映射的基本步骤; 3.编程任务1 a)程序说明。说明程序的功能、结构。 b)编制的应用程序上机调试的情况、上机调试步骤、调试所遇到的问题 是如何解决的,并对编程过程中的问题进行分析,对执行结果进行分 析。 c)写出源程序清单(详细注释)和执行结果。 d)实验结果的分析。 五、实验器材(设备、元器件):

[心得体会]vb程序设计实验心得4篇

[心得体会]vb程序设计实验心得4篇数据库课程设计大赛的尘嚣渐渐远去,怀着对这次大赛的些许不舍,怀着对当初课程设计开始时候的豪情万丈的决心的留恋,怀着通过这次课程设计积累的信心与斗志,我开始写这篇文章,为自己的足迹留下哪怕是微不足道但是对自己弥足珍贵的痕迹并期望与大家共勉。 首先,让我的记忆追溯到大二暑假,在老大的指引下,我接触到Microsoft 公司的.NET产品。那个时候我已经学过vc和asp,因为windows程序设计实验的课的关系,接触过vb,但是没有专门去学他,因为习惯了c++里面的class,int,觉得vb的sub,var 看着就不是很顺心。我是一个好奇心很强的人,突然看到了一个号称“.网络是用于创建下一代应用程序的理想而又现实的开发工具”,而且主推c#语言,由于对c语言的一贯好感,我几乎是立刻对他产生了兴趣。我就开始了对c#的学习,任何语言都不是孤立存在的,所以数据交互是很重要的,暑假的时候我把我们这学期的课本数据库系统概论看了一遍。我记得以前用c语言编程的时候,数据是在内存中申请空间,譬如使用数组等等。很耗费内存空间。这个时候就是数据库站出来的时候啦,于是我又装上了sql serverXX,以前学asp的时候用的是aess,那个时候只是照着人家做,理论是什么也不是很清楚。

通过一个暑假的学习,基本搞清楚了理论方面的东西,具体怎么 用也不是很清楚。但是这为这学期的课程设计打下了铺垫。 来到学校后,随着这学期的数据库课程大赛开始了,我有一个看 法就是我自己应该具备的能力不是我会多少,而是我应该具备快速学会东西的能力。遇到什么就学什么。我们有时候很容易被一些专业名词说吓着,包括什么建模,软件工程,数据分析,数据挖掘等等。我身边就有很多同学被这些纸老虎所唬住,而没有勇气去接触他们,总是说这个太难了之类的退堂鼓的话,他们低估了自己的潜力同时也压抑住了他们自己的好奇心。其实都是纸老虎,又不是什么国家科研难题,只是去用一些工具,发明工具是很难,但是用一个工具就容易多了,just do it!我记得我做这个数据库之前,我们老师说要做好前期分析,我就在网上搜索用什么分析工具好。最后我选择了roseUML 建模工具。在此之前,我脑袋里面没有软件建模的思想,什么UML建模对我而言就是一张空白的纸。但是真正接触后并没有想象的那么难,有什么不懂的上网去搜索,这是一个信息横流的世界,有google,baidu就没有不能解决的知识难题。以及后来的数据库分析的时候用到的powerdesigner也是一样。 开发的时候我想过用什么架构,c/s模式?模式有很多,怎么选择?我就上网搜索现在最流行的架构是什么。结果搜到了MVC架构,就是你啦。我决定用这个架构,不会,没关系,咱学。Just do it!

https://www.doczj.com/doc/af9881578.html,程序的设计实验报告

福建农林大学金山学院 实验报告 课程名称:.NET程序设计 姓名:洪绵绵 系:信息与机电工程系 专业:计算机科学与技术 年级:2008 学号:082231029 指导教师:林松 职称:讲师 2010年12月29日

实验项目列表

福建农林大学金山学院实验报告 系:信息与机电工程专业:计算机科学与技术年级: 2008级 姓名:洪绵绵学号: 082231029 实验室号_ 608 计算机号 B3 实验时间: 2010.11.26上午一二节指导教师签字:成绩: 实验一数组、类、接口与结构 一、实验目的和要求 1、了解数组、类、接口和结构的定义、概念。 2、了解结构和类的区别。 3、掌握数组的声明、实例化、初始化和访问。 4、掌握类、接口的声明和使用,结构的声明和调用。 二、实验内容和原理 1、屏幕打印10行杨辉三角,逐行输出,用到Console.Write("{0,5}", A[i, j]); 和Console.WriteLine();语句。 2、创建抽象基类Shape和派生类Rectangle, Circle利用多态性实现Area(计算面积)和Show(在屏幕上显示图形名称和面积)抽象方法 3、声明一个接口ICDPlayer,包含4个接口方法:Play(),Stop(),NextTrack()和PreviousTrack(),以及一个只读属性CurrentTrack创建类CDPlayer实现该接口,模拟CD的播放、停止、下一音轨、上一音轨的操作。 4、声明一个表示平面坐标系中的点的结构体CoOrds,包含字段x,y,以及带2个参数的构造函数。分别利用三种不同的方法(默认构造函数、有2个参数的构造函数、先声明结构体变量再对其x,y字段赋值),创建3个平面坐标点变量。求这3个点所构成的三角形面积。注意判断3个坐标点是否可以构成三角形。 三、实验环境 1、硬件:PC机 2、软件:windowsXP、VS2008 四、算法描述及实验步骤 1、(1) 打开记事本,编写代码。

VB实验报告模板

课程编号:B080103140 https://www.doczj.com/doc/af9881578.html,程序设计 实验报告 东北大学软件学院

1.实验目的 (1)练习https://www.doczj.com/doc/af9881578.html,的控件的综合运用。熟悉https://www.doczj.com/doc/af9881578.html,的集成开发环境,掌握https://www.doczj.com/doc/af9881578.html, 编程技巧和开发过程。 (2)训练学生对https://www.doczj.com/doc/af9881578.html,的基本语句、控件、文件等的综合运用。 2.实验内容 (1)https://www.doczj.com/doc/af9881578.html,控件综合应用。 (2)https://www.doczj.com/doc/af9881578.html,文件操作——具体的名称(需要替换并变为黑色)。 3.程序中使用的控件及其命名 把程序中用到的控件类型及对应的名称以表格的形式给出,表格的行数可以根据需要进行扩充。 正文字体为“宋体五号”,并且为黑色,首行缩进2个汉字,如包含英文,用“Times New Roman”,行间距为“多倍行距”,设置为1.25(从弹出菜单的“段落”菜单项进行设置,或利用“格式刷”直接从本说明刷取格式)。 注意说明文字需要删除,不能保留在文档中。 (1)实验1的控件及命名 (2)实验2的控件及命名 4.系统实现与调试 把主要实现的功能用语言进行描述,并给出调试时的截图(主要是功能验证的截图,在结算时,是否能正确的找零等) 如果包含图片,图片要居中,而且图片的高度不能超过页面高度的1/3。 (1)实验1的系统实现与调试 正文字体为“宋体五号”,并且为黑色,首行缩进2个汉字,如包含英文,用“Times New Roman”,行间距为“多倍行距”,设置为1.25(从弹出菜单的“段落”菜单项进行设置,或利用“格式刷”直接从本说明刷取格式)。 注意说明文字需要删除,不能保留在文档中。

(2)实验2的系统实现与调试 正文字体为“宋体五号”,并且为黑色,首行缩进2个汉字,如包含英文,用“Times New Roman”,行间距为“多倍行距”,设置为1.25(从弹出菜单的“段落”菜单项进行设置,或利用“格式刷”直接从本说明刷取格式)。注意说明文字需要删除,不能保留在文档中。 5.创新点及存在问题 列举出主要的创新点和存在的问题。正文字体为“宋体五号”,并且为黑色,首行缩进2个汉字,如包含英文,用“Times New Roman”,行间距为“多倍行距”,设置为1.25(从弹出菜单的“段落”菜单项进行设置,或利用“格式刷”直接从本说明刷取格式)。注意说明文字需要删除,不能保留在文档中。 6.实验总结 正文字体为“宋体五号”,并且为黑色,首行缩进2个汉字,如包含英文,用“Times New Roman”,行间距为“多倍行距”,设置为1.25(从弹出菜单的“段落”菜单项进行设置,或利用“格式刷”直接从本说明刷取格式)。注意说明文字需要删除,不能保留在文档中。

vbnet程序设计实验001

实验一VB环境与简单程序设计 一、实验目的 1. 掌握在Visual Baisic环境中创建简单应用程序的方法。 2. 掌握在窗体上添加控件的方法,对控件的调整方法。 3. 掌握简单代码的编写。 二、实验内容 1. 创建一个无代码的简单程序。 2. 创建一个含有简单代码的程序。 3. 将VB工程编译生成可执行文件。 三、实验步骤与指导 1. 创建一个无代码的简单程序 (1)创建工程 启动Visual Baisic,在“新建工程”对话框中选择“标准EXE”(图1-1),单击“打开”按钮,进入Visual Baisic集成开发环境(IDE)。 (a) 新建工程(b) Visual Baisic集成开发环境(IDE) 图1-1 创建工程 (2)设计界面 双击工具箱“Label”控件,在窗体上添加一个标签(Label1)。 (3)设置属性 设置标签属性。在界面设计窗口选定标签,在属性窗口将标签的Caption属性值改为“Hello,World!”。单击Font属性右侧的按钮,在对话框中将字体大小设置为二号。在界面设计窗口调整标签控件的大小,使“Hello,World!”显示为一行。通过“格式”菜单中的“在窗体中居中对齐”菜单项(图1-2)将标签放置在窗体中央。 设置窗体属性。在属性窗口将窗体的Caption属性值改为“我的第一个程序”。 (4)运行程序 单击工具栏中启动按钮(?)或按F5键运行应用程序。程序运行结果如图1-3所示。 图1-2 “格式”菜单图1-3 第一个程序

2. 创建一个含有简单代码的程序 (1)新建工程 在Visual Baisic集成开发环境中单击“文件”菜单,选择“新建工程”。 (2)设计界面 单击工具箱“CommandButton”控件,在窗体上拖动鼠标“画出”三个命令按钮;单击工具箱“TextBox”控件,在窗体上画出文本框。 (3)设置属性 单击特定对象,然后在属性窗口作如下设置: 将三个命令按钮(Command1、2、3)的Caption属性分别设为“画圆”、“清除”和“退出”。将文本框的Text属性设为空。将窗体的Caption属性设为“在窗体上画圆”,FillColor 属性设为浅绿色,FillStyle属性设为0-Solid。 (4)编写代码 双击“画圆”按钮,打开代码编辑器窗口,在光标闪动处添加以下代码: Form1.Circle (1100, 1000), 800, vbBlue Text1.Text = "画一个实心圆" 在代码编辑器窗口内左上部的“对象”组合框列表中选定Command2,在右上部的“过程”组合框的列表中选择Click,然后在光标闪动处添加以下代码: Form1.Cls Text1.Text = "实心圆消失了" 在代码编辑器窗口内左上部的“对象”组合框的列表中选定Command3,在右上部的“过程”组合框的列表中选择Click,然后在光标闪动处添加以下代码: End 单击工具栏中启动按钮(?)或按F5键运行应用程序。程序运行效果如图1-4所示。 图1-4 含有简单代码的应用程序 3. 将VB工程编译生成可执行文件 将上述工程保存后,单击“文件”菜单中“生成….exe”菜单项,在对话框中选择保存位置并输入文件名,然后单击“确定”。退出VB开发环境,双击已生成的.exe文件运行。 4. 代码快速输入技巧 VB代码编辑器具有自动完成关键字的功能。若某些关键字或对象名称较长,或忘记了它们的完整拼写形式,只记得其前几个字母,利用此功能,即可快速、准确地输入关键字或对象名称。 方法1:用快捷键。先输入关键字或对象名称的前几个字符,然后按Alt+→键,此时在插入点处将会出现如图1-5所示的快速列表,用↓或↑键选中所需关键字或对象名称,然后按Tab键或其他分隔符(如空格、圆点“.”、逗号、等号、非字母运算符等),即可准确无误地输入该关键字或对象名称。用鼠标双击快速列表中的关键字或对象名称亦可完成输入。 方法2:用工具栏按钮。先输入关键字或对象名称的前几个字符,然后单击“编辑”工具栏按钮(图1-6),亦可调出图1-5所示的快速列表。若“编辑”工具栏未显示,可通过菜单“视图”→“工具栏”→“编辑”显示该工具栏。

.NET程序设计实验一

实验报告(一) 课程名称:.NET程序设计年级:2017级实验日期:姓名:学号:班级:

double b = Convert.ToDouble(Console.ReadLine()); if (a > b) { Console.WriteLine("较小的数为:" +b); } else if (a < b) { Console.WriteLine("较小的数为:"+a); } else { Console.WriteLine("两个数一样大"); } Console.ReadKey(); } } } 实验结果: 2.实验代码: using System; using System.Collections.Generic; using https://www.doczj.com/doc/af9881578.html,ponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;

namespace WindowsFormsApplication7 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } enum WeekDay { 星期天, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六}; private void button1_Click(object sender, EventArgs e) { DateTime dt = Convert .ToDateTime ( textBox1 .Text); WeekDay wd =(WeekDay ) dt.DayOfWeek; label1.Text= "这一天是"+wd+"."; } } } 实验结果: 五、总结 本次实验用C#编写了两个简单的任务程序,一个用的是控制台程序,第二

试验一VBNET初步

实验一https://www.doczj.com/doc/af9881578.html,环境和程序设计 一、实验目的 1. 掌握启动与退出https://www.doczj.com/doc/af9881578.html,的方法。 2. 掌握建立、编辑和运行一个简单的https://www.doczj.com/doc/af9881578.html,应用程序的全过程。 3. 掌握利用常用控件创建基于图形用户界面应用程序的技术。 4. 掌握https://www.doczj.com/doc/af9881578.html,程序设计语言的语法规则和编程技术。 二、实验内容 1.基本控件标签、文本框、按钮的使用。 利用文本框的字号、内容和格式等属性来实现格式设置,并对选中的复制练习,效果见图1.1。在TextBox1输入一字符串,建立三个命令按钮: (1)Button1:Text内容为“隶书25磅”,事件过程代码为: TextBox1.Font = New Font("隶书", 25) (2)Button2:Text内容为“幼圆15磅”,代码类似。 (3)Button3:Text内容为“复制=>”,要求复制在TextBox1选中的内容以及其字体格式。选中的内容通过TextBox1的.SelectedText属性;字体通过Font直接赋值。 图1.1 实验1.1运行界面 2. 输入数据合法性检验、MsgBox对话框的使用。 利用计算机解决古代数学问题“鸡兔同笼问题”。即已知在同一笼子里有总数为m只鸡和兔,鸡和兔的总脚数为n只,求鸡和兔各有多少只? 提示:鸡、兔的只数通过已知输入的m,n列出方程可解,但不要求出荒唐的解(例3.5只鸡、4.5只兔,或者求得的只数为负数)。因此,在TextBox2_LostFocus事件中要考虑下面两个条件: (1)对输入的总脚数n必须是偶数,否则提示数据错的原因,重新输入数据; (2)若求出的头数为负数,提示数据错的原因,重新输入数据。

《.NET程序设计》实验指导书-图文

《.程序设计》实验指导书-图文 《.程序设计》 实验指导书 年10月 1 2021 实验一 C#基本编程方法 一.实验目的 1.练习C#中变量声明和赋值的方法。 2.练习C#类型转换的方法。 3.练习C#分支语句的基本用法。 4.练习C#循环语句的基本用法。 二.实验内容 1.编写并调试一个C#控制台应用程序,输出1到5的平方值。 2.编写一个C#控制台应用程序,要求完成下列功能。(1)接收一个整数n。 (2)如果接收的值n为正数,输出1到n间的全部整数,循环转向(1),继续接收一个整数n。 (3)如果接收的值为负值,用break退出循环。 3.为铁路部门编写计算运费的程序。假设铁路托运行李,规定每张客票托运费计算方法是:行李重量不超过50kg时,每千克0.25元;超过50kg而不超过100kg时,其超出部分每千克0.35元时;超过

100kg时,其超过部分每千克0.45元。要求从键盘上输入行李重量后,程序计算并输出托运的费用。 三.实验体会: 2 实验二 C#面向对象编程 一.实验目的 1.练习如何创建类和对象。 2.练习如何为定义的类编写相应的方法。 3.练习如何通过属性访问对象中的数据。 4.练习如何创建基类及其派生类。 二.实验内容 1.编写一个控制台应用程序,定义并使用一个时间类,该类包含时、分、秒字段与属性,具有将时间增加1秒、1分和1小时的方法,具有分别显示时、分、秒和同时显示时分秒的方法。 2.编写一个控制台应用程序,程序中有两个类定义,一个是创建程序时系统自动创建的类Class1,一个是用户自定义的Student类,要求该类包含私有字段:学号(字符串)、姓名(字符串)和性别(字符),具有三个属性:学号(读写)、姓名(只读)、性别(读写),具有有参构造方法、具有同时显示学生个人信息的方法。在Class1类的Main方法中完成以下功能:(1)从键盘上输入一个学生的个人信息(学号、姓名、性别)。(2)修改该学生的学号和性别。 (3)打印修改前后该学生的个人信息。

相关主题
文本预览
相关文档 最新文档