2011-01-06 18 views
6

Editar: rotoglup encontró los problemas en mi código, agregando los sombreadores que había eliminado completaron la solución. Ver mi respuesta a continuación para el código correcto (con sombreadores).basic openGL, buffers de vértice y pyglet

¡Hola a todos!

Estoy tratando de aprender algunos conceptos básicos de OpenGL moderno desde this tutorial.

Me gustaría hacerlo con python/pyglet en lugar de C++. Sé que pyglet puede abstraer gran parte del bajo nivel de OpenGL; Sin embargo, quiero entender algunos de los conceptos básicos antes de seguir ocultándolos detrás de capas de abstracción.

Mi problema es extremadamente simple: el siguiente código solo dibuja un punto único en lugar de los 3 que estoy esperando. Mi código es, hasta donde puedo decir, idéntico al C++ en el tutorial, excepto por la eliminación de los sombreadores de vértices y fragmentos (hecho a través de gletools en python), que parece no afectar mi problema.

Simplificar las cosas en un solo punto muestra un comportamiento que no entiendo (la primera coordenada parece ser la única que afecta a algo), lo que me lleva a pensar que simplemente no pude entender algo muy básico sobre cualquiera Pyglet, OpenGL, o incluso en 3D en general: p

Aquí está el código correspondiente:

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

¿Quiere decir que con el código corregido, todavía tiene un único punto dibujado? ¿Este punto está dibujado en el medio de la pantalla? Si cambias las primeras coordenadas, ¿se mueve el punto? – rotoglup

+0

Con el código corregido, lo mejor que obtengo es un único punto que no se mueve con la coordenada w en 1 y pasando el tamaño en bytes. Si elimino las coordenadas w y cambio glVertexAttribPointer en consecuencia, no obtengo nada. ¡Estoy completamente confundido! –

+0

Corrección: w tiene que estar en 0 para que se muestre algo, lo que me hace más confuso. –

Respuesta

5
glDrawArrays(GL_POINTS, 0, 1) 

instruye para sacar 1 punto, en su tutorial, 1 es 3:

glDrawArrays(GL_POINTS, 0, 3) 

Nótese también que el componente cuarto (w) de sus vértices debe ser de 1, no 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] 

Como alternativa, puede quitar el componente W,

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

y cambiar el la siguiente llamada a:

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

Otra cosa, no soy un experto en pyglet, pero es posible que glBufferData, al igual que su contraparte C, toma un tamaño en bytes, no en elementos. Cada flotador tiene 4 bytes, puede intentar:

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

¡Gracias por la respuesta! He editado mi pregunta con sus sugerencias (en realidad, había intentado con la versión correcta de drawArray pero olvidé restaurarla antes de copiar mi código). Aunque el problema aún existe ... empiezo a preguntarme si algo está mal con mi versión de pyglet, tuve que instalar la versión de desarrollo para usar gletools. –

+0

Editó la respuesta para agregar otra corrección posible. – rotoglup

+0

¡Gracias por la (más) respuesta! Todavía no hay alegría, lamentablemente ... Estoy empezando a preguntarme si esto es específico de pyglet en lugar de ser un problema de OpenGL. ¡Probaré la lista de correos de pyglet e informaré! –

4

¡Finalmente lo conseguí!

Parece que me estaba engañando el hecho de que jugar con los vértices, glDrawArrays y glVertexAttribPointer a veces daba como resultado la visualización de un solo punto. Esto parece ser un accidente: con las correcciones proporcionadas por la respuesta de rotoglup, no se dibuja nada. Este es el comportamiento "correcto" para el código en mi pregunta original.

un inventario de mis errores en caso de que ayuda a nadie:

  • establecer la coordenada w a 0, en lugar de 1, falta por completo las explicaciones para la transformación clip-espacio en el tutorial.

  • dando glBufferData el tamaño del búfer en los vértices cuando espera bytes.

  • eliminando el vértice y fragmenta los sombreadores (para simplificar el código mientras se buscan los dos problemas anteriores). Esto aseguró que nada se renderizaría ... excepto el único punto (con errores) que a veces obtengo.

Para el registro, el siguiente código muestra un solo triángulo, con sombreadores de paso, en lo que espero que esté actualizado y corrija OpenGL. Los requisitos son pyglet y 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() 
Cuestiones relacionadas