Как исправить OpenGLES glDrawElements

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

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

Я проверил, что файл (кажется) правильно загружен отладчиком как: В классе ModelObject 'vCoords' содержится:

{
 1.0,  1.0,  1.0, 
-1.0, -1.0,  1.0, 
 1.0, -1.0,  1.0, 
-1.0,  1.0,  1.0, 
-1.0, -1.0, -1.0, 
 1.0, -1.0, -1.0, 
 1.0,  1.0, -1.0, 
-1.0,  1.0, -1.0
}

и каждая MaterialGroup имеет 6 индексов, которые смещены на -1 из файла obj. (индексы .obj начинаются с 1 вместо 0)

Индексы каждой MaterialGroup находятся в отдельной строке (также извлекаются из отладчика во время вызовов отрисовки).

{ 3, 6, 7, 3, 0, 6 }  //yellow
{ 0, 5, 6, 0, 2, 5 }  //blue
{ 5, 7, 6, 5, 4, 7 }  //purple
{ 2, 4, 5, 2, 1, 4 }  //red
{ 1, 7, 4, 1, 3, 7 }  //white
{ 0, 1, 2, 0, 3, 1 }  //light green

В классе ModelObject:

public void draw(float[] mvpm, GLProgram program){
        int mvpmH  = program.getUniformLocation("mvpm");

        GLES20.glEnableVertexAttribArray(posH);
        GLES20.glVertexAttribPointer(
                posH,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                    false,
                COORDS_PER_VERTEX*Float.BYTES,
                vCoords);
        GLES20.glUniformMatrix4fv(mvpmH, 1, false, mvpm,0 );
        GLErrorLogger.check();
        for(MaterialGroup materialGroup : groups){

            materialGroup.draw(program);
        }

        GLES20.glDisableVertexAttribArray(posH);
        GLErrorLogger.check();
}

В классе MaterialGroup:

public void draw(GLProgram program){
        GLErrorLogger.check();
        int colorH = program.getUniformAttribLocation("vColor");
        GLErrorLogger.check();
        GLES20.glUniform4fv(colorH, 1, material.diffuse, 0);
        GLErrorLogger.check();

        //GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, points);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, iv.limit(), 
                 GLES20.GL_UNSIGNED_SHORT, iv);

        GLErrorLogger.check();
}

iv - индексный буфер vCoords — это буфер, содержащий все вершины

Полный исходник можно найти по адресу: https://github.com/TheIncgi/GLES_GAME_fixed/blob/master/app/src/main/java/com/theincgi/gles_game_fixed/geometry/ModelLoader2.java

Текущий результат: Текущая проблема рендеринга

Цель: Как должен выглядеть куб

Редактировать 1: исправлена ​​проблема с форматированием

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
234
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Третий параметр glDrawElements указывает тип значений в списке индексов.

Буфер (iv) — это буфер int, в котором каждый элемент имеет 4 байта.

IntBuffer   iv, it, in;

Но константа перечислителя OpenGL GL_UNSIGNED_SHORT указывала, что буфер — это буфер short значений, где размер каждого значения равен 2 байтам:

GLES20.glDrawElements(GLES20.GL_TRIANGLES, iv.limit(), GLES20.GL_UNSIGNED_SHORT, iv);

Если версия OpenGL ES поддерживает GL_UNSIGNED_INT, то для решения проблемы достаточно заменить GL_UNSIGNED_SHORT на GL_UNSIGNED_INT:

GLES20.glDrawElements(GLES20.GL_TRIANGLES, iv.limit(), GLES20.GL_UNSIGNED_INT, iv);

Если GL_UNSIGNED_INT не поддерживается, то вместо ShortBuffer необходимо создать IntBuffer:

ShortBuffer iv;

GLES20.glDrawElements(GLES20.GL_TRIANGLES, iv.limit(), GLS20.GL_UNSIGNED_SHORT, iv);

Это сработало отлично. Было ощущение, что это было что-то простое, что я упустил из виду. Благодаря тонну!

TheINCGI 02.04.2019 19:07

Однако спецификация говорит, что в ES 2.0 он принимает только GL_UNSIGNED_BYTE и GL_UNSIGNED_SHORT. Тем не менее, я протестировал его на некоторых устройствах, которые работают с GL_UNSIGNED_INT, но вам, вероятно, не следует слишком полагаться на это.

Reaper 02.04.2019 23:46

@Reaper Спасибо. Я был небрежен и не рассматривал версию OpenGL ES.

Rabbid76 02.04.2019 23:54

Другие вопросы по теме