简体   繁体   English

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

[英]basic openGL, vertex buffers and pyglet

Edit: rotoglup found the problems in my code, adding the shaders I had removed completed the solution. 编辑:rotoglup在我的代码中发现了问题,添加了我删除的着色器完成了解决方案。 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 . 我正在尝试从本教程中学习一些现代OpenGL的基础知识。

I'd like to do it with python/pyglet instead of C++ though. 我想用python / pyglet而不是C ++来做。 I know pyglet can abstract much of the low level OpenGL away; 我知道pyglet可以抽取大部分低级OpenGL; 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. 我的问题非常简单:下面的代码只绘制一个点而不是我期望的3个点。 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. 据我所知,我的代码与教程中的C ++相同,除了删除顶点和片段着色器(通过python中的gletools完成),这似乎对我的问题没有任何影响。

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 将事物简化为单点显示我不理解的行为(第一个坐标似乎是唯一影响任何事物的坐标),这让我回想起我完全不理解pyglet,OpenGL,或者甚至是一般的3D: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()
glDrawArrays(GL_POINTS, 0, 1)

instructs to draw 1 point, in your tutorial, 1 is 3 : 指示画1点,在你的教程中,1是3:

glDrawArrays(GL_POINTS, 0, 3)

Notice also that the 4th (w) component of your vertices should be 1, not 0 : 另请注意,顶点的第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]

Alternatively, you could remove the w component, 或者,您可以删除w组件,

  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. 另一件事,我不是pyglet的专家,但glBufferData可能像C语言一样,采用字节大小而不是元素。 Each float being 4 bytes, you could try : 每个浮点数为4个字节,您可以尝试:

glBufferData(GL_ARRAY_BUFFER, len(vertexPositionsGl)*4, vertexPositionsGl, GL_STATIC_DRAW)

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. 似乎我被顶点,glDrawArrays和glVertexAttribPointer摆弄的事实所误导,有时会导致显示一个点。 This appears to be an accident: with the corrections provided by rotoglup's answer, nothing at all is drawn. 这似乎是一个意外:由rotoglup的答案提供的更正,根本没有绘制。 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. 将w坐标设置为0而不是1,完全没有教程中剪辑空间转换的解释。

  • giving glBufferData the size of the buffer in vertices when it expects bytes. 在期望字节时,给glBufferData提供顶点中缓冲区的大小。

  • 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. 为了记录,下面的代码显示一个三角形,通过着色器,我希望是最新的和正确的OpenGL。 Requirements are pyglet and gletools. 要求是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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM