[英]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.