2016-10-13 7 views
4

Я хотел бы сделать треугольник с помощью OpenGL 4.5. Я нашел множество примеров в Интернете, используя более старые версии OpenGL, но ни один из них не использует функции OpenGL 4.5. Поэтому я попытался сам «обновить» код. Это старый рабочий код:Как использовать vao и буферы в 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 

Может кто-нибудь сказать мне, что я сделал неправильно ?

Edit: 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); 
} 
+2

Вы должны иметь очень современный графический процессор для поддержки OpenGL версии 4.х, и даже в этом случае вы можете ограничить более раннюю реализацию, если драйверы еще не существуют. Что вы используете? Шейдеры - обычная проблема. –

+0

У меня есть GTX 760 и установлены последние версии драйверов. Я использую glew для загрузки расширений OpenGL, и он подтверждает, что ARB_direct_state_access доступен. – para

+0

попробуйте #version 430 вместо #version 450 .... это говорит, что GTX 760 поддерживает OpenGL 4.3 http://www.geforce.com/hardware/desktop-gpus/geforce-gtx-760/specifications –

ответ

1

Преступник, скорее всего, эта линия:

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

Последний параметр является stride, который означает расстояние между двумя последовательными элементами массива. В традиционном glVertexAttribPointer вызова, также есть параметр stride, но есть небольшая смысловая разница:

Если вы используете stride из 0 в glVertexAttribPointer, это удобный ярлык для написания count * sizeof(type), и будет считать, плотно упакованным массив атрибутов.

С glVertexArrayVertexBuffer шаг 0 просто означает 0, так что он подаст вам тот же самый элемент для каждой вершины этого призывного вызова. glVertexArrayVertexBuffer не может предоставить одну и ту же команду shourtcut, поскольку она не привязана напрямую к любому атрибуту вершины, и несколько атрибутов могут (и обычно) ссылаться на один и тот же индекс буфера. (И интерфейс также будет очень странно, потому что вы можете установить формат вершины до или после того, как вы установите переплет, так что должен быть оценены позже.)

Так концептуально шаг является не части формат атрибута. Формат просто описывает все, что необходимо для одной вершины. Обратите внимание, что это изменение не имеет никакого отношения к доступу прямого доступа. Он был фактически введен с ARB_vertex_attrib_binding (ядро с GL 4.3), которое разделило привязку буфера от описания формата атрибута. В (2) и вопросы (3) в этом документе, являются весьма уместным к этому вопросу:

(2) Каким образом шаг нуля интерпретированы в BindVertexBuffer?

RESOLVED: Ошибка генерируется, все элементы массива для заданного атрибута будут получены из того же места в буфере.

(3) Как шаг с нулевой обработкой в ​​VertexAttribPointer?

ПОСТАНОВИЛ: BindVertexBuffer не имеет информации об атрибуте, , поэтому 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));