Визуализация OpenGL: все вершины перемещаются в границы единичной сферы - PullRequest
0 голосов
/ 31 декабря 2018

Я программирую рендерер для своего игрушечного игрового движка, используя OpenTK в C #.Поскольку он будет использоваться только мной, я использую OpenGL 4.5.После того, как я реализовал основы, я попытался визуализировать чайник в Юте.Вот что у меня получилось: Attempt to render the Utah Teapot

Когда я рендерил простой куб, он рендерился нормально.Как только я добавляю больше вершин, все начинает напоминать сферу.Я использую формат файла .obj.Мой загрузчик не вызывает проблемы, я записал все позиции вершин в консоль и вручную создал еще один файл .obj с этими позициями, импортировал их в Blender, и они показали себя нормально.Мой вершинный шейдер просто передает все данные, а фрагментный шейдер просто назначает белый цвет.Я просмотрел весь интернет, но ни у кого не было этой проблемы.Я просто загружаю файл .obj, создаю массивы вершин и индексов, создаю VAO, VBO с вершинами, EBO с индексами.GL.GetError() не дает мне ничего.Я думаю, что проблема заключается в загрузке данных модели в VBO, но я просто не могу найти, в чем проблема.Это мой код для загрузки данных меша:

private bool _initialized = false;
public readonly int _id, _vertexCount, _indexCount;
private readonly int _vboID, _iboID;
public Mesh(Vertex[] vertices, int[] indices)
{
    _vertexCount = vertices.Length;
    _indexCount = indices.Length;
    GL.CreateVertexArrays(1, out _id);

    GL.CreateBuffers(1, out _vboID);   
    GL.NamedBufferStorage(
        _vboID,
        Vertex.Size * _vertexCount,   // Vertex is a struct with Vector3 position, Vector2 texCoord, Vector3 normal
        vertices,
        BufferStorageFlags.MapReadBit);

    GL.EnableVertexArrayAttrib(_id, 0); // _id is the VAO id provided by GL.CreateVertexArrays()
    GL.VertexArrayAttribFormat( 
        _id,
        0,                      
        3,                      // Vector3 - position
        VertexAttribType.Float, 
        false,                  
        0);                     // first item, offset 0
    GL.VertexArrayAttribBinding(_id, 0, 0);

    GL.EnableVertexArrayAttrib(_id, 1);
    GL.VertexArrayAttribFormat(
        _id,
        1,
        2,                      // Vector2 - texCoord
        VertexAttribType.Float,
        false,
        12);                    // sizeof(float) * (3) = (Size of Vector3)
    GL.VertexArrayAttribBinding(_id, 1, 0);

    GL.EnableVertexArrayAttrib(_id, 2);
    GL.VertexArrayAttribFormat(
        _id,
        0,
        3,                      // Vector3 - normal
        VertexAttribType.Float,
        false,
        20);                    // sizeof(float) * (3 + 2) = (Size of Vector3 + Vector2)
    GL.VertexArrayAttribBinding(_id, 2, 0);

    GL.VertexArrayVertexBuffer(_id, 0, _vboID, IntPtr.Zero, Vertex.Size);

    GL.CreateBuffers(1, out _iboID);
    GL.NamedBufferStorage(
        _iboID,
        sizeof(int) * _indexCount,
        indices,
        BufferStorageFlags.MapReadBit);
    GL.VertexArrayElementBuffer(_id, _iboID);
    _initialized = true;
}

1 Ответ

0 голосов
/ 31 декабря 2018

Проблема заключается в настройке массива нормальных векторных атрибутов.2-й параметр GL.VertexArrayAttribFormat является индексом атрибута и должен быть 2 вместо 0, в вашем случае:

GL.EnableVertexArrayAttrib(_id, 2);
GL.VertexArrayAttribFormat(
    _id,
    2,  // <----------------------- 2 instead of 0
    3,                     
    VertexAttribType.Float,
    false,
    20);                    
GL.VertexArrayAttribBinding(_id, 2, 0);

Индекс атрибута 0 приводит к тому, что спецификация координат вершины перезаписывается нормальювекторы.Нормальные векторы: Единичные векторы (длина == 1), если они рассматриваются как координаты вершины, они образуют сферическую форму.

...