[轉]Ogre:Hardwarebuffer

 

[轉]Ogre:Hardwarebuffer

關鍵字:

Ogre中的硬件緩存是指在顯卡上的存儲,這和在內存上的存儲一樣是可以訪問的。有三種硬件緩存:HardwareVertexBuffer(頂點緩存,存儲頂點的各種數據)、HardwareIndexBuffer(索引緩存,存儲一個mesh的面片的頂點索引),HardwarePixelBuffer(紋理緩存,存儲某個紋理貼圖的數據)。這些數據在程序運行時都在顯卡的存儲上,然而你可以去讀和寫這些數據,來操控程序中物體的形狀、紋理等。這個用處是非常大的。

1、最上面的hardwarevertexbuffer
讀寫:如果mesh使用的所有子mesh共享buffer的形式,則用meshsharedvertexdata,否則用submeshvertexdata來得到vertexdata結構,vertexdata封裝了對該mesh的頂點緩存數據的訪問方式,但是卻不直接包含這些頂點緩存數據。vertexdata中的vettexbufferbinding可以知道當前的vertexdata對應了確切的硬件上的哪塊buffer,可以通過vettexbufferbindinggetBuffer確切的得到該頂點緩存,而vertexdata中的vertexdeclaration則是一個對他對應的buffer進行各種訪問的接口,裏面有訪問的格式等。如果要開始操縱這個buffer,需要將getbuffer得到的hardwarevertexbuffer調用lock,然後將這片緩存上鎖,這個lock返回了一個void指針,指向的就是緩存數據。拿着這個指針就可以讀取改寫等

創建:使用hardwarebuffermanagercreate來創建,創建後利用hardwarevertexbufferwrite寫入數據

2.中間的hardwareindexbuffer
讀寫:直接使用submeshindexdata來得到一個indexdata結構,再調用它的hardwareindexbuffer的來得到這個頂點緩存,童年頂點緩存一樣再調用lock來進行讀寫操作

創建:同頂點緩存

3最下面的hardwarepixelbuffer

讀寫:從texture中可以直接得到這個hardwarepixelbuffer,然後對它lock後就可以得到一個pixelbox的數據,pixebox封裝了所有紋理數據及其各種屬性信息

創建:texture是由texturemanager創建的

下面是一些具體的使用硬件緩存的例子

讀取頂點和索引緩存

Ogre::MeshPtr meshPtr=mainEntity->getMesh();
//
假設這裏使用的是share的形式

Ogre::VertexData* vertex_data=meshPtr->sharedVertexData;

//得到位置數據的信息
const Ogre::VertexElement* posElem =vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

//得到紋理座標數據的信息
const Ogre::VertexElement*texcoElem=vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES);
//
得到位置和紋理的緩存

Ogre::HardwareVertexBufferSharedPtr posBuf=vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
Ogre::HardwareVertexBufferSharedPtr texcoBuf=vertex_data->vertexBufferBinding->getBuffer(texcoElem->getSource());
//
頂點位置緩存的lock,讀取

unsigned char* vertexPos =static_cast<unsignedchar*>(posBuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

//將第一個點的位置讀出
float* pReal;

//這個函數的作用是將當前vertexPos指向的數據用其他型(這裏是float*)的指針指向,這樣讀出來的數據就是float型的了,或者用float型的數據進行寫入
posElem->baseVertexPointerToElement(vertexPos, &pReal);
Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
//
訪問之後要上鎖

posBuf->unlock();

//
讀取索引信息

Ogre::SubMesh* submesh = meshPtr->getSubMesh( i );

//得到這個submeshindexdata
Ogre::IndexData* index_data = submesh->indexData;
int numTris = index_data->indexCount / 3;

//得到indexbuffer
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
bool use32bitindexes = (ibuf->getType() ==Ogre::HardwareIndexBuffer::IT_32BIT);

//得到具體的索引緩存數據
unsigned long* pLong = static_cast<unsignedlong*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);

… …
ibuf->unlock();

訪問紋理緩存

Ogre::HardwarePixelBufferSharedPtrcrossPixbufferPtr=texture.getPointer()->getBuffer(0,0);
crossPixbufferPtr->lock(Ogre::HardwareBuffer::HBL_NORMAL);
Ogre::PixelBox pb=crossPixbufferPtr->getCurrentLock();
int height = pb.getHeight();
int width = pb.getWidth();
int pitch = pb.rowPitch; // Skip between rows of image
uint32* data=static_cast<uint32*>(pb.data);

……操縱data……
crossPixbufferPtr->unlock();

創建頂點緩存和索引緩存,進而根據其創建一個自定義的mesh

void createColourCube()
{
/// Create the mesh via the MeshManager
Ogre::MeshPtr msh =MeshManager::getSingleton().createManual("ColourCube","General");
/// Create one submesh
SubMesh* sub = msh->createSubMesh();
const float sqrt13 = 0.577350269f; /* sqrt(1/3) */
/// Define the vertices (8 vertices, each consisting of 2 groups of 3 floats
const size_t nVertices = 8;
const size_t vbufCount = 3*2*nVertices;
float vertices[vbufCount] = {
-100.0,100.0,-100.0, //0 position
-sqrt13,sqrt13,-sqrt13, //0 normal
100.0,100.0,-100.0, //1 position
sqrt13,sqrt13,-sqrt13, //1 normal
100.0,-100.0,-100.0, //2 position
sqrt13,-sqrt13,-sqrt13, //2 normal
-100.0,-100.0,-100.0, //3 position
-sqrt13,-sqrt13,-sqrt13, //3 normal
-100.0,100.0,100.0, //4 position
-sqrt13,sqrt13,sqrt13, //4 normal
100.0,100.0,100.0, //5 position
sqrt13,sqrt13,sqrt13, //5 normal
100.0,-100.0,100.0, //6 position
sqrt13,-sqrt13,sqrt13, //6 normal
-100.0,-100.0,100.0, //7 position
-sqrt13,-sqrt13,sqrt13, //7 normal
};
RenderSystem* rs = Root::getSingleton().getRenderSystem();
RGBA colours[nVertices];
RGBA *pColour = colours;
// Use render system to convert colour value since colour packing varies
rs->convertColourValue(ColourValue(1.0,0.0,0.0), pColour++); //0 colour
rs->convertColourValue(ColourValue(1.0,1.0,0.0), pColour++); //1 colour
rs->convertColourValue(ColourValue(0.0,1.0,0.0), pColour++); //2 colour
rs->convertColourValue(ColourValue(0.0,0.0,0.0), pColour++); //3 colour
rs->convertColourValue(ColourValue(1.0,0.0,1.0), pColour++); //4 colour
rs->convertColourValue(ColourValue(1.0,1.0,1.0), pColour++); //5 colour
rs->convertColourValue(ColourValue(0.0,1.0,1.0), pColour++); //6 colour
rs->convertColourValue(ColourValue(0.0,0.0,1.0), pColour++); //7 colour
/// Define 12 triangles (two triangles per cube face)
/// The values in this table refer to vertices in the above table
const size_t ibufCount = 36;
unsigned short faces[ibufCount] = {
0,2,3,
0,1,2,
1,6,2,
1,5,6,
4,6,5,
4,7,6,
0,7,4,
0,3,7,
0,5,1,
0,4,5,
2,7,3,
2,6,7
};
/// Create vertex data structure for 8 vertices shared between submeshes
msh->sharedVertexData = new VertexData();
msh->sharedVertexData->vertexCount = nVertices;
/// Create declaration (memory format) of vertex data
VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration;
size_t offset = 0;
// 1st buffer
decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
offset += VertexElement::getTypeSize(VET_FLOAT3);
decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
offset += VertexElement::getTypeSize(VET_FLOAT3);
/// Allocate vertex buffer of the requested number of vertices (vertexCount)
/// and bytes per vertex (offset)
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton().createVertexBuffer(
offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
/// Upload the vertex data to the card
vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
/// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding;
bind->setBinding(0, vbuf);
// 2nd buffer
offset = 0;
decl->addElement(1, offset, VET_COLOUR, VES_DIFFUSE);
offset += VertexElement::getTypeSize(VET_COLOUR);
/// Allocate vertex buffer of the requested number of vertices (vertexCount)
/// and bytes per vertex (offset)
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
offset, msh->sharedVertexData->vertexCount,HardwareBuffer::HBU_STATIC_WRITE_ONLY);
/// Upload the vertex data to the card
vbuf->writeData(0, vbuf->getSizeInBytes(), colours, true);
/// Set vertex buffer binding so buffer 1 is bound to our colour buffer
bind->setBinding(1, vbuf);
/// Allocate index buffer of the requested number of vertices (ibufCount)
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
createIndexBuffer(
HardwareIndexBuffer::IT_16BIT,
ibufCount,
HardwareBuffer::HBU_STATIC_WRITE_ONLY);
/// Upload the index data to the card
ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
/// Set parameters of the submesh
sub->useSharedVertices = true;
sub->indexData->indexBuffer = ibuf;
sub->indexData->indexCount = ibufCount;
sub->indexData->indexStart = 0;
/// Set bounding information (for culling)
msh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100));
msh->_setBoundingSphereRadius(Math::Sqrt(3*100*100));
/// Notify -Mesh object that it has been loaded
msh->load();
}

然後可以從mesh直接創建entity放在場景中

Entity*thisEntity =sceneManager->createEntity("cc", "ColourCube");

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章