2011-01-06 125 views
6

編輯:rotoglup發現在我的代碼中的問題,增加我已經刪除完成解決方案的着色器。請在下面查看我的答案以獲取正確的代碼(使用着色器)。基本的OpenGL,頂點緩衝區和pyglet

大家好!

我努力學習現代的OpenGL的一些基本知識,從this tutorial

我想和蟒蛇/ pyglet而不是C++這樣做雖然。我知道pyglet可以將很多低級別的OpenGL抽象出來;我想了解一些基本知識,然後繼續將它們隱藏在抽象層之後。

我的問題非常簡單:只在下面的代碼繪製一個點,而不是3我期待。 就我所知,我的代碼與本教程中的C++完全相同,除了刪除頂點和片段着色器(通過Python中的gletools完成),這似乎對我的問題沒有任何影響。

將事物簡化爲一個點顯示出我不明白的行爲(第一個座標似乎是唯一影響任何事物的座標),這讓我回到了我的信念,即我沒有理解關於pyglet,OpenGL的,甚至是3D一般:p

下面是相關代碼:

import pyglet 
from pyglet.gl import * 

window = pyglet.window.Window() 

positionBufferObject = GLuint() 
vao = GLuint() 

vertexPositions = [0.0, 0.0, 0.0, 
        0.25, 0.0, 0.0, 
        1.75, 1.75, 0.0] 

vertexPositionsGl = (GLfloat * len(vertexPositions))(*vertexPositions) 

@window.event 
def on_draw(): 
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 
    glEnableVertexAttribArray(0) 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0) 
    glDrawArrays(GL_POINTS, 0, 3) 
    glDisableVertexAttribArray(0) 

glGenBuffers(1, positionBufferObject) 
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 
glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW) 
glBindBuffer(GL_ARRAY_BUFFER, 0) 

glClearColor(0.0, 0.0, 0.0, 0.0) 
pyglet.app.run() 
+0

你的意思是,使用正確的代碼,你仍然有一個單點繪製?這一點是否畫在屏幕的中間?如果你改變了第一個座標,點是否移動? – rotoglup 2011-01-06 22:06:22

+0

使用已更正的代碼,我得到的最好的仍然是一個不會隨w座標移動1的單個點,並以字節爲單位傳遞大小。如果我刪除了w座標並相應地更改了glVertexAttribpointer,我什麼也得不到。我徹底困惑! – 2011-01-07 07:36:03

回答

5
glDrawArrays(GL_POINTS, 0, 1) 

指示繪製1點,在您的教程,1是3:

glDrawArrays(GL_POINTS, 0, 3) 

另請注意,您的頂點的第4(W)分量應該是1,而不是0:

vertexPositions = [0.0, 0.0, 0.0, 1.0, 
        0.25, 0.0, 0.0, 1.0, 
        1.75, 1.75, 0.0, 1.0] 

或者,你可以刪除w成分,

vertexPositions = [0.0, 0.0, 0.0, 
        0.25, 0.0, 0.0, 
        1.75, 1.75, 0.0] 

和更改以下調用:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0) 

另一件事,我不是在pyglet的專家,但它可能是glBufferData與其C對象一樣,以字節爲單位,而不是元素。每個浮點數爲4個字節,你可以嘗試:

glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW) 
4

我終於得到了這個權利!

看來我是被由與頂點,調用glDrawArrays和glVertexAttribPointer有時會導致單點擺弄正在顯示的事實所誤導。 這似乎是一個意外:由rotoglup的答案提供的更正,什麼都沒有繪製。這是我原始問題中代碼的「正確」行爲。

我的情況下,錯誤的清單可以幫助任何人:

  • 設置w值0,而不是1,完全失蹤教程夾空間轉換的解釋。

  • 當glBufferData需要字節時,給頂點緩衝區的大小。

  • 刪除頂點和片段着色器(以簡化代碼,同時尋找上述兩個問題)。這確保了什麼都不會呈現......除了我有時得到的(單車)單點。

爲了記錄,下面的代碼顯示了一個單一的三角形,通過着色器,我希望能夠更新和更正OpenGL。要求是pyglet和gletools。

import pyglet 
from pyglet.gl import * 
from gletools import ShaderProgram, FragmentShader, VertexShader 

window = pyglet.window.Window() 

positionBufferObject = GLuint() 

vertexPositions = [0.75, 0.75, 0.0, 1.0, 
        0.75, -0.75, 0.0, 1.0, 
        -0.75, -0.75, 0.0, 1.0] 
vertexPositionsGl = (GLfloat * len(vertexPositions))(*vertexPositions) 

program = ShaderProgram(
    FragmentShader(''' 
    #version 330 
    out vec4 outputColor; 
    void main() 
    { 
     outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); 
    }'''), 
    VertexShader(''' 
    #version 330 
    layout(location = 0) in vec4 position; 
    void main() 
    { 
     gl_Position = position; 
    }''') 
) 

@window.event 
def on_draw(): 
    with program: 
     glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 
     glEnableVertexAttribArray(0) 
     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0) 
     glDrawArrays(GL_TRIANGLES, 0, 3) 
     glDisableVertexAttribArray(0) 

glGenBuffers(1, positionBufferObject) 
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 
glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW) 
glBindBuffer(GL_ARRAY_BUFFER, 0) 

pyglet.app.run()