首页 > 解决方案 > 使用 pyglet 的 glVertexAttribPointer 数据类型的意外行为

问题描述

我一直致力于实现基于四叉树的 LOD 系统。我正在使用 Pyglet 作为 OpenGL 的 python 绑定,我得到了一些奇怪的行为,我想知道我是否做错了什么。

设置我的缓冲区:(输入数据是要在顶点着色器中解码的四叉树的叶子)

num_points = 4
buffer = GLuint()
glGenBuffers(1, pointer(buffer))
glBindBuffer(GL_ARRAY_BUFFER, buffer)
data = (GLuint * num_points)(*[0b111001000100, 0b111001010100, 0b111001100100, 0b111001110100])
glBufferData(GL_ARRAY_BUFFER, sizeof(data), pointer(data), GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 1, GL_UNSIGNED_INT, GL_FALSE, 0, 0)

绘制调用:

@window.event
def on_draw():
    glClear(GL_COLOR_BUFFER_BIT)

    glUseProgram(test_shader)
    glUniformMatrix4fv(glGetUniformLocation(test_shader, b'view_mat'), 1, GL_FALSE, camera.view_matrix())
    glUniformMatrix4fv(glGetUniformLocation(test_shader, b'projection_mat'), 1, GL_FALSE, camera.proj_matrix())

    glBindBuffer(GL_ARRAY_BUFFER, buffer)
    glDrawArrays(GL_POINTS, 0, num_points)
    glBindBuffer(GL_ARRAY_BUFFER, 0)

test_shader 的来源:

test_v = b'''
#version 430
layout (location = 0) in uint key;
uniform mat4 view_mat, projection_mat;

uint lt_undilate_2(in uint k) 
{
    k = (k | (k >> 1u)) & 0x33333333;
    k = (k | (k >> 2u)) & 0x0F0F0F0F;
    k = (k | (k >> 4u)) & 0x00FF00FF;
    k = (k | (k >> 8u)) & 0x0000FFFF;
    return (k & 0x0000FFFF);
}

void lt_decode(in uint key, out uint level, out uvec2 p)
{
    level = key & 0xF;
    p.x = lt_undilate_2((key >> 4u) & 0x05555555);
    p.y = lt_undilate_2((key >> 5u) & 0x05555555);
}

void lt_cell(in uint key, out vec2 p, out float size)
{
    uvec2 pos;
    uint level;
    
    lt_decode(key, level, pos);
    size = 1.0 / float(1u << level);
    p = pos * size;
}


void main()
{
    vec2 pos;
    float scale;
    lt_cell(key, pos, scale);
    gl_Position = projection_mat * view_mat * vec4(pos*100,0, 1);
}
'''

这对我没有任何帮助。经过一些调试后,我发现如果我改变

glVertexAttribPointer(0, 1, GL_UNSIGNED_INT, GL_FALSE, 0, 0)

到:

glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, 0)

然后我得到了我预期的渲染......尽管我的数据是一个 uint,而不是一个浮点数。我对opengl相当陌生,我在这里犯了一些错误吗?

以 GL_FLOAT 作为 dtype 输出

标签: pythonopenglglslshaderpyglet

解决方案


如果属性的类型是整数(例如uint),您必须使用glVertexAttribIPointer而不是glVertexAttribPointer. 关注I并查看glVertexAttribPointer

glVertexAttribPointer(0, 1, GL_UNSIGNED_INT, GL_FALSE, 0, 0)

glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, 0, 0)

type参数glVertexAttribPointer仅指定源数据的类型。但是,假设属性的类型是浮点数,并且数据被转换为浮点值。


推荐阅读