2011-05-25 74 views
7

好了,所以我仍然在努力得到這個工作。我的代碼的重要部分是:調用glDrawArrays VS glDrawElements

def __init__(self, vertices, normals, triangles): 
    self.bufferVertices = glGenBuffersARB(1) 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices) 
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(vertices), ADT.voidDataPointer(vertices), GL_STATIC_DRAW_ARB) 
    self.vertices = vertices 
    self.bufferNormals = glGenBuffersARB(1) 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals) 
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(normals), ADT.voidDataPointer(normals), GL_STATIC_DRAW_ARB) 
    self.normals = normals 
    self.bufferTriangles = glGenBuffersARB(1) 

    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles) 
    glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ADT.arrayByteCount(triangles), ADT.voidDataPointer(triangles), GL_STATIC_DRAW_ARB) 

    self.triangles = triangles 
    glDisableClientState(GL_VERTEX_ARRAY) **(Not sure if any of the following influence in any way)** 
    glDisableClientState(GL_NORMAL_ARRAY) 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0) 
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0) 

我不覺得有什麼錯在這裏從我迄今爲止關於VBO的讀取。所以現在我有我的頂點,法線(尚未使用)和三角形索引緩衝區。現在爲實際繪製:

def draw(self, type): 
    glDisableClientState(GL_VERTEX_ARRAY) 
    glDisableClientState(GL_NORMAL_ARRAY) 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0) 
    glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0) 
    **Again above line not sure if they have any use.**   
    glEnableClientState(GL_VERTEX_ARRAY)   
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices) 
    glVertexPointer(3, GL_FLOAT, 0, None) 

    glEnableClientState(GL_NORMAL_ARRAY); 
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals) 
    glNormalPointer(GL_FLOAT, 0, None) 

    if type == GL_POINTS:  
     #glDrawArrays(GL_POINTS, 0, len(self.vertices));  
     glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0) 
    else: 
     #glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles)**(If I uncomment this doesnt seem to make any difference?!)** 
     #glDrawArrays(GL_TRIANGLES, 0, len(self.triangles)); 
     glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0)**(What does it draw now since GL_ELEMENT_ARRAY_BUFFER_ARB is binded to 0 ?!)** 

現在glDrawArrays的作品。但是在我必須繪製三角形的情況下,它不繪製我在bufferTriangles中定義的三角形(這是從drawArrays不使用索引以來我讀過的正常情況?或者我錯了嗎?)。問題是,如果我嘗試使用與glDrawElements一切都崩潰:

Exception Type: EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes: KERN_INVALID_ADDRESS at 0x000000003150ebbc 
Crashed Thread: 0 

Thread 0 Crashed: 
0 com.apple.GeForce8xxxGLDriver 0x1a3e7050 gldGetTextureLevel + 743600 
1 com.apple.GeForce8xxxGLDriver 0x1a3e7563 gldGetTextureLevel + 744899 
2 GLEngine      0x1a206eee gleDrawArraysOrElements_VBO_Exec + 1950 

現在我缺少什麼嗎?從我能理解的情況來看,我可能在某處傳遞了一個糟糕的指針?請注意,即使我嘗試使用glDrawElements(類型,24,GL_UNSIGNED_INT,0),它仍然崩潰甚至壽定義的三角形數量是這樣的方式更大,所以我不認爲這有什麼與大小。

問候, 波格丹

編輯: 好了,所以現在我已經做了一些額外的檢查,這裏是我目前的情況:我已經改變了LEN(三角形),以ADT.byteCount,無解然而。所以我檢查了我得到的所有數據,它是這樣的:頂點數組包含~60000 * 3 = 180000個GL_Float類型的頂點條目,和法線數組一樣。由於只有< 62535頂點我使用無符號三角形短。所以我有len(三角形)是~135000。我也改變了glDrawElements(GL_TRIANGLES,LEN(self.triangles),GL_UNSIGNED_SHORT,0).I've還檢查了所有的數據從三角形陣列是0和62534之間,我想也許一些指數這是超出範圍滑槽。這裏還有什麼可能是錯的? 哦,glDrawElements(GL_POINTS,...)是如何工作的?它是否也需要某種指數?

EDIT2 我已經更新上面的代碼和說有,現在畫的元素吸引我的GL_POINTS,但我不知道他在哪裏得到指數?或者在GL_POINTS的情況下不需要它們?而對於GL_TRIANGLES,它是這樣工作的,與glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,self.bufferTriangles)commentated,卻又什麼樣的指標它現在的元素緩衝區綁定到0採取這裏?!另一件事是,glDrawElements不會繪製glDrawArrays所做的所有點。爲了更好地explatin:

