Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基本openGL、顶点缓冲区和pyglet_Python_Opengl_Pyglet - Fatal编程技术网

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

Python 基本openGL、顶点缓冲区和pyglet,python,opengl,pyglet,Python,Opengl,Pyglet,Edit:rotoglup在我的代码中发现了问题,添加了我删除的着色器完成了解决方案。有关正确的代码(使用着色器),请参见下面的答案。 大家好 我正试图从中学习一些现代OpenGL的基础知识 我希望用Python/PygLee来代替C++。我知道pyglet可以抽象出很多底层OpenGL;我想先了解一些基础知识,然后再将它们隐藏在抽象层后面 我的问题非常简单:下面的代码只画了一个点,而不是我期望的3个点。 据我所知,我的代码与教程中的C++完全相同,除了删除顶点和片段着色器(通过Python完成

Edit:rotoglup在我的代码中发现了问题,添加了我删除的着色器完成了解决方案。有关正确的代码(使用着色器),请参见下面的答案。

大家好

我正试图从中学习一些现代OpenGL的基础知识

我希望用Python/PygLee来代替C++。我知道pyglet可以抽象出很多底层OpenGL;我想先了解一些基础知识,然后再将它们隐藏在抽象层后面

我的问题非常简单:下面的代码只画了一个点,而不是我期望的3个点。 据我所知,我的代码与教程中的C++完全相同,除了删除顶点和片段着色器(通过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()
指示绘制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)

我终于弄对了

我似乎被这样一个事实误导了:摆弄顶点、GLDrawArray和GLVertexAttributePointer有时会导致显示单个点。 这似乎是一个意外:根据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()

谢谢你的回答!我已经根据您的建议编辑了我的问题(实际上我已经尝试了drawArray调用的正确版本,但在复制代码之前忘记了恢复它)。但是这个问题仍然存在。。。我开始怀疑我的pyglet版本是否有问题,为了使用gletools,我不得不安装开发版本。谢谢(进一步)回答!不幸的是,仍然没有快乐。。。我开始怀疑这是否是pyglet特有的,而不是OpenGL的问题。我将尝试pyglet邮件列表并报告!这可能是一个解决办法。如果您对3d、opengl等都是新手,那么还应该尝试遵循更简单的教程,不使用缓冲区对象,使用普通的glVertex调用。通过消除python浮点到字节的问题,这将使事情变得更加明显。你可以试试NeHe教程。再次感谢你,我终于找到了工作,并添加了正确的代码作为答案。我错误地认为现在可以跳过着色器,而实际上它们是必需的,但由于您在我的代码中更正的问题而无法工作!我意识到从缓冲区对象和着色器开始有点冒险,但我想了解“好的老”OpenGL(已经阅读了一些NeHe教程)和最近的方法之间的区别:)你的意思是,使用正确的代码,仍然绘制了一个点?这一点是在屏幕中间画出来的吗?如果更改第一个坐标,该点会移动吗?使用更正的代码,我得到的最好结果仍然是一个点,该点不会随着w坐标为1并以字节为单位传递大小而移动。如果我删除w坐标并相应地更改GLVERTEXATTRIBCPOINTER,则什么也得不到。我完全糊涂了!更正:w必须为0才能显示某些内容,这只会让我更加困惑。这可能与在您不知道的情况下发生的某些剪辑有关。由于您没有设置任何投影或变换矩阵,所以您的第三点肯定是在屏幕外。由于Z值的原因,其他的也可能被剪裁。不过,我没有想到默认的opengl投影。您应该尝试调用glOrtho来安装投影。你也应该试着画一个三角形,如果一些点在无穷远处或屏幕之外,它会使事情变得更加明显。
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()