2010-06-01 61 views
1

我的頂點緩衝區對象代碼應該很好地渲染紋理,但相反,紋理渲染奇怪與一些三角形形狀。OpenGL頂點緩衝對象代碼給出了不好的輸出

會發生什麼 - http://godofgod.co.uk/my_files/wrong.png

什麼是應該發生 - http://godofgod.co.uk/my_files/right.png

這個函數創建VBO並設置頂點和紋理座標數據:

extern "C" GLuint create_box_vbo(GLdouble size[2]){ 
    GLuint vbo; 
    glGenBuffers(1,&vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    GLsizeiptr data_size = 8*sizeof(GLdouble); 
    GLdouble vertices[] = {0,0, 0,size[1], size[0],0, size[0],size[1]}; 
    glBufferData(GL_ARRAY_BUFFER, data_size, vertices, GL_STATIC_DRAW); 
    data_size = 8*sizeof(GLint); 
    GLint textcoords[] = {0,0, 0,1, 1,0, 1,1}; 
    glBufferData(GL_ARRAY_BUFFER, data_size, textcoords, GL_STATIC_DRAW); 
    return vbo; 
} 

下面是一些初步認識代碼另一個應該用VBO繪製紋理的函數。

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 
glColor4d(1,1,1,a/255); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTranslated(offset[0],offset[1],0); 
glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glVertexPointer(2, GL_DOUBLE, 0, 0); 
glEnableClientState(GL_VERTEX_ARRAY); 
glTexCoordPointer (2, GL_INT, 0, 0); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
glDrawArrays(GL_TRIANGLES, 0, 3); 
glDrawArrays(GL_TRIANGLES, 1, 3); 
glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
glDisableClientState(GL_VERTEX_ARRAY); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

我本來希望在代碼中使用的前三個座標(左上,左下,右上)和最後三個(左下,右上,右下)以最有效的方式正確繪製具有紋理數據的三角形。我不明白爲什麼三角形應該使它更有效率,但顯然這是要走的路。當然,它由於某種原因失敗。

我在問什麼是壞的,但我是否正常地以正確的方式去做?

謝謝。

回答

1

如果你想使用一個VBO的頂點和紋理座標,你需要使用一個結構對它們進行分組。

定義你的數據:

typedef struct { 
    GLdouble x, y; 
    GLint s, t; 
} VertexData; 

VertexData data[] = { 
// x  y  s t 
    {0.0,  0.0,  0, 0}, 
    {0.0,  size[1], 0, 1}, 
    {size[0], 0.0,  1, 0}, 
    {size[0], size[1], 1, 1} 
}; 

將其複製到VBO:

glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glBufferData(GL_ARRAY_BUFFER, sizeof(data), (GLvoid*)data, GL_STATIC_DRAW); 

設置指針。請注意,步幅是您的結構的大小和指針本身作爲偏移:

glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glVertexPointer(2, GL_DOUBLE, sizeof(VertexData), (GLvoid*)offsetof(VertexData, x)); 
glTexCoordPointer(2, GL_INT, sizeof(VertexData), (GLvoid*)offsetof(VertexData, s)); 
glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

並繪製。

編輯:用Bahbar建議的offsetof()實現偏移量。

+1

真正挑剔,但您最好使用某種形式的offsetof來查找紋理座標的偏移量。這裏y和s之間可能沒有填充,但是說你有3個短褲,那麼這個故事會非常不同(3 * sizeof(GLshort)將是錯誤的偏移量,因爲偏移量可能是8個字節,而不是6)。 – Bahbar 2010-06-02 08:11:20

+0

非常感謝您的支持。我現在正在研究它。 – 2010-06-02 12:11:48

+0

使用GLdouble作爲紋理座標以及頂點,當然我可以使用多維數組?我需要爲我的圓角紋理使用雙精度紋理座標。 – 2010-06-02 12:36:16

0

您正在向vbo加載兩次數據。第二次調用glBufferData將替換第一個。然後,在調用繪製時,對gl *指針的調用實際上使用相同的數據。

+0

謝謝你的回答。 我在某處讀到它可以這樣做。這是一個話題,想要一個解決方案的人說它工作。 如果我把頂點之後的紋理座標放在「glTexCoordPointer」裏面,我該怎麼做?我不明白如何讓它指向紋理座標開始的數組中的第9個元素。 我可以將這些點函數放在create_box_vbo函數中並只使用它們一次嗎? 再次感謝您。 – 2010-06-01 19:59:07

+0

嗯,我只是試圖移動的功能,它使情況變得更糟,所以我想我不能這樣做。 – 2010-06-01 20:01:39

+0

我只是覺得每個紋理的紋理座標都是一樣的,所以爲什麼不只是有一個VBO紋理座標。愚蠢的是不這樣做。 – 2010-06-01 20:33:57