Как работают несколько буферов для атрибутов в шейдерах openGL (ES) и API C ++ - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть пример пресловутого куба, и я пишу код, чтобы протестировать его и узнать больше о шейдерах.Мой вопрос о том, как нескольким буферам назначается доступ в шейдере и как написать код шейдера для ссылки на них.Образцы, похоже, основаны на неявных ссылочных значениях по умолчанию, которые скрывают то, что действительно происходит, и то, как кто-то манипулирует им в примерах.

Моя настройка буфера выглядит следующим образом (данные опущены)

        glGenBuffers(1, &vertexPosObject);
        glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
            sizeof(Vec3f), (void*)0);

        /* load index buffer with array of indices */
        glGenBuffers(1, &indexBufferObject);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        /* load color buffer with array of colors */
        glGenBuffers(1, &colorBufferObject);
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertColors), vertColors, GL_STATIC_DRAW);

        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,
            sizeof(Vec4f), 0);

С этим я получаю рисунок куба и могу вращать его.с.

        Matrix4d modelView;
        double rot = rc.timing().frameTime()*.3;
        rot = fmod(rot, ARTD_M_PI * 2);
        modelView.setRotation(Vec3d(0, 1, 1), rot);
        artdGlUniformMatrix4(modelViewId, modelView); // convenience call

тогда я могу нарисовать его ниже

        glUseProgram(cubeShader);

        glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

        const int vertexCount = 36;
        const int type = GL_UNSIGNED_INT; // unsigned short ??
        const int firstIndex = 0;

        // vertexCount is the number of verts in your vertex array object
        // firstIndex is the first index to use in an array of offsets (element index) into the vertex data.

        glDrawElements(GL_TRIANGLES, vertexCount, type, (void *)firstIndex);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

Я предполагал, что массиву вершин назначен "слот" с

        glEnableVertexAttribArray(0);

Иэтот слот "0" является косвенно тем, что шейдер использует в качестве входных вершин.(???)

Итак, я решил попробовать присвоить массив цветов слоту "1", дескриптор массива индекса передается непосредственно в glDrawElements () и извлекает вершины для ввода в шейдер, используяиндексный массив, обращающийся к буферу, назначенному слоту "0"

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

Мой вопрос: как получить доступ к буферу цветовых массивов в шейдере, а также получить доступ к другим буферам в качестве индексируемых массивов в вершинном шейдере ???

Как связать буферы с различными идентификаторами, доступными для шейдеров, и как получить к ним доступ из этих идентификаторов в коде шейдера.Понимание этих отношений является ключевым.

В настоящее время эта пара шейдеров работает для рисования куба с вычисленными цветами.

    "uniform mat4 Projection;\n"
    "uniform mat4 Model;\n"

    "attribute vec4 vPosition;\n"
    "varying vec3 color;\n"
    "void main(){\n"
        "mat4 MVP = Model * Projection;\n"
        "gl_Position = vPosition * MVP;\n"
        "color = gl_Position.xyz + vec3(0.5);\n"
    "}\n"

Фрагментный шейдер

   "precision mediump float;\n"
    "varying vec3 color;\n"
    "void main()\n"
    "{\n"
        "gl_FragColor = vec4 ( color, 1.0 );\n"
    "}\n"

Pardon C ++ strings :)

Спасибо !!

1 Ответ

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

Если вы хотите использовать атрибут цвета, вам нужно добавить новый атрибут в шейдер:

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

attribute vec4 vPosition;
attribute vec4 vColor;

varying vec4 color;

uniform mat4 Projection;
uniform mat4 Model;

void main()
{
    mat4 MVP    = Model * Projection;
    gl_Position = vPosition * MVP;
    color       = vColor;
}

После шейдераПрограмма связана с glLinkProgram, атрибут ind3ex можно получить с помощью glGetAttribLocation:

GLuint cubeShader = ....;

glLinkProgram(cubeShader);

GLint pos_attr_i   = glGetAttribLocation(cubeShader, "vPosition");
GLint color_attr_i = glGetAttribLocation(cubeShader, "vColor");

Это индексы атрибутов, которые необходимо использоватьв glVertexAttribPointer соответственно glEnableVertexAttribArray:

glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
glVertexAttribPointer(pos_attr_i, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3f), (void*)0);

glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
glVertexAttribPointer(color_attr_i, 4, GL_FLOAT, GL_FALSE, sizeof(Vec4f), 0);

glEnableVertexAttribArray(pos_attr_i);
glEnableVertexAttribArray(color_attr_i);
...