FloatBuffer рисует текстурированный квад, но ShortBuffer не делает - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь нарисовать текстурированный квад.Поскольку это четверный, я хочу использовать glDrawElements и VEO, но для этого требуется ShortBuffer вместо FloatBuffer.Я пытался изменить свой код, но теперь ничего не рисует.Старый код: Загрузка и рисование:

 public void flush() {
    if (numVertices > 0) {
        vertices.flip();

        if (vao != null) {
            vao.bind();
        } else {
            vbo.bind(GL_ARRAY_BUFFER);
            specifyVertexAttributes();
        }
        program.use();

        /* Upload the new vertex data */
        vbo.bind(GL_ARRAY_BUFFER);
        vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);

        /* Draw batch */
        glDrawArrays(GL_TRIANGLES, 0, numVertices);

        /* Clear vertex data for next batch */
        vertices.clear();
        numVertices = 0;
    }
}

Добавление текстуры в буфер:

if (vertices.remaining() < 7 * 6) {
        /* We need more space in the buffer, so flush it */
        flush();
    }

    float r = c.getRed();
    float g = c.getGreen();
    float b = c.getBlue();
    float a = c.getAlpha();

    vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
    vertices.put(x1).put(y2).put(r).put(g).put(b).put(a).put(s1).put(t2);
    vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);

    vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
    vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);
    vertices.put(x2).put(y1).put(r).put(g).put(b).put(a).put(s2).put(t1);

    numVertices += 6;

Обновленный код: Загрузка и рисование:

public void flush() {
    if (numVertices > 0) {
        vertices.flip();

        if (vao != null) {
            vao.bind();
        } else {
            vbo.bind(GL_ARRAY_BUFFER);
            specifyVertexAttributes();
        }
        program.use();

        /* Upload the new vertex data */
        vbo.bind(GL_ARRAY_BUFFER);
        vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);

        /* Draw batch */
        glDrawArrays(GL_TRIANGLES, 0, numVertices);

        /* Clear vertex data for next batch */
        vertices.clear();
        numVertices = 0;
    }
}

Добавление текстуры в буфер:

if (vertices.remaining() < 7 * 6) {
        /* We need more space in the buffer, so flush it */
        flush();
    }

    short r = (short) c.getRed();
    short g = (short) c.getGreen();
    short b = (short) c.getBlue();
    short a = (short) c.getAlpha();

    short sx1 = (short) Math.round(x1), sx2 = (short) Math.round(x2), sy1 = (short) Math.round(y1), sy2 = (short) Math.round(y2), ss1 = (short) Math.round(s1), ss2 = (short) Math.round(s2), st1 = (short) Math.round(t1), st2 = (short) Math.round(t2);
    vertices.put(sx1).put(sy1).put(r).put(g).put(b).put(a).put(ss1).put(st1);
    vertices.put(sx1).put(sy2).put(r).put(g).put(b).put(a).put(ss1).put(st2);
    vertices.put(sx2).put(sy2).put(r).put(g).put(b).put(a).put(ss2).put(st2);

    vertices.put(sx1).put(sy1).put(r).put(g).put(b).put(a).put(ss1).put(st1);
    vertices.put(sx2).put(sy2).put(r).put(g).put(b).put(a).put(ss2).put(st2);
    vertices.put(sx2).put(sy1).put(r).put(g).put(b).put(a).put(ss2).put(st1);

    numVertices += 6;

В коде не было никаких других изменений, кроме замены FloatBuffer на ShortBuffer в моем методе uploadSubData.Класс VBO - это просто оболочка для методов OpenGL, поэтому uploadSubData - это glUploadSubData и т. Д. Что мне не хватает?Почему glDrawArrays не рисует ShortBuffer?Если я что-то пропустил, скажите, пожалуйста, у меня не было много времени, чтобы написать это.

1 Ответ

0 голосов
/ 21 февраля 2019

Вы путаете индексы и координаты вершин.Координаты - это кортежи типа GL_FLOAT в GL_ARRAY_BUFFER.Но индексы представляют собой список интегральных индексов (например, типа GL_SHORT) в GL_ELEMENT_ARRAY_BUFFER, которые относятся к координатам вершины.

Квадрат может быть нарисован двумя треугольниками.Вы можете определить 6 координат и атрибутов вершин и использовать glDrawArrays.

В следующем vertices имеет тип FloatBuffer:

vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
vertices.put(x1).put(y2).put(r).put(g).put(b).put(a).put(s1).put(t2);
vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);

vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);
vertices.put(x2).put(y1).put(r).put(g).put(b).put(a).put(s2).put(t1);

numVertices += 6;
vbo.bind(GL_ARRAY_BUFFER);
vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);

glDrawArrays(GL_TRIANGLES, 0, numVertices);

Или вы можете определить 4 координаты вершины соответственно атрибутам и 6 индексам и использовать glDrawElements.

В следующем vertices все еще имеет тип FloatBuffer, но indices являетсятипа ShortBuffer:

vertices.put(x1).put(y1).put(r).put(g).put(b).put(a).put(s1).put(t1);
vertices.put(x1).put(y2).put(r).put(g).put(b).put(a).put(s1).put(t2);
vertices.put(x2).put(y2).put(r).put(g).put(b).put(a).put(s2).put(t2);
vertices.put(x2).put(y1).put(r).put(g).put(b).put(a).put(s2).put(t1);

numVertices += 4;
indices.put(0).put(1).put(2);
indices.put(0).put(2).put(3);

numIndices += 4;
vbo.bind(GL_ARRAY_BUFFER);
vbo.uploadSubData(GL_ARRAY_BUFFER, 0, vertices);
ibo.bind(GL_ELEMENT_ARRAY_BUFFER);
ibo.uploadSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices);

glDrawElements(GL_TRIANGLES, GL_SHORT, numIndices, null);

Итак, ключ в том, что вам понадобятся 2 uploadSubData методы.Первый должен иметь дело с FloatBuffer, а второй - с ShortBuffer.
Обратите внимание, что в общем случае атрибуты вершин являются значениями с плавающей запятой.Цвета часто являются значениями с плавающей запятой в диапазоне [0, 1].Координаты текстуры находятся в диапазоне [0, 1].Конечно, это можно закодировать в интегральный тип данных, но, по крайней мере, для координат вершин это может привести к потере точности.

...