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

发布于 2024-10-10 17:01:46 字数 1511 浏览 0 评论 0原文

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

大家好!

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

我想用 python/pyglet 而不是 C++ 来实现。我知道 pyglet 可以抽象出大部分低级 OpenGL;在继续将它们隐藏在抽象层后面之前,我想了解一些基础知识。

我的问题非常简单:下面的代码只绘制一个点,而不是我期望的 3 个点。 据我所知,我的代码与教程中的 C++ 相同,除了删除顶点和片段着色器(通过 gletools in python),这似乎对我的问题没有影响。

将事情简化为一个点显示了我不理解的行为(第一个坐标似乎是唯一影响任何事情的坐标),使我回到了我的信念,即我根本无法理解有关 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()

Edit: rotoglup found the problems in my code, adding the shaders I had removed completed the solution. See my answer below for the correct code (with shaders).

Hi all !

I'm trying to learn some basics of modern OpenGL from this tutorial.

I'd like to do it with python/pyglet instead of C++ though. I know pyglet can abstract much of the low level OpenGL away; I want to understand some of the basics before moving on to hiding them behind layers of abstraction though.

My problem is extremely simple: the code below only draws a single point instead of the 3 I am expecting.
My code is, as far as I can tell, identical to the C++ in the tutorial, except for the removal of vertex and fragment shaders (done via gletools in python), which appears to make no difference to my problem.

Simplifying things to a single point shows behaviour I do not understand (the first coordinate appears to be the only one that affects anything), leading me back to my belief that I've simply failed to understand something very basic about either pyglet, OpenGL, or even 3D in general :p

Here's the relevant code:

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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

歌枕肩 2024-10-17 17:01:46
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)

Another事情,我不是 pyglet 的专家,但 glBufferData 可能像它的 C 对应项一样,采用字节大小,而不是元素大小。每个浮点数为 4 个字节,你可以尝试:

glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)
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)
南风几经秋 2024-10-17 17:01:46

我终于做对了!

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

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文