[英]How to use vao and buffers in OpenGL 4.5
我想用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
有人能告诉我我做错了什么吗?
编辑:triangle.frag
#version 450
in vec4 gl_FragCoord;
out vec4 fColor;
void main ()
{
fColor = vec4 (0.0, 0.0, 1.0, 1.0);
}
triangle.vert
#version 450
layout (location = 0) in vec3 vPosition;
uniform mat3 projectionMatrix;
void main ()
{
vec3 tmp = projectionMatrix*vPosition;
gl_Position = vec4 (tmp, 1.0f);
}
罪魁祸首很可能就是这条线:
glVertexArrayVertexBuffer(vaos, 0, buffers, 0, 0);
最后一个参数是stride
,表示两个连续数组元素之间的距离。 在传统的glVertexAttribPointer
调用中,还有一个stride
参数,但是存在轻微的语义差异:
如果在glVertexAttribPointer
使用stride
为0
, glVertexAttribPointer
这是编写count * sizeof(type)
的便捷快捷方式,并将采用紧密压缩的属性数组。
使用glVertexArrayVertexBuffer
, 0
的步幅意味着0
,因此它将为该绘制调用的每个顶点提供相同的元素。 glVertexArrayVertexBuffer
不能提供相同的shourtcut,因为它不直接绑定到任何顶点属性,并且几个属性可以(通常也是)引用相同的缓冲区索引。 (并且界面也会非常奇怪,因为您可以在设置绑定之前或之后设置顶点格式,因此必须稍后进行评估。)
因此,从概念上讲,步幅不是属于attribue格式的一部分。 格式只描述了单个顶点所需的全部内容。 请注意,此更改与直接状态访问无关。 它实际上是通过ARB_vertex_attrib_binding
(自GL 4.3以来的核心)引入的,它确实将缓冲区绑定与属性格式描述分开。 该文件中的问题(2)和(3)与这个问题非常相关:
(2)在
BindVertexBuffer
如何解释零步?已解决:未生成错误,给定属性的所有数组元素都将来自缓冲区中的相同位置。
(3)
VertexAttribPointer
如何处理零步?已解决:
BindVertexBuffer
不了解attrib格式,因此VertexAttribPointer
需要计算步幅本身。 但是,如果应用程序指定步幅为零,然后查询VERTEX_ATTRIB_ARRAY_STRIDE
,则返回零。 因此,传递给BindVertexBuffer
的派生步幅必须与最初传递给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));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.