Понимание основ OpenGL

Приветствую вас, любители OpenGL!

  • Прежде всего, я использую LWJGL 2, поэтому ниже приведен код Java.
  • Второй. Я хочу сказать, что я гуглил каждый вопрос, который я будет спрашивать в этом посте. Основная проблема в том, что ответы различаются друг от друга, поэтому я не могу построить конкретное понимание вещей это происходит в моем коде ниже.
  • В третьих. Я только начал изучать OpenGL и совсем не разбираюсь в Java. Так что, если у вас есть какие-либо предложения, помимо объяснения моего вопроса, не стесняйтесь критиковать / советовать. Помимо OpenGL с C++ :)

А теперь приступим.

public class Loader {
public void createVAO(int[] indices) {
    int vaoID = glGenVertexArrays();

    glBindVertexArray(vaoID);
    createIndicesVBO(indices);
    glEnableVertexAttribArray(0);
}

public void createVBO(float[] vertices) {
    int vboID = glGenBuffers(); 
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    FloatBuffer buffer = makeByteBufferFromArrayOfFloats(vertices);
    glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
}

public void createIndicesVBO(int[] indices) {
    int vboID = glGenBuffers();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
    IntBuffer buffer = makeByteBufferFromArrayOfInts(indices);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
}

public void pleaseDraw(float[] vertices, int[] indices) {
    glClearColor(0, 0, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);

}
public void cleanUp() {
    glDeleteBuffers(0);
    glDeleteVertexArrays(0);
}
public FloatBuffer makeByteBufferFromArrayOfFloats(float[] vertices) {

    FloatBuffer FloatByteBuffer = BufferUtils.createFloatBuffer(vertices.length);
    FloatByteBuffer.put(vertices);
    FloatByteBuffer.flip();
    return FloatByteBuffer;
}

public IntBuffer makeByteBufferFromArrayOfInts(int[] array) {

    IntBuffer IntByteBuffer = BufferUtils.createIntBuffer(array.length);
    IntByteBuffer.put(array);
    IntByteBuffer.flip();
    return IntByteBuffer;
}
}

Примечание - этот код работает и выводит синее окно с черным квадратом посередине. Вопросов:

  1. glBindBuffer(GL_ARRAY_BUFFER, vboID); Я не совсем понимаю, что вообще означает GL_Array Buffer. Насколько я могу понять, это просто показывает текущее состояние OpenGL, что этот VBO в какой-то момент будет хранить данные массива. Но из приведенной ниже функции я могу догадаться, что это не просто тип данных, а что-то вроде контейнер для данных, и это только то, что может быть активный для текущего состояния. Я правильно понимаю? Или я что-то упускаю?
  2. glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW); Опять это GL_Array_Thing. И кажется, эта функция помещает данные в графический процессор или помещает текущий VBO в VAO? Я не уверен.
  3. glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0); Итак, VAO состоит из атрибутов, и здесь мы показываем OpenGL, как читать наш атрибут 0. Поправьте меня если я ошибаюсь.
  4. Если я узнаю, как attribs в VAO работает правильно, я предполагаю, что могу изменить эти строки glEnableVertexAttribArray(0); и glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0); на glEnableVertexAttribArray(1); и glVertexAttribPointer(1, 3, GL_FLOAT, false, 0,0);. В финальном рендере ничего не должно измениться, но на самом деле черный квадратик не появляется. Не могу понять почему.
  5. Я использую индексы, чтобы нарисовать четырехугольник. Но как вообще OpenGL понимает, как читать данные, которые я предоставляю, потому что я не указывал, как их использовать. Я только предполагаю, что эта строчка поможет мне в этом glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);

Есть много дополнительных вопросов, но они либо появляются из-за моего непонимания вопросов, которые я описал выше. Пожалуйста, помогите мне разобраться в этой неразберихе в моей голове об основах OpenGL. Для тех, кто смог прочитать или хотя бы ответить на этот пост - Большое спасибо!

Этот сайт лучше всего подходит для короткие и конкретные вопросы, по одному вопросу на сообщение. Это не форум. Предлагаю разбить это на несколько постов. Кроме того, пробовали ли вы его поискать (в вики OpenGL и / или на страницах руководства)? Если вы предоставите подробную информацию о том, что вы обнаружили и как это не ответит на ваш вопрос, люди могут с большей готовностью помочь вам.

HolyBlackCat 24.08.2018 18:32

Эти вопросы нацелены на некоторые фундаментальные принципы OpenGL. Они слишком широки, чтобы на них можно было ответить в сообщении stackoverflow. По этим темам уже существует обширная документация и руководства. См., Например, вики OpenGL на буферные объекты и Спецификация вершин. Есть также обширные учебники, такие как open.gl или Изучение программирования современной 3D-графики.

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

Ответы 1

Ответ принят как подходящий
glBindBuffer(GL_ARRAY_BUFFER, vboID);

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

glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW); //Notice I added "size" for C++. LWJGL doesn't need it.

Средство: заполнить связанный в данный момент array_buffer (с помощью "glBindBuffer") байтами size; взять их с buffer (адрес в RAM CPU). Мое намерение (GL_STATIC_DRAW) состоит в том, чтобы графический процессор многократно считывал данные, а не модифицировал их.

glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0,0); // "stride" added

Графический процессор читает из одного или нескольких VBO. Например, VBO может состоять из координат x, y, z (3 числа с плавающей запятой), за которыми следуют компоненты цвета R, G, B, A (4 байта) и повторять последовательность для других вершин.
glVertexAttribPointer устанавливает связь между VBO и необходимыми атрибутами. В примере: первый атрибут (0) требует значений 3 типа GL_FLOAT, которые не (false) нормализованы (не в диапазоне [0,0, 1,0]). Следующая последовательность для этого атрибута - это stride байта (использование 0 означает, что атрибуты плотно упакованы). Последний 0.0 - это смещение в VBO для первого атрибута.

Цвет может быть прочитан как другой атрибут из того же VBO или нет. «Имя» для этого атрибута может быть 1, потому что 0 уже используется для координат. Поэтому ему нужен собственный вызов glVertexAttribPointer.

Идентификаторы атрибутов были выбраны графическим процессором. Поскольку OpenGL> = 3.3 (который я настоятельно рекомендую использовать), вам лучше выбирать их (по "location = 0" в шейдерах)

VAO содержит привязки буферов и привязки атрибутов. Каждый раз, когда вам нужно рендерить данные из некоторых VBO, вам не нужно снова использовать требуемые glBindBuffer и glVertexAttribPointer. Просто используйте вместо него glBindVertexArray.

«Индексирующий рендеринг» означает, что вы используете два VBO: один для координат, а другой для индексов. (Другие VBO также могут использоваться для других атрибутов). VBO с индексами сообщает графическому процессору порядок «последовательностей» от первого VBO (и других VBO). Это позволяет читать одну и ту же вершину несколько раз, не повторяя ее атрибуты. Обратите внимание, что триангуляция имеет одну и ту же вершину среди нескольких треугольников. Вы можете избежать отправки в GPU повторяющихся данных.

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