Gamebryo3.0SDK翻译-NiMesh

来源:互联网 发布:海岛奇兵民房升级数据 编辑:程序博客网 时间:2024/05/01 18:59


NiMesh

一、 NiMesh简介

NiMesh库提供了一些列具有平台独立性的类,从而完成和几何体之间的交互。

1. 术语(terminology)

Stream:是一个抽象的数据缓冲区,可以包括一个或多个顶点、顶点索引以及用户自定义的元素

Usage:stream封装了一个缓冲区,这些缓冲可以被用作不同的目的。GB使用Usage来标志该stream的用途:

USAGE_VERTEX-顶点数据

USAGE_VERTEX_INDEX-顶点索引数据

USAGE_USER-自定义数据类型,GB渲染器使用用户自定义stream来保存shader constant数组。

Element:一个元素代表一个数据数组,该数据是一个着色程序的输入。每一个stream element定义了格式和偏移量(标志该数据放在stream的位置)。一个stream包含多个element

Region:定义了一个steam的子集,每一个region包含如下数据:

在每个stream中基址偏移量

活动element的数量

NiMesh:封装了一个完整几何体的数据,该几何数据被一些列动态特效(lights,projected textures等)和属性(textures、material properties等)影响。

Sub-Mesh:是NiMesh的一部分,被渲染器单独绘制,一个NiMesh至少包含一个sub-mesh。Region和sub-meshes一起对一个几何体进行多次绘制而不需要切换streams(包含统一行为架构)。

2. 词法(semantics)

词法是一个字符串,该字符串可以帮助识别元素的标识(POSITION、COLOR、NORMAL)或者一些自定制标识。可以通过congtent create tool来生成用户自定义词法。

3. Streams、regions、mesh和sub-meshes

每个NiDataStram实例包含一个region(NiDataStream::Region)数组和一个element(NiDataStreamElement)数组。

每一个NiMesh对象包含了一个NiDataStreamRefs数组,NiDataStramRefs包含一个指向NiDataStream的指针和GPU相关的参数。同时,NiDataStreamRefs包含一个顶点所有的数组,该索引代表一个sub-mesh。NiDataStramRefs使用词法和索引来映射特向的Element。

clip_image002

NiDataStream - NiDataStreamElement - NiMesh - NiDataStreamRef object relationships

4. 创建子mesh的约束

(1)所有绑定到统一子Mesh的USAGE_VERTEX stream region必须包含同样数量的顶点。

(2)USAGE_VERTEX_INDEX数据流的值必须小于绑定到子mesh上的顶点数。

(3)一个mesh只能有一个USAGE_VERTEX_INDEX数据流。

(4)每一子mehsh要求为每一个挂载到mesh上的流建一个region binding。

5. sharing和regions

一个NiDataSteamRef的sub-mesh bindings使用NiDataStream::Region作为一个指向。允许多个Mesh指向同一个数据流,此时不需要知道数据流的具体分割情况。

clip_image004

Relationship between multiple meshes that reference the same NiDataStream

6. 索引和无索引几何体

组成顶点索引类型的几何体必须且仅仅只能有一个索引数据流。

clip_image006

Indexed and non-indexed geometry

非索引类型几何体无需包含索引数据

7. 使用

(1)基本

clip_image008

(2)多三角形

clip_image010

Static indexed triangle stripped mesh with two strips

(3)多skin分割

clip_image011

Skinned indexed triangle mesh with 2 sub-meshes

二、 创建一个Mesh

三、 处理Mesh数据

1. NiDataStream介绍

(1)创建数据流

NiDataStramElements:描述了数据流中的单个元素。

CreateSingleElementDataStream:负责创建单个元素的数据流。

CreateDataStream

NiDataStreamFactory

NiToolDataStream

Region

(2)向Mesh添加数据流

NiDataStreamRef

(3)数据流和Mesh修改器

2. Data Stream 访问

(1)数据流访问标志

NiDataStream确保以线程安全的方式被访问,这意味着一个线程为读取顶点数据而访问数据流,此时其它线程就不能访问该数据流。

CPU访问标志

GPU访问标志

(2)数据流加锁标志

3. 寻找Data Streams

FindStreamRef:使用在知道NiDataStreamRef只有一个元素时。

clip_image013

FindStreamRefAndElementBySemantic:当不知该数据流是否只含一个Element时。

clip_image015

GetFirstStreamRef

clip_image017

clip_image019

clip_image021

4. Data Stream的锁定和Iterator 对象

(1)顶点元素(Vertex Element)

代表单个顶点属性(坐标、法向量、切线等)的顶点数据数组。

clip_image023

NiDataStreamElementLock

Retriving an Iterator

NiDataStreamLock

(2)图元元素(Primitive Element)

clip_image025

NiDataStreamPrimitiveLock

Retrieving an Iterator

Consideration When Iterating Over Multiple Stream

5. 克隆和Data Stream

(1)Basic clones

(2)Share vertex buffer,no shared data

(3)Some shared data

(4)Duplicate copy of data

(5)Sharing the layout, but not the data

6. 序列化Data Stream

四、 Mesh修改器(Modifers)

1. Mesh Modifiers 简介

Mesh修改器(Modifier)是一个可以动态、实时修改Mesh的对象。GB使用它可以实现皮肤变化、外形变形、粒子系统以及裁剪。应用程序可以通过定义新的mesh 修改器从而实现动态网格功能.

网格修改器使用Floodgate Library设计从而实现了并行处理网格的功能.

2. Mesh modifiers 执行模型

网格修改器使用并行工作提交的工作模型从而实现并行计算的目的.

修改器可以针对任何Mesh上的任何类型的计算。由于基于并行的,所以Floodgate kernel model是最合适Modifiers。

(1) NiMeshModifier 功能

NiMeshModifier中有两个函数用于实时控制:

SubMitTasks:该函数在modifier将要被启动并行任务(parallel Tasks)时调用,一个任务就是一个和Floodgate NiSPTask对象进行通信的过程。该函数可以完成一些列工作,包括所有和建立任务有关的。

CompleteTasks:该函数时在完成一个并行任务时被调用。它是一个同步函数

使用floodgate以为着modifiers的许多工作时基于kernel function的,同时还需要使用流处理。

(2) 同步点(SyncPoint)

SubmitTasks和CompleteTasks被执行的时间点。Modifers注册这两个时间点,一个用于建立submission,一个用于completion。SubmitTasks函数在每一个提交同步点被调用,同时CompleteTask函数在每一个完成同步点被调用。

clip_image027

如图所示,每一个同步点负责每一帧的相应的阶段,有如下同步点被定义在NiSyncArgs类中:

SYNC_UPDATE: SubmitTasks和CompleteTasks函数在Update时被调用,CompleteTasks函数在进入对象函数时就被调用,SubmitTasks在物体的时间控制器被更新后,但时在新的世界位置,包围盒更新之前被调用。所以modifier使用SYNC_POST_UPDATE去计算世界变换和世界包围盒。

SYNC_POST_UPDATE:

SYNC_VISIBLE:

SYNC_RENDER

3. 对Mesh进行修改器绑定

添加(Add):只是把相应的修改器添加给特定的网格,但是不工作

挂载(Attach): Modifier指向Mesh中数据流。

仅当NiMeshModifier::AreRequirementMet返回true时,NiMeshModifier才能被挂载,该函数检查modifier是否可以在Mesh上成功执行。

NiMeshModifier::Attach

该方法不能添加或修改网格中的数据流.但可以修改数据流中的数据.

NiMeshModifier::Detach

NiMeshModifier::AreRequirementsMet:查询修改器的功能.

该函数必须被所有的网格修改器实现.

NiMesh::ResetModifires:当向网格中的添加,移除或者改变数据流时,该函数必须被调用.

4. 修改器和工具的交互

5. 创建用户自定义修改器

网格修改器通常需要实现如下函数:

clip_image029

网格修改器的数据成员

标志和本地数据

Floodgate对象

NiSPTask

NiSPStream

NiSPKernel

NiSPWorkflow

Attach函数

主要负责初始化相关工作:

l Sets sync points

l Allocate a Floodgate to something

l Create o Floodgate kernel

l Set up Floodgate streams

Detach函数

在调用该函数之前,确保CompleteTasks函数被调用

SubmitTasks函数

该函数在网格修改器每次达到提交同步点(submit sync point)都会被掉用,所以在每一帧中它会被多次调用。

CompleteTask函数

该函数在网格修改器每次达到完成同步点(complete sync point)被调用。

RetrieveRequirement 函数

