|
|
TextureMng以及MaterialMng的实现是比较简单的,这里不多说了。
开始考虑RenderPass类。这是同流水线关系密切的一个类,我们要仔细的考虑它的接口。一个RenderPass实例对应的是显卡的渲染中的一个批次,可以通过Index和Vertex两种方法来定义这个批次,所以,RenderPass需要包含一个VertexBuffer和一个IndexBuffer(当然这不是最好的设计:可以让多个RenderPass共用一个VertexBuffer,而使用不同的IndexBuffer,这样当然会节约存储空间,但是会使类的实现十分困难),在创建RenderPass的同时,我们要实例花它里面的VertexBuffer和IndexBuffer,即使它不会用到IndexBuffer(这样并不会影响什么,因为IndexBuffer对象在没有创建缓冲区的时候,其占用的内存是可以忽略的)。我们要使用RenderPass包含的VertexBuffer的时候就可以这样:
RenderPass pass;
VertexBuffer *pVB = pass.GetVertexBuffer();
pVB->Create(50*2*sizeof(CUSTOMVERTEX),D3DFVF_CUSTOMVERTEX,0,UHEPOOL_DEFAULT );
所以我们先写下一些简单的接口:
virtual VertexBuffer * GetVertexBuffer() = 0;
virtual IndexBuffer * GetIndexBuffer() = 0;
virtual void SetTextureMng( TextureMng * ) = 0;
virtual void SetMaterialMng( MaterialMng * ) = 0;
virtual TextureMng * GetTextureMng() = 0;
virtual MaterialMng * GetMaterialMng() = 0;
virtual void Render() = 0;
virtual void Release() = 0;
在后面,完成了其他的部分后,RenderPass的接口还要有增加。
想象一下,美工做了一个人物的静态模型,他把眼睛,头部,躯干,放到不同的Group里面去,你这时候来解析这个模型。简单的想,把不同的Group放到不同的RenderPass里面去么?这样也不是不行,只是,很多情况下,多个Group之间有大量的顶点是重复的,那么就我们的RenderPass的设计而言,这样做无疑会造成大量的顶点缓冲的重复,而且,想一下,这样做无疑会造成渲染时的多批次问题,这应该需要改进的地方。我暂时的做法是,把多个Group创建到一个RenderPass里面去,把不同的Group的信息保存为不同的IndexBuffer的偏移地址。也就是说,为所有的顶点创建一个缓冲区,把不同的Group里面的Index信息连成一个IndexBuffer存放,并且记录下各个Group对应的IndexBuffer的起、止地址。这样做可以解决重复的缓冲区的问题,而且,在需要渲染整个模型的时候,我们可以只用一个pass(传给显卡整个IndexBuffer)。
为了管理这些偏移地址的下标,创建一个SubRenderPass类。SubRenderPass类需要包含两个下标的数据:
//File: UHESubRenderPass.h
#ifndef _INCLUDE_UHESUBRENDERPASS_H
#define _INCLUDE_UHESUBRENDERPASS_H
#include "UHEPrerequisites.h"
namespace UHEngine
...{
class _UHE_Export SubRenderPass
...{
public:
SubRenderPass();
~SubRenderPass();
void BindTexture( int texID );
void BindMaterial( int matID );
int GetTextureID()
...{
return m_texID;
}
int GetMaterialID()
...{
return m_matID;
}
void DimIndex( WORD first, WORD second );
std::pair<WORD, WORD> GetIndex()
...{
return m_index;
}
private:
int m_texID;
int m_matID;
std::pair<WORD, WORD> m_index;
};
}
#endif
看到接口中还有关于Texture和Material的信息,这是因为如果不同的SubRenderPass可以对应不同的纹理和材质(当然如果真的是这样,我们就不得不分多次渲染他们了,在Render的时候,我们会判断一下,如果SubRenderPass的确是用的同样的纹理和材质,就只作一次pass)。
相应的,RenderPass类也会有改动,加入这些接口:
virtual int DimSubPass( WORD firstIndex, WORD secondIndex ) = 0;
virtual std::pair<WORD, WORD> GetSubPassIndex( int subID ) = 0;
virtual int GetNumSubPass() = 0;
virtual UHESubRenderPass * GetSubPass( int passID ) = 0;
我们还需要比RenderPass的粒度高一个层次的流水线对象,对于其他的真正“分块”的模型,我们可以选择用多个RenderPass来处理,把这些RenderPass放到一个类中——RenderTarget。毕竟很多的复杂的模型(比如Quake3中的人物模型),都是由几个文件部分组成的,更自然的,我们需要用多个RenderPass来实现。RenderrTarget不止是一个多RenderPass的管理器而已,它还需要(通常对于人物模型)把不同的RenderPass的坐标组织到一起(把不同的物体映射到同一个的世界坐标中去)。
(今天先写道这里。。。)
|
|