【问题标题】:basic openGL, vertex buffers and pyglet基本的 openGL、顶点缓冲区和 pyglet
【发布时间】:2011-01-06 19:24:19
【问题描述】:

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

大家好!

我正在尝试从this tutorial 学习一些现代 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()

【问题讨论】:

  • 你的意思是用更正的代码,你仍然有一个单点绘制?这个点是画在屏幕中间的吗?如果你改变第一个坐标,点会移动吗?
  • 使用更正后的代码,我得到的最好的仍然是一个单点,它不会随着 w 坐标为 1 移动并以字节为单位传递大小。如果我删除 w 坐标并相应地更改 glVertexAttribPointer,我什么也得不到。我彻底糊涂了!
  • 更正:w 必须为 0 才能显示某些内容,这只会让我更加困惑。
  • 这可能与在您不知情的情况下发生的一些剪辑有关。由于您没有设置任何投影或变换矩阵,因此您的第三点肯定在屏幕外。由于 Z 值,其他的也可能被剪裁。不过,我没有考虑默认的 opengl 投影。您应该尝试调用 glOrtho 来安装投影。您还应该尝试绘制一个三角形,如果某些点在无限远或屏幕外,它会使图形更加明显。

标签: python opengl pyglet


【解决方案1】:
glDrawArrays(GL_POINTS, 0, 1)

指示绘制 1 个点,在您的教程中,1 是 3:

glDrawArrays(GL_POINTS, 0, 3)

另请注意,顶点的第四 (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)

【讨论】:

  • 感谢您的回答!我已经根据您的建议编辑了我的问题(我实际上尝试了正确版本的 drawArray 调用,但在复制我的代码之前忘记恢复它)。但问题仍然存在......我开始怀疑我的 pyglet 版本是否有问题,我必须安装开发版本才能使用 gletools。
  • 感谢您的(进一步)回答!不幸的是,仍然没有快乐......我开始怀疑这是否特定于 pyglet 而不是 OpenGL 问题。我会尝试 pyglet 邮件列表并报告!
  • 这可能是一个解决方案。如果您是 3d、opengl 等的新手,您还应该尝试遵循一个更简单的教程,没有缓冲区对象,使用普通的旧 glVertex 调用。通过确定将 python 浮点数删除到字节问题,这将使事情变得更加明显。你可以试试 NeHe 教程。
  • 再次感谢,我终于让事情正常了,并添加了更正的代码作为答案。我错误地认为着色器现在可以被跳过,而实际上它们是必要的,但由于您在我的代码中纠正的问题而无法工作!我意识到从缓冲区对象和着色器开始有点冒险,但我想了解“旧的”OpenGL(已经阅读了一些 NeHe 教程)和更新的方法之间的区别:)
【解决方案2】:

我终于做对了!

我似乎被这样一个事实误导了,即摆弄顶点、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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    相关资源
    最近更新 更多