【问题标题】:How to use vao and buffers in OpenGL 4.5如何在 OpenGL 4.5 中使用 vao 和缓冲区
【发布时间】:2016-10-13 20:02:46
【问题描述】:

我想使用 OpenGL 4.5 渲染一个三角形。我在网上找到了很多使用旧版本 OpenGL 的示例,但没有使用 OpenGL 4.5 函数的示例。因此,我尝试自己“升级”一些代码。这是旧的工作代码:

// Triangles to render
vec3 vertices[2][3] = { { vec3(-0.90f, -0.90f, 1.0f), vec3(0.85f, -0.90f, 1.0f), vec3(-0.90f, 0.85f, 1.0f) },
                    { vec3(0.90f, -0.85f, 1.0f),  vec3(0.90f, 0.90f, 1.0f),  vec3(-0.85f, 0.90f, 1.0f) } };

//Initialize
glGenVertexArrays(1, &vaos);
glBindVertexArray(vaos);

glGenBuffers(1, &buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangles), triangles, GL_STATIC_DRAW);

ShaderInfo shaders[] = {
    { GL_VERTEX_SHADER, "triangles.vert" },
    { GL_FRAGMENT_SHADER, "triangles.frag" },
    { GL_NONE, NULL }
};
program = LoadShaders(shaders);
glUseProgram(program);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);

//Render
GLint index;
index = glGetUniformLocation(program, "projectionMatrix");
glUniformMatrix3fv(index, 1, true, value_ptr(projectionMatrix));
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vaos);
glDrawArrays(GL_TRIANGLES, 0, nvertices);

我将它“更新”为这段代码,它似乎没有在屏幕上绘制任何东西:

// Same triangles
// Initialize
glCreateVertexArrays(1, &vaos);
glEnableVertexArrayAttrib(vaos, 0);
glVertexArrayAttribFormat(vaos, 0, 3, GL_FLOAT, GL_FALSE, 0);

glCreateBuffers(1, &buffers);
glNamedBufferData(buffers, sizeof(triangles), triangles, GL_STATIC_DRAW);

glVertexArrayAttribBinding(vaos, 0, 0);
glVertexArrayVertexBuffer(vaos, 0, buffers, 0, 0);

ShaderInfo shaders[] = {
    { GL_VERTEX_SHADER, "triangles.vert" },
    { GL_FRAGMENT_SHADER, "triangles.frag" },
    { GL_NONE, NULL }
};
program = LoadShaders(shaders);
glUseProgram(program);

// Same render

谁能告诉我我做错了什么?

编辑: 三角形片段

#version 450

in vec4 gl_FragCoord;
out vec4 fColor;

void main ()
{
    fColor = vec4 (0.0, 0.0, 1.0, 1.0);
}

三角形.vert

#version 450

layout (location = 0) in vec3 vPosition;

uniform mat3 projectionMatrix;

void main ()
{
    vec3 tmp = projectionMatrix*vPosition;
    gl_Position = vec4 (tmp, 1.0f);
}

【问题讨论】:

  • 您需要一个非常现代的图形处理器来支持 OpenGL 4.x 版本,即使如此,如果驱动程序尚不存在,您可能会受限于较早的实现。你在什么上面运行它?着色器是一个常见的问题。
  • 我有一台 GTX 760 并安装了最新的驱动程序。我正在使用 glew 加载 OpenGL 扩展,它确认 ARB_direct_state_access 可用。
  • 尝试 #version 430 而不是 #version 450 .... 这表示 GTX 760 支持 OpenGL 4.3 geforce.com/hardware/desktop-gpus/geforce-gtx-760/…
  • @ScottStensland:这些只是 GPU 首次发布时的最新 GL 版本。 NVidia 支持 OpenGL 4.5 的所有卡回到 Fermi / Geforce 400。

标签: c++ opengl opengl-4


【解决方案1】:

罪魁祸首很可能是这一行:

glVertexArrayVertexBuffer(vaos, 0, buffers, 0, 0);

最后一个参数是stride,表示两个连续数组元素之间的距离。在传统的glVertexAttribPointer调用中,也有stride参数,但语义上略有不同:

如果您在glVertexAttribPointer 中使用0 中的stride,这是编写count * sizeof(type) 的便捷快捷方式,并且将假定一个紧凑的属性数组。

对于glVertexArrayVertexBuffer0 的步幅仅表示0,因此它将为该绘图调用的每个顶点提供完全相同的元素。 glVertexArrayVertexBuffer 不能提供相同的快捷方式,因为它不直接绑定到任何顶点属性,并且多个属性可以(并且通常会)引用相同的缓冲区索引。 (而且界面也会很奇怪,因为你可以在设置绑定之前或之后设置顶点格式,所以需要稍后进行评估。)

所以从概念上讲,步幅不是属性格式的一部分。该格式仅描述了 single 顶点所需的所有内容。请注意,此更改与直接状态访问无关。它实际上是由ARB_vertex_attrib_binding(自 GL 4.3 以来的核心)引入的,它确实将缓冲区绑定与属性格式描述分开。该文件中的问题(2)和(3)与这个问题非常相关:

(2) 在BindVertexBuffer 中如何解释零步幅?

已解决:未生成错误,给定的所有数组元素 属性将来自缓冲区中的同一位置。

(3) 在VertexAttribPointer 中如何处理零步幅?

已解决:BindVertexBuffer 不知道属性格式, 所以VertexAttribPointer 需要自己计算步幅。然而, 如果应用程序指定步幅为零,然后查询 VERTEX_ATTRIB_ARRAY_STRIDE,它返回零。所以派生的步幅 传递给BindVertexBuffer 的信息必须与 stride 最初传递给VertexAttribPointer,所以这个规范介绍了 一个单独的状态 (VERTEX_BINDING_STRIDE)。 渲染总是使用 VERTEX_BINDING_STRIDE.

如果 API 是 被滥用。例如:

    VertexAttribPointer(0, 3, FLOAT, FALSE, 12, 0);
    // VERTEX_ATTRIB_ARRAY_STRIDE = 12
    // VERTEX_BINDING_STRIDE = 12
    BindVertexBuffer(0, buffer, 0, 16)
    // now VERTEX_ATTRIB_ARRAY_STRIDE is still 12, but
    // VERTEX_BINDING_STRIDE = 16.

长话短说:对于您的用例,您需要

glVertexArrayVertexBuffer(vaos, 0, buffers, 0, 3*sizeof(GLfloat));

【讨论】:

    猜你喜欢
    • 2012-12-24
    • 1970-01-01
    • 2020-10-11
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多