当GB的工具修改相关修改器涉及的属性时,该函数被调用。

AreRequirementsMet函数

当一个网格修改器将要Attach到一个网格时,该函数被调用,当该函数返回为false时,该修改器不能被attach到指定的网格。

6. GB标准修改的要求

五、 Instancing

1. 介绍

Hardware instancing是一项这样的技术,它允许在一次绘制操作中渲染大量对象,从而减小了多次调用绘制操作的开销,提升整体效率(该技术起源于shader model3.0)。由于大量的CPU时间耗费在调用每次绘制操作上,这样可以把大量的对象放到一起绘制,从而减少CPU调用绘制操作的次数,从而提高了效率。Hardware Instanceing技术适用于使用少数mesh绘制大量对象情况,如水里大量的海星(使用相同的Mesh)。

Hardware Instanceing技术可以释放大量CPU资源,但是会增加GPU的消耗。

Hardware Instancing工作原理

2. 基本知识

可以使用GB中的NiInstancingUtilities类来测试当前硬件是否支持Hardware Instancing技术、打开指定Mesh的Hardware Instancing、为instances提供变换。

可以使用NiMeshHWInstance为Mesh的Instances创建场景节点,从而实现这些Instances的管理。

(1) Instacning选项

应用程序使用Hardware Instancing处理两个操作:变换、剔除。

变换

应用程序可以使用两种方法来对Instanced Mesh进行变换:使用NiMeshHWInstance对象,并把添加到场景图中并直接对Instanced Mesh进行手动变换。另一种方法是直接设置Instancing的变换矩阵。

一个NiMeshHWInstan对象是一个NiAVObject,该NiAVObject对象和一个Instanced Mesh对象关联。

剔除

    使用NiMeshHWInstance对象的好处在于,应用程序可以使用与其它场景对象一样的方式来操作Mesh 
Instances,而不需要手动管理每一个instance的变换。当一个NiMeshHWInstance对象放到场景中比挂到
一个节点上。当NiMeshHWInstance任何时候改变时,instanceed mesh都被通知,预期同时保存在
instanced mesh中的instance transform会被更新。NiMeshHWInstance对象的好处在于可以处理复杂的场
景,并及时更新变换。
如果不采用NiMeshHWInstance对象,这些变换信息可以被应用程序手动管理,并直接传到instanced mesh
。该方法,需要应用程序内部来管理变换信息,它不需要大量的NiMeshHWInstance对象,从而节省空间。
该方法,可以处理场景中的阴影和静态变换。
     由于硬件instancing造成了,一个mesh来代表大量mesh,所以要求应用程序决定裁减方式。instanced 
mesh中存储的包围盒代表了所有instance的包围盒。这样造成instanced mesh被剔除了,所有的
instances也将看不见,同时当只有一个instance可见时,所有的instances将被绘制。
GB支持逐个instance剔除,从而解决该类问题。逐instance剔除,将会使用两个culling passes。第一个
culling pass,一个包围盒讲包含所有instances,从而迅速进行裁减。当该大包围可见,则第二个
culling pass将被初始化。第二个culling pass是进行逐instance裁减,只有可见的instance才会被送到
GPU绘制。GB使用了NiInstancingMeshModifier(使用Floodgate)来并行处理裁减处理。
    另一个优化裁减工作的方法是,设置instance mesh的包围盒为静态的。因为使用动态包围盒时,当一个
新instance 变换被加入或NiMeshHWInstance的本地变换改变时,instance mesh的包围盒都需要被更新。
而处理包围盒是一个较费时的过程。设置静态包围盒从而消除了包围盒的更新操作。

(2) 使用Hardware Instancing

分为三步:

A:检测硬件环境

clip_image031

B:对指定Mesh开启Hardware Instancing

要求Mesh的索引数据的访问方式为:NiDataSteam:ACCESS_CPU_READ,调用EnabaleMeshInstacing()开启。

C:更新Instance的变换信息。

clip_image033

3. 实际使用注意

大量稀疏的静态物体(如、场景中零星分布的森林)

此时使用两次剔除操作,并且使用NiMeshHWInstance。

大量稠密的静态物体(如、大量砖块组成的墙壁)

使用一次剔除操作,手动更新变换,即不使用NiMeshHWInstance,在需要时才更新包围盒。

大量动态物体

4. 渲染器的支持

原创粉丝点击