7

编辑: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()
4

2 回答 2

5
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)
于 2011-01-06T19:30:03.020 回答
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()
于 2011-01-07T11:07:32.563 回答