2016-04-21 284 views
0

我試圖在OpenGL 3.3中渲染Suzanne(來自Blender),但緩衝區數據似乎並不正確。我得到這個:glBufferData和glBufferSubData Offset

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

我也試圖呈現一個球體用一個簡單的紋理:

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

我進口商插入頂點數據到一個std ::向量爲單精度浮點:

if(line.substr(0,2) == "v ") 
{ 
/** Vertex position */ 
    std::istringstream s(line.substr(2)); 
    float v[3]; 
    s >> v[0]; s >> v[1]; s >> v[2]; 

    this->vertices.push_back(v[0]); 
    this->vertices.push_back(v[1]); 
    this->vertices.push_back(v[2]); 
} 

我設置陣列緩衝器如下:

glGenBuffers(1, &this->vbo); 
glBindBuffer(GL_ARRAY_BUFFER, this->vbo); 

glBufferData(GL_ARRAY_BUFFER, 
    sizeof(float)*(this->vertices.size()+this->textures.size()+this->normals.size()), 
    NULL, 
    GL_STATIC_DRAW); 

然後我用glBufferSubData

glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*this->vertices.size(), this->vertices.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*this->vertices.size(), sizeof(float)*this->textures.size(), this->textures.data()); 
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*(this->vertices.size()+this->textures.size()), sizeof(float)*this->normals.size(), this->normals.data()); 

我也插入相同的方式索引(當然GL_ELEMENT_ARRAY_BUFFER)插入的實際數據。

然後我點到的信息:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size())); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size()+this->vt.size())); 

我的頂點着色器需要在這樣的數據:

layout(location = 0) in vec3 position; 
layout(location = 1) in vec2 texCoord; 
layout(location = 2) in vec3 normals; 

難道我搞砸了偏移?

編輯: 我想出了最大的問題!我編寫了一個外部的Lua程序來將obj文件轉換爲更易於導入的格式,但最終導致數據混亂並在「f#/#/#/#/#/#/#/ #「所以文件看起來像這樣(x-> y-> x)而不是(x-> y-> z)

還修復了其他幾個錯誤,這要歸功於下面的回覆!

+0

好抓!很高興你能夠得到它的工作。 – Exide

+0

非常感謝您的幫助!一切都在工作。 :D我意識到當我繪製網格的「線框」時,我使用的是GL_LINE_LOOP而不是glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);因此,網格內部的額外面。這是證明:P https://gyazo.com/928640e745bfe3041798954f3f32079a – sheep

回答

0

沒有看到你的着色器我不能100%確定你的電話glVertexAttribPointer是否合法。我也不知道你是否想在一個VBO中交錯頂點數據。你現在擁有的所有頂點位置,然後是所有的紋理座標,最後是所有的法線。

要插入數據,首先要將所有數據放入單個數組(或向量),以便每個頂點重複使用PPPTTNNN模式。其中PPP是三位浮標,TT是兩個texcoord浮標,NNN是三個正常浮標。

它看起來像這樣(使用虛假類型,值和間距,以幫助說明模式):

float[] vertices = { 
/* pX, pY, pZ, tX, tY, nX, nY, nZ */ 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 1 
    0, 0, 0, 1, 1, 0, 0, 0,  // vertex 2 
    1, 1, 1, 0, 0, 1, 1, 1,  // vertex 3 
    ... 
}; 

比方說,你把它所有到一個名爲vertices單一的載體,那麼你就可以上傳它用一個命令:

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW); 

你也可以把每個屬性放到它自己的VBO中。您如何決定將數據存儲在GPU上最終取決於您。如果您故意按照您的方式存儲數據,請在評論中告訴我,我會更新答案。

好的,現在着色位。

比方說,你已經有了一個頂點着色器,看起來像這樣:

in vec3 position; 
in vec2 texcoord; 
in vec3 normal; 
out vec2 uv; 

void main() { 
    gl_Position = vec4(position, 1); 
    uv = texcoord; 
} 

和片段着色器,看起來像這樣:

in vec2 uv; 
uniform sampler2D image; 
out vec4 color; 

void main() { 
    color = texture(image, uv); 
} 

然後,你會希望以下glVertexAttribPointer電話:

int stride = (3 + 2 + 3) * sizeof(float); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)3); 
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)5); 

注意每個呼叫的第一個參數是不同的數。這在頂點着色器中分別對應於position,texcoord,normal

另外,紋理座標通常只有一對浮點數(例如vec2 texcoord),所以我將texcoord調用的第二個參數更改爲2

最後,當使用交錯數組時,最後一個參數只需要指定每個頂點的偏移量。因此,我們分別得到0,35分別用於位置偏移,texcoord偏移和正常偏移。

希望這可以讓你得到你想要的東西。

查看docs.gl page on glVertexAttribPointer瞭解更多信息。

+0

感謝您的迴應!我會用着色器更新我的問題!我從obj文件獲取數據的方式使得僅僅追加數據而不是交織數據變得容易。 – sheep