2017-04-26 44 views
1

我在學習OpenGL並遇到「障礙」。 我用索引緩衝區畫了一些房屋(塊和金字塔)。 當將所有頂點(從所有房屋)加載到頂點緩衝區並使用1個大的索引緩衝區時,這可以正常工作。現在我想動畫化對象並逐個將它們加載到頂點緩衝區中,以便我可以逐個對對象執行變換。代碼與一個大緩衝區沒有多大區別,但是當我這樣做時,我只是看到屏幕上出現一些隨機的形狀。我的代碼如下:OpenGL indexbuffer在逐個加載對象時不起作用

我有一個世界級的持有3D對象列表,有一個所有頂點的大列表(用於試用),一個大列表(也是試用版)以及一個添加方法一個Object3D對象的世界。

class World 
{ 
public: 
World(); 
~World(); 

vector<Object3D> objects; 
vector<glm::vec3> Vertices; 
vector<GLushort> Indices; 

void AddObject(Object3D &object); 

};

Object3D類:

class Object3D 
{ 
public: 
Object3D(); 
~Object3D(); 

glm::vec3 Position; 
vector<glm::vec3> Vertices; 
vector<unsigned int> Indices; 
}; 

世界AddObject方法,簡單地將對象添加到了「對象」名單,並增加了頂點和索引的「頂點」和「指標」列出了創建一個大的緩衝區:

void World::AddObject(Object3D &object) { 

int oldVerticesSize = Vertices.size(); 
objects.push_back(object); 
Vertices.insert(Vertices.end(), object.Vertices.begin(), object.Vertices.end()); 

for each (GLushort index in object.Indices) 
{ 
    Indices.push_back(index + oldVerticesSize); 
} 
} 

當我渲染所有頂點和索引(如下所示)的大緩衝區時,它工作正常。

void WorldRenderer::Render() 
{ 
glClearColor(0.0, 0.0, 0.0, 1.0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glBindVertexArray(Vao); //use vao 
glDrawElements(GL_TRIANGLES, World.Indices.size(), GL_UNSIGNED_SHORT, 0); 
//glDrawArrays(GL_TRIANGLES, 0, World.Vertices.size()); 
glBindVertexArray(0); //release vao 

//Model = glm::rotate(Model, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f)); 
Mvp = Projection * View * Model; 

glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp)); 
glutSwapBuffers(); 

//glutPostRedisplay(); 

}

當我通過對象迴路和負載的對象的頂點在緩衝一對象在-A-時間(如下所示)它顯示了一些隨機「的形狀」,它保持「拍攝」或快速變化。我在這裏做錯了什麼? 在此先感謝您的任何建議。

void WorldRenderer::Render() 
{ 
glClearColor(0.0, 0.0, 0.0, 1.0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

int index = 0; 
for each (Object3D mesh in World.objects) 
{ 
    Mvp = Projection * View * Model; 

    UpdateBuffer(mesh.Vertices, mesh.Indices); 

    glBindVertexArray(Vao); //use vao 
    glDrawElements(GL_TRIANGLES, mesh.Indices.size() , GL_UNSIGNED_SHORT, 0); 
    glBindVertexArray(0); //release vao 
    glUniformMatrix4fv(UniformMvp, 1, GL_FALSE, glm::value_ptr(Mvp)); 
    index++; 
} 

glutSwapBuffers(); 
} 

UpdateBuffers方法:

void WorldRenderer::UpdateBuffer(vector<glm::vec3> vertices, vector<unsigned int> indices) { 

//fill Vbo 
glBindBuffer(GL_ARRAY_BUFFER, Vbo); 
glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

//fill ibo 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

glBindVertexArray(Vao); 
glBindBuffer(GL_ARRAY_BUFFER, Vbo); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo); 
} 

對於第一渲染方法(不循環)的緩衝器中,看起來像這樣init方法創建一次:

void WorldRenderer::Init(int argc, char ** argv) { 
InitGlutGlew(argc, argv); 
InitMatrices(); 

glDisable(GL_CULL_FACE); 
//-------------- init buffers -------------- 
// vbo vertices 
glGenBuffers(1, &Vbo); 
glBindBuffer(GL_ARRAY_BUFFER, Vbo); 
glBufferData(GL_ARRAY_BUFFER, World.Vertices.size() * sizeof(glm::vec3), 
    &World.Vertices[0], GL_STATIC_DRAW); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 
//ibo 
glGenBuffers(1, &Ibo); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, World.Indices.size() * sizeof(unsigned int), 
    &World.Indices[0], GL_STATIC_DRAW); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

// VAO setup 
glGenVertexArrays(1, &Vao); 
glBindVertexArray(Vao); 
// Bind vertices to vao 
glBindBuffer(GL_ARRAY_BUFFER, Vbo); 
//Bind elements 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Ibo); 

//------ init shaders ----------- 
InitShader(); 
} 

回答

2

一旦因爲我看到你的UpdateBuffer函數,我覺得glBufferDatavbo沒有正確加載。

第二個參數vertices.size()僅返回矢量中的元素數量,但不返回對象的實際大小。

因此,第二個參數應該是vertices.size() * sizeof(glm::vec3)

而第三個參數是確定它返回指針到底層陣列。如果不工作....直接傳遞第一個元素的地址,如下所示。

總的來說,它應該如下所示。

glBufferData(
    GL_ARRAY_BUFFER, 
    vertices.size() * sizeof(glm::vec3), 
    &vertices[0], 
    GL_STATIC_DRAW 
); 

檢查是否正常工作。

爲什麼你看到差異?

首先渲染:

你的緩衝區包含了世界上所有的數據,頂點時間可持續,當glDrawElements被調用。 所以這裏的mesh1最後一個頂點繼續與網格2第一個頂點 ....所以你看到一種封閉的形狀。

第二渲染:

你的緩衝區只包含一個網格數據的時間,當glDrawElements被調用。

讓您的形狀在撥打glDrawElements後每個網格結束。

要獲得與第一次渲染相同的結果,必須首先更新所有網格的單個頂點緩衝區(使用glBufferSubData)。

然後撥打glDrawElements一次。然後你會看到相同的結果。

+0

謝謝! :D這讓我更進了一步(我應該更加整潔)。但是現在我只能看到大約一半的三角形。 indexbuffer和vertexbuffer看起來很好,我試着移動一些索引並禁用Cull的面部,但我一直看到每個網格的相同三角形。任何想法爲什麼這樣?圖片不錯:https://puu.sh/vwZAc/e108f7fb9c.png。圖片不好:https://puu.sh/vx0j6/a8eddd1d7d.png –

+0

嘗試在循環外釋放「glBindVertexArray(0); //釋放vao」....我的意思是在每個循環之後......在函數「Render()」 – Naidu

+0

這似乎並不工作:\。也嘗試glBindVertexArray(Vao)外循環(這似乎邏輯),但不幸的是沒有改變。 –

相關問題