GLES20 Почему данные текстур не связаны с индексами вершин?

Я пытался отрендерить куб и применить единую текстуру ко всем граням. а также использовать как можно меньше вершин, передавая индексы вершин грани. пример:

Вершины:

static final float FACE_VERTEX[] = {
        // front
        0.0f,  1.0f, 1.0f,     //0
        0.0f, 0.0f, 1.0f,     //1
        1.0f, 0.0f, 1.0f,      //2
        1.0f,  1.0f, 1.0f,      //3

        //back
        1.0f,  1.0f, 0.0f,      //4 - 3
        1.0f, 0.0f, 0.0f,      //5 - 2
        0.0f, 0.0f, 0.0f,     //6 - 1
        0.0f,  1.0f, 0.0f,     //7 - 0
}; 

Индексы:

static final int FACE_INDEX[] = {
        //front
        0,1,2, 0,2,3,
        //back
        4,5,6, 4,6,7,

        //left
        7,6,1, 7,1,0,

        //right
        3,2,5, 3,5,4,

        //top
        4,7,0, 4,0,3,

        //bottom
        1,6,5, 1,5,2

};

данные наложения текстуры:

final int textureCoordinateData[] =
        {
                // Front face
                0,0, 0,1, 1,1, 1,0,
                //back
                0,0, 0,1, 1,1, 1,0,
                //left
                0,0, 0,1, 1,1, 1,0,
                //right
                0,0, 0,1, 1,1, 1,0,
                //top
                0,0, 0,1, 1,1, 1,0,
                //bottom
                0,0, 0,1, 1,1, 1,0,
                //top
                0,0, 0,1, 1,1, 1,0,
                //bottom
                0,0, 0,1, 1,1, 1,0,


        };

Текстура рендерится со всех сторон куба, кроме верхней и нижней. рендерится только первый ряд пикселей лицевой грани по всей верхней и нижней граням (см. скриншот):

введите здесь описание изображения

Я использую VBO для хранения данных вершин/индексов/текстур в графическом процессоре и рендеринга с помощью

glDrawElements(GL_TRIANGLES, indexLength, GL_UNSIGNED_INT, 0);

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

Мои вопросы будут такими: - Есть ли способ сохранить данные вершин как можно меньше и сопоставить текстуру с данными индекса? - Если я создам 36 вершин (некоторые из них повторяются) для решения проблемы отображения текстур, но я создам правильные индексы для рендеринга куба, будет ли это все равно быстрее, чем использование glDrawArrays? или мне все равно пойти с glDrawArrays и уничтожить данные индексации?

связанный вопрос (который не ответил на мой вопрос):

OpenGL ES - все карты текстур грани восьмивершинного куба?

Если вы прочитали первый комментарий к ответу:

Что вы имеете в виду, вы должны использовать 24 вершины? Если вам нужно дублировать вершины, какой смысл использовать индексный буфер, если вы все еще отправляете повторяющиеся данные на графический процессор?


person Rami Dabain    schedule 20.07.2016    source источник


Ответы (1)


На самом деле нет разумного способа нарисовать куб с текстурными координатами с менее чем 24 вершинами. Это потому, что... у него 24 вершины, если использовать определение того, что формирует вершину в OpenGL, то есть каждая уникальная комбинация атрибутов вершины (положение, координаты текстуры, нормаль и т. д.).

Возможно, вы сможете немного уменьшить число, используя только позиции и координаты текстуры, поскольку координаты текстуры в вашем случае представляют собой только комбинации значений 0 и 1. Если вас не волнует ориентация текстуры на каждой грани, вы можете, например, иметь 1 вершину, которая использует (0, 0) для координат текстуры всех трех смежных граней. Конечно, вы не можете сделать это для всех вершин, но вы можете несколько сократить количество вершин.

Так стоит ли использовать индексы? Как вы уже поняли, вы можете легко придерживаться 24 вершин при использовании индексов, но вам нужно 36 вершин с самым простым использованием glDrawArrays(), где вы используете один вызов отрисовки с GL_TRIANGLES в качестве типа примитива. Таким образом, это уменьшает количество вершин.

Вы также можете уменьшить его до 24 вершин с помощью glDrawArrays(), если сделаете отдельный вызов отрисовки для каждой грани и отрисуете грань, используя примитивный тип GL_TRIANGLE_STRIP с 4 вершинами в каждой. Однако это приведет к 6 вызовам отрисовки, а наличие большого количества мелких вызовов отрисовки также нежелательно.

Даже если это может показаться сомнительным в случае с кубом, индексные буферы в целом очень полезны. Куб — это такая маленькая и простая форма, что способ отправки вершин в любом случае не будет иметь большого значения.

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

_____________
|  /|  /|  /|
| / | / | / |
|/__|/__|/__|
|  /|  /|  /|
| / | / | / |
|/__|/__|/__|

вы можете видеть, что внутренние вершины являются общими для 6 треугольников каждая. Таким образом, для относительно большой гладкой поверхности вы обычно можете уменьшить количество вершин примерно в 6 раз, разделяя вершины, что позволяет делать использование массива индексов. Сокращение использования памяти почти в 6 раз может быть существенным преимуществом, если ваша геометрия достаточно велика.

person Reto Koradi    schedule 21.07.2016