Рендеринг с использованием VBO / VAO в OpenGL4

Я пытаюсь обновить код OpenGL старого стиля до современного OpenGL4.

У меня есть огромная текстурированная и предварительно мозаичная модель куба для рендеринга.

Вместо этого теперь я получаю следующее:

Ошибка

Это поле из полупроизвольных черных треугольников на белом фоне.

Мой код сборки VAO / VBO:

        // Normal buffer
        GL.GenBuffers(1, out VBONormals);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBONormals);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Normals.Length * Vector3.SizeInBytes),
        Normals, BufferUsageHint.StaticDraw);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        // TexCoord buffer
        GL.GenBuffers(1, out VBOTexCoords);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBOTexCoords);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(TexCoords.Length * Vector3.SizeInBytes),
        TexCoords, BufferUsageHint.StaticDraw);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        // Vertex buffer
        GL.GenBuffers(1, out VBO);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Positions.Length * Vector3.SizeInBytes),
        Positions, BufferUsageHint.StaticDraw);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        // Index buffer
        GL.GenBuffers(1, out VBOIndices);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOIndices);
        GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(Indices.Length * sizeof(uint)),
        Indices, BufferUsageHint.StaticDraw);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
        GL.GenVertexArrays(1, out VAO);
        GL.BindVertexArray(VAO);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBONormals);
        GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBOTexCoords);
        GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, 0, 0);
        GL.EnableVertexAttribArray(0);
        GL.EnableVertexAttribArray(1);
        GL.EnableVertexAttribArray(2);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOIndices);
        // Clean up
        GL.BindVertexArray(0);
        GL.DisableVertexAttribArray(0);
        GL.DisableVertexAttribArray(1);
        GL.DisableVertexAttribArray(2);
        GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);

и код рендеринга:

        VBOTexture.Bind();
        GL.BindVertexArray(VAO);
        //GL.DrawRangeElements(PrimitiveType.Triangles, 0, Positions.Length, Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
        GL.DrawArrays(PrimitiveType.Triangles, 0, Indices.Length);

Вершинный шейдер:

#version 430 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 texcoord;

layout (location = 1) uniform mat4 projection;

layout (location = 0) out vec3 f_color;

void main()
{
    f_color = normal;
    gl_Position = projection * vec4(position, 1.0);
}

фрагментный шейдер:

#version 430 core

layout (binding = 0) uniform sampler2D tex;

layout (location = 0) in vec3 f_color;

out vec4 color;

void main()
{
    vec4 tcolor = texture2D(tex, gl_TexCoord[0].st);
    float dist = 0.0;
    if (gl_TexCoord[0].x < 0.5)
    {
        dist = gl_TexCoord[0].x;
    }
    else
    {
        dist = 1.0 - gl_TexCoord[0].x;
    }
    if (gl_TexCoord[0].y < 0.5)
    {
        dist *= gl_TexCoord[0].y;
    }
    else
    {
        dist *= 1.0 - gl_TexCoord[0].y;
    }
    dist *= 32;
    dist = min(1, dist);
    color = vec4(tcolor[0] * dist, tcolor[1] * dist, tcolor[2] * dist, tcolor[3]);
}

Обратите внимание, что переключение вызова отрисовки на закомментированный дает те же результаты.

Также обратите внимание: исходный код был точно таким же, за исключением фрагмента VAO и рендеринга с таким:

        GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBONormals);
        GL.NormalPointer(NormalPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.NormalArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBOTexCoords);
        GL.TexCoordPointer(2, TexCoordPointerType.Float, Vector2.SizeInBytes, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.TextureCoordArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ElementArrayBuffer, VBOIndices);
        GL.DrawElements(PrimitiveType.Quads, Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
        GL.PopClientAttrib();

(за исключением того, что я также переключил texcoords с Vector2 на Vector3 по не связанным причинам)

Где я ошибся?


person mcmonkey4eva    schedule 07.02.2015    source источник
comment
Не по теме, но обычно вы хотите избегать conditionals в шейдерах из-за снижения производительности   -  person MickyD    schedule 07.02.2015
comment
Этот код был временной проверкой концепции, он не оптимизирован ни в малейшей степени.   -  person mcmonkey4eva    schedule 07.02.2015
comment
Что ж, вызов glDrawArrays() концептуально совершенно неверен, особенно с Indices.Leght как count. glDrawRangeElements() должен работать в принципе. Когда оба вызова дают один и тот же результат, ваш индексный массив либо является тривиальным случаем первых n целых чисел (включая ноль), либо где-то с вашими данными что-то не так.   -  person derhass    schedule 07.02.2015


Ответы (1)


В вашем старом коде используется drawElements, а в новом - drawArrays.

    VBOTexture.Bind();
    GL.BindVertexArray(VAO);
    //GL.DrawRangeElements(PrimitiveType.Triangles, 0, Positions.Length, Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
    GL.DrawElements(PrimitiveType.Quads, Indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero);
person ratchet freak    schedule 07.02.2015
comment
PrimitiveType.Quads это опечатка? Похоже, что в индексном буфере хранятся треугольники, а в ядре GL нет четырехугольников. - person Colonel Thirty Two; 07.02.2015
comment
@ColonelThirtyTwo - это то, что он использовал в исходном коде - person ratchet freak; 07.02.2015
comment
... Пожалуйста, скажите мне, что я не случайно переключился с треугольников на квадраты или наоборот, потому что это очень хорошо все объясняет ... - person mcmonkey4eva; 07.02.2015
comment
Ага. Треугольники - ›квадраты - вот степень различий. Я сам удивляюсь. Спасибо, что заметили это! Теперь мне просто нужно выяснить, почему текстура черная как смоль ... возможно, мой шейдер не передает текстовые координаты или что-то в этом роде, я справлюсь с этим. Если нет, у меня есть этот замечательный сайт, где я могу попросить дополнительную помощь: D А пока вы определенно ответили на мой главный вопрос. Принятие ... (Кроме того, мне, вероятно, следует использовать здесь треугольники, почему у меня четырехугольники? Это проблема вторая для меня) - person mcmonkey4eva; 07.02.2015