glDrawArrays(GL_POINTS, 0, len(self.vertices)); 

這正確吸取我的所有點:

glDrawElements(type, len(self.vertices), GL_UNSIGNED_SHORT, 0) 

這似乎明顯吸取少得多百分點,比調用glDrawArrays。現在,有趣的是,如果我通過爲大小像10 * LEN(self.vertices)來繪製,將繪製所有點元素(有的也許兩次以上的;我可以檢查這個?),但母艦一樣想崩潰?

問候

EDIT3

關於陣列的一些更精確的信息:

頂點 - 浮點數的數組,

LEN(頂點)= 180000 BYTECOUNT(頂點) = 720000

triangles - 一個numpy.uint16的數組

LEN(三角形)= 353439 BYTECOUNT(三角形)= 706878 分鐘(三角形)= 0 最大值(三角形)= 59999,所以它們應指向有效頂點

的附圖進行:

glDrawElements(GL_TRIANGLES,LEN(self.triangles),GL_UNSIGNED_SHORT,0)

UPDATE

好吧只是當我因子評分我這應該是如何工作的,我試圖跳過VBO的元素去只是:

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles)) 

現在不僅做這項工作,並完全吸引我的所有的三角形,但是FPS是更好。 VBO不應該更快嗎?有什麼能導致上述的方法來工作,但下面的死機:

glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, self.bufferTriangles) 
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ADT.arrayByteCount(triangles), ADT.voidDataPointer(triangles), GL_STATIC_DRAW_ARB) 
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0) 

回答

4

我有使用Python GL沒有經驗,但我想我發現了一些東西。你在調用glDrawElements時使用len(self.triangles),所以我想這會給你三角形數組中索引的數量。但爲什麼然後在glBufferData中使用len(triangles)作爲大小,而不是在其他調用中使用ADT.arrayByteCount。所以你的緩衝區太小了,因爲它包含len(triangles)字節,儘管三角形包含未簽名的整數。如果三角形確實包含字節(我懷疑),您將不得不在glDrawElements中使用GL_UNSIGNED_BYTE

編輯:根據您的編輯我得到了更多的答案。當然glDrawElements(GL_POINTS, ...)也需要索引。它只是使用每個索引來繪製一個點,而不是每三個三角形的索引。這只是因爲你經常不需要glDrawElements,因爲你不會重複使用頂點,但是你仍然需要它的索引。它不會神奇地變成引擎蓋下的glDrawArrays

並記住,vertices數組包含浮動和glDrawArrays繪製頂點,因此您必須繪製len(vertices)/3頂點。 Juts記得,一個元素是一個索引(單個頂點),而不是一個三角形,頂點是3個浮點數(或者你在glVertexPointer中指定的),而不僅僅是一個。

但是,如果您的triangles數組確實包含3個索引的元組(因此len(triangles)是三角形數而不是索引數),則必須繪製3*len(triangles)元素(索引)。並且如果您的數組包含矢量而不僅僅是浮點數,則在glDrawArrays調用中繪製len(vertices)頂點是正確的。因此很高興看到他們的聲明是確定的。

+0

是的,使用glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,4 * LEN(三角形),ADT.voidDataPointer(三角形),GL_STATIC_DRAW_ARB)。用sizeof(unsigned int) – Calvin1602 2011-05-25 13:56:18

+0

的python替換「4」好的謝謝,但是當我嘗試這樣做時,我在那裏發生了崩潰。該緩衝區是否有一些最大尺寸?目前,我的三角形長度爲353439,字節數爲1413756。這是否會導致崩潰? – Bogdan 2011-05-25 15:27:27

+0

忽略我最後的評論。我會仔細看看,然後回來。 – Bogdan 2011-05-25 15:30:23

0

根據我的經驗,一旦你開始使用一些更高級的OpenGL調用,Python OpenGL封裝器就非常麻煩。許多調用似乎無緣無故地導致崩潰,有時甚至會以相同順序的不同調用來替代它們......我爲OpenGL切換了編程語言,而不必處理這些問題。

+0

是的,我注意到,仍然有一些越野車方面,尤其是當使用VBO的時候,但除了標準C和後面的集成之外,我沒有其他選擇,我將作爲最後的手段離開。 – Bogdan 2011-06-05 16:31:51

0

之所以

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles)) 

作品和

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, 0) 

不會是因爲PyOpenGL預計None爲void指針,而不是0使用C語言編寫的OpenGL的例子時要小心,因爲它們使用(void*)0作爲void指針,而PyOpenGL並沒有將它正確地解釋爲一個指針,而它將0視爲一個非空值。

相反,你應該使用

glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, None) 

(參見https://stackoverflow.com/a/14365737/478380