基本的openGL,顶点缓冲区和pyglet

Nic*_*vre 6 python opengl pyglet

编辑:rotoglup在我的代码中发现了问题,添加了我删除的着色器完成了解决方案.请参阅下面的答案以获取正确的代码(使用着色器).

大家好 !

我正在尝试从本教程中学习一些现代OpenGL的基础知识.

我想用python/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()
Run Code Online (Sandbox Code Playgroud)

rot*_*lup 5

glDrawArrays(GL_POINTS, 0, 1)
Run Code Online (Sandbox Code Playgroud)

指示画1点,在你的教程中,1是3:

glDrawArrays(GL_POINTS, 0, 3)
Run Code Online (Sandbox Code Playgroud)

另请注意,顶点的第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]
Run Code Online (Sandbox Code Playgroud)

或者,您可以删除w组件,

  vertexPositions = [0.0, 0.0, 0.0,
                     0.25, 0.0, 0.0,
                     1.75, 1.75, 0.0]
Run Code Online (Sandbox Code Playgroud)

并将以下调用更改为:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0)
Run Code Online (Sandbox Code Playgroud)

另一件事,我不是pyglet的专家,但glBufferData可能像C语言一样采用字节大小而不是元素.每个浮点数为4个字节,您可以尝试:

glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)
Run Code Online (Sandbox Code Playgroud)


Nic*_*vre 5

我终于做对了!

看来我被以下事实误导了:摆弄顶点、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()
Run Code Online (Sandbox Code Playgroud)