Tutorial2-- Rendering Vertices
用Direct 3D的方法渲染一个三角形,所以的三维形体其实都是由三角形组成的三角形网格(triangle mesh)逼近表示的。
代码如下:
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace VerticesTutorial
{
public class Vertices : Form
{
// Our global variables for this project
Device device = null; // Our rendering device
VertexBuffer vertexBuffer = null;
public Vertices()
{
// Set the initial size of our form
this.ClientSize = new System.Drawing.Size(300,300);
// And its caption
this.Text = "Direct3D Tutorial 2 - Vertices";
}
public bool InitializeGraphics()
{
try
{
// Now let's setup our D3D stuff
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed=true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
this.OnCreateDevice(device, null);
return true;
}
catch (DirectXException)
{
return false;
}
}
public void OnCreateDevice(object sender, EventArgs e)
{
Device dev = (Device)sender;
// Now Create the VB
vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 3, dev, 0, CustomVertex.TransformedColored.Format, Pool.Default);
vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);
this.OnCreateVertexBuffer(vertexBuffer, null);
}
public void OnCreateVertexBuffer(object sender, EventArgs e)
{
VertexBuffer vb = (VertexBuffer)sender;
GraphicsStream stm = vb.Lock(0, 0, 0);
CustomVertex.TransformedColored[] verts = new CustomVertex.TransformedColored[3];
verts[0].X=150; verts[0].Y=50; verts[0].Z=0.5f; verts[0].Rhw=1; verts[0].Color = System.Drawing.Color.Red.ToArgb();
verts[1].X=250; verts[1].Y=250; verts[1].Z=0.5f; verts[1].Rhw=1; verts[1].Color = System.Drawing.Color.Yellow.ToArgb();
verts[2].X=50; verts[2].Y=250; verts[2].Z=0.5f; verts[2].Rhw=1; verts[2].Color = System.Drawing.Color.Green.ToArgb();
stm.Write(verts);
vb.Unlock();
}
private void Render()
{
if (device == null)
return;
//Clear the backbuffer to a blue color (ARGB = 000000ff)
device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0);
//Begin the scene
device.BeginScene();
device.SetStreamSource( 0, vertexBuffer, 0);
device.VertexFormat = CustomVertex.TransformedColored.Format;
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
//End the scene
device.EndScene();
device.Present();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
this.Render(); // Render on painting
}
protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
{
if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)
this.Close(); // Esc was pressed
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
using (Vertices frm = new Vertices())
{
if (!frm.InitializeGraphics()) // Initialize Direct3D
{
MessageBox.Show("Could not initialize Direct3D. This tutorial will exit.");
return;
}
frm.Show();
// While the form is still valid, render and process messages
while(frm.Created)
{
frm.Render();
Application.DoEvents();
}
}
}
}
}
这里频繁出现了一个类-- VertexBuffer ,顶点缓存。还有一些相关的类,方法接下来谈一下。
VertexBuffer 操作存储顶点的缓存,和相关的资源 |
||
属性 |
||
Description |
VertexBufferDescription |
得到关于VertexBuffer的信息 |
公共方法 |
||
VertexBuffer |
VertexBuffer类的构造函数,无参数 |
|
Lock |
锁定缓存,返回顶点集合供用户进行读写操作 |
|
UnLock |
解除对缓存的锁定 |
* Description: 是VertexBufferDescription类。VertexBufferDescription类的属性就是与关于VertexBuffer的信息,包括Pool(容纳缓存的内存池),Size(缓存的大小),Usage(缓存使用的附属信息)等。
* VertexBuffer方法有多个参数,其中有:
public VertexBuffer(Device, int, Usage, VertexFormats, Pool);
public VertexBuffer(Type, int, Device, Usage, VertexFormats, Pool);
Type:Vertex的类型
int:缓存所能够储存的顶点个数
Usage:是enum,用于设定一些缓存使用的附加信息
Dynamic:所创建的是动态缓存(dynamic buffer),动态缓存一般储存在AGP储存区中,其内容可以迅速更新,但数据的绘制就不如在显存(video memory)的快;与之相对应的是静态缓存(static buffer),静态缓存一般储存在显存中,这样能够加快处理的速度,但相应的数据的更新速度就慢下来了。根据上述的特性,静态缓存适合储存一些不会经常修改的数据,如地形,城市建筑的相关数据;而动态缓存,就适合储存一些频繁更新的数据。粒子系统就是一个好例子。值得注意的是Usage并没有Static这一选择,这是因为只要没有选择Dynamic,系统就认为你选择的是Static。
VertexFormats:顶点格式,定义缓存中单个顶点的格式,类似C++中的FVF(灵活顶点格式)。
Pool:定义容纳缓存的内存池
* Lock与UnLock:
public GraphicsStream Lock(int, int, LockFlags);
public Array Lock(int, LockFlags);
public Array Lock(int, Type, LockFlags, int[]);
public void Unlock();
为了访问缓存中的数据,就要使用到Lock来得到缓存中某一系列顶点的集合(而在C++中,通过Lock得到的是一个指向缓存内部储存区的指针)。得到这些顶点的集合(GraphicsStream或者Array),我们就可以对其进行读写操作。
那么,究竟什么是“锁定”缓存呢?它其实就是允许CPU直接访问资源中一定范围内数据的操作。你不能直接访问图形硬件,因此需要一种方法来控制程序中的顶点数据,而锁存就是用来完成这个任务的。(引用)
其中LockFlags是定义锁定类型的enum,常用的如下:
Discard:仅可用于动态缓存,它指示硬件将缓存内容丢弃,并返回新分配的缓存空间(对于动态的纹理,缓存会被重写),使得丢弃了的缓存能被重新利用,这样数据的处理就不会停滞。
NoOverWrite:
ReadOnly:
很重要的一点是对缓存访问完毕时,必须对缓存解锁,只需调用Unlock()这个方法即可。
CustomVertex 用于定义制定多种固定格式的顶点类型的类,这个类包含了很多结构体。 |
||
结构体 |
||
Structures |
Transformed |
|
Structures |
TransformedColored |
|
Structures |
TransformedTextured |
|
Structures |
PositionColored |
|
…… |
* CustomVertex有多种类型的顶点结构体类似于C++的FVF(灵活顶点格式,Flexible Vertex Format)。它是一个结构体集合的类,里面包含着大量的结构体。里面结构体基本上都包含点信息,但大部分在点的空间信息上进行了扩展,例如,法线方向,纹理等。点是计算机图形学里面最基本的元素。
至于各种格式顶点的区别和用法,我还没有弄清楚,暂时只知道通过这些结构体可以修改顶点的空间属性、rhw(reciprocal homogeneous w齐次W的倒数,计算机图形学的东西 网上查到说,指该顶点包含已经进行光照、坐标转换后的数据)、颜色纹理等附加属性。
我看了一下,各种的结构体主要分为Position打头的和Transformed打头的,试了一下Position打头的应该只处理点,而Transformed打头的应该处理点与周围空间的。这个以后还需要再看。
三角网 Vertex与Index
构成场景(Scene)各种各样的模型,都可以由三角形网格(triangle mesh)逼近表示。三角形网格是构成模型的基本单元。
顶点是指一个多边形中相邻的两边的交汇点。在描述一个三角形单元,就需要3个顶点。
顶点除了空间信息,还包括其它的附加信息,如颜色,法线等(详细见CustomVertex各种结构体)
C#中的DrawPrimitives 与BeginSence ,EndScence,Present
前后台缓冲区与Swap Chain的关系