basic openGL, vertex buffers and pyglet

狂风中的少年 提交于 2019-11-30 07:28:58
glDrawArrays(GL_POINTS, 0, 1)

instructs to draw 1 point, in your tutorial, 1 is 3 :

glDrawArrays(GL_POINTS, 0, 3)

Notice also that the 4th (w) component of your vertices should be 1, not 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]

Alternatively, you could remove the w component,

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

and change the following call to :

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

Another thing, I'm not an expert in pyglet, but it's possible that glBufferData, like its C counterpart, take a size in bytes, not in elements. Each float being 4 bytes, you could try :

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

I finally got this right !

It seems I was being misled by the fact that fiddling with vertices, glDrawArrays and glVertexAttribPointer sometimes resulted in a single dot being shown. This appears to be an accident: with the corrections provided by rotoglup's answer, nothing at all is drawn. This is the "correct" behaviour for the code in my original question.

An inventory of my mistakes in case it helps anyone:

  • setting the w coordinate to 0, instead of 1, completely missing the explanations for clip-space transformation in the tutorial.

  • giving glBufferData the size of the buffer in vertices when it expects bytes.

  • removing the vertex and fragment shaders (to simplify the code while looking for the above two issues). This ensured that nothing would ever be rendered... except the (buggy ?) single dot I was sometimes getting.

For the record, the code below displays a single triangle, with pass through shaders, in what I hope to be up to date and correct OpenGL. Requirements are pyglet and 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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!