簡體   English   中英

如何在OpenGL 4.5中使用vao和緩沖區

[英]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使用stride0glVertexAttribPointer這是編寫count * sizeof(type)的便捷快捷方式,並將采用緊密壓縮的屬性數組。

使用glVertexArrayVertexBuffer0的步幅意味着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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM