OpenGL вращение и перевод камеры от первого лица - PullRequest
1 голос
/ 22 января 2012

Я пытаюсь написать простую игру-лабиринт без использования устаревшего API OpenGL (т.е. без непосредственного режима). Я использую один объект Vertex Buffer для каждой плитки в моем лабиринте, который по сути является комбинацией четырех Vertex s:

class Vertex {
public:
    GLfloat x, y, z; // coords
    GLfloat tx, ty;  // texture coords

    Vertex();
};

и хранятся в VBO следующим образом:

void initVBO()
{
    Vertex vertices[4];
    vertices[0].x = -0.5;
    vertices[0].y = -0.5;
    vertices[0].z = 0.0;
    vertices[0].tx = 0.0;
    vertices[0].ty = 1.0;
    vertices[1].x = -0.5;
    vertices[1].y = 0.5;
    vertices[1].z = 0.0;
    vertices[1].tx = 0.0;
    vertices[1].ty = 0.0;
    vertices[2].x = 0.5;
    vertices[2].y = 0.5;
    vertices[2].z = 0.0;
    vertices[2].tx = 1.0;
    vertices[2].ty = 0.0;
    vertices[3].x = 0.5;
    vertices[3].y = -0.5;
    vertices[3].z = 0.0;
    vertices[3].tx = 1.0;
    vertices[3].ty = 1.0;

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*4, &vertices[0].x, GL_STATIC_DRAW);

    ushort indices[4];
    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 2;
    indices[3] = 3;

    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort) * 4, indices, GL_STATIC_DRAW);
}

Теперь я застрял в движении камеры. В предыдущей версии моего проекта я использовал glRotatef и glTranslatef для перевода и поворота сцены, а затем рендерил каждую плитку в режиме glBegin() / glEnd(). Но эти две функции теперь устарели, и я не нашел учебника по созданию камеры в контексте, использующем только VBO. Как правильно поступить? Должен ли я зацикливаться между каждой плиткой, изменяя положение вершин в соответствии с новой позицией камеры?

Ответы [ 3 ]

4 голосов
/ 22 января 2012

Но эти две функции теперь устарели, и я не нашел никакого руководства по созданию камеры в контексте, использующем только VBO.

VBO не имеют к этому никакого отношения.

Непосредственный режим и матричный стек - это две разные пары ботинок.VBO имеют дело с передачей данных геометрии в рендерер, а матричный стек - с получением преобразования там.VBO влияют только на геометрические данные.

Что касается вашего вопроса: вы сами вычисляете матрицы и передаете их в шейдер по форме.Также важно понимать, что матричная функция OpenGL никогда не была ускорена графическим процессором (за исключением одной машины, Onyx SGI), так что это даже не дало некоторого прироста производительности.На самом деле использование матричного стека OpenGL оказало негативное влияние на общую производительность из-за выполнения избыточных операций, которые также должны выполняться в другом месте программы.

Для простой математической библиотеки матриц посмотрите мой linmath.h http://github.com/datenwolf/linmath.h

2 голосов
/ 22 января 2012

Я добавлю к ответу datenwolf.Я предполагаю, что вам доступен только шейдерный конвейер.

Требования

В OpenGL 4.0+ Opengl не делает для вас никакого рендеринга, поскольку он удаляется отконвейер с фиксированной функцией.Если вы сейчас визуализируете свою геометрию без шейдера, вы используете устаревший конвейер.Начать работу без какой-либо базовой платформы будет сложно (не невозможно, но я бы порекомендовал использовать базовую среду).Для начала я бы порекомендовал использовать GLUT (это создаст окно для вас и будет иметь базовые обратные вызовы для функции ожидания и ввода), GLEW (для настройки контекста рендеринга)и gLTools (матричный стек, универсальные шейдеры и менеджер шейдеров для быстрой настройки, чтобы вы могли хотя бы начать рендеринг).

Настройка

Я дам здесь важные части, которые вы можете затем собрать вместе.На данный момент, я предполагаю, что вы правильно настроили GLUT ( ищите, как его настроить ), и вы можете зарегистрировать цикл обновления с ним и создать окно (то есть цикл, который вызываетодна из выбранных вами функций [примечание, это не может быть методом] для каждого кадра).Обратитесь к ссылке выше для помощи по этому вопросу.

  • Сначала инициализируйте glew (вызывая glewInit())
  • Настройте вашу сцену.Это включает в себя использование класса GLBatch (из glTools) для создания набора вершин для визуализации в виде треугольников и инициализацию класса GLShaderManager (также из GLTools) и его базовых шейдеров путем вызова его InitializeStockShaders() function.
  • В цикле ожидания вызовите функцию UseStockShader() диспетчера шейдеров, чтобы запустить новый пакет.Вызовите функцию draw() в вашем пакете вершин.Для полного обзора glTools, перейдите сюда .
  • Не забудьте очистить окно перед рендерингом и поменять местами буферы после рендеринга, вызвав glClear() и glSwapBuffers() соответственно.

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

MVP Matrix (РЕДАКТИРОВАТЬ: Забыли добавить этот раздел)

OpenGL отображает все, что естьв координатах -1,1, глядя вниз по оси Z.Он не имеет понятия о камере и не заботится о чем-либо, что выходит за рамки этих координат.Матрица модель-вид-проекция - это то, что превращает вашу сцену в подходят эти координаты.

В качестве отправной точки, не беспокойтесь об этом, пока на экране не будет что-то визуализировано (убедитесь, что все координаты, которые вы задаете для вашей вершинной партии, меньше 1).После этого настройте матрицу проекции (проекция по умолчанию - орфографическая), используя класс GLFrustum в glTools.Из этого класса вы получите матрицу проекции, которую вы умножите на матрицу вида модели.Матрица вида модели представляет собой комбинацию матрицы преобразования модели и преобразования камеры (помните, что камеры нет, поэтому, по сути, вы перемещаете сцену вместо этого).После того, как вы умножили их все на одну матрицу, вы передаете ее шейдеру с помощью функции UseStockShader().

Используйте стандартный шейдер в GLTools (например, GLT_SHADER_FLAT), затем начните создавать свой собственный.

Ссылка

Наконец, я настоятельно рекомендую приобрести эту книгу: OpenGL SuperBible, всеобъемлющее руководство и справочник (пятое издание - убедитесь, что это именно это издание)

1 голос
/ 22 января 2012

Если вы действительно хотите придерживаться новейшего API OpenGL, где множество функций было удалено в пользу программируемого конвейера (OpenGL 4 и OpenGL ES 2), вам придется самостоятельно написать вершинный и фрагментный шейдеры и реализоватьвещи преобразования там.Вам нужно будет вручную создать все атрибуты, которые вы используете в шейдере, в частности, координаты и координаты текстуры, которые вы используете в своем примере.Вам также понадобятся 2 одинаковые переменные, одна для матрицы вида модели и другая для матрицы проекции, если вы хотите имитировать поведение старой фиксированной функциональности OpenGL.

Вращение / перемещение, которое вы использовали, - это матрицаоперации.На этапе преобразования вершин конвейера, который теперь выполняется предоставленным вершинным шейдером, необходимо умножить матрицу преобразования 4x4 на положение вершины (4 координаты, интерпретируемые как матрица 4x1, где 4-я координата обычно равна 1, если вы этого не делаетеничего особенного).Там результирующий вектор будет в правильном относительном положении в соответствии с этим преобразованием.Затем вы умножаете матрицу проекции на этот вектор и выводите результат во фрагментный шейдер.

Вы можете узнать, как все эти матрицы построены, посмотрев документацию glRotate, glTranslate и gluPerspective.Помните, что умножение матриц некоммутативно, поэтому порядок их умножения имеет значение (именно поэтому порядок, который вы называете glRotate и glTranslate, также имеет значение).

Об изучении GLSL и о том, как использовать шейдеры,Я изучил здесь , но эти руководства относятся к OpenGL 1.4 и 2 и сейчас очень стары.Основное отличие состоит в том, что предопределенные входные переменные для вершинных шейдеров, такие как gl_Vertex и gl_ModelViewMatrix, больше не существуют, и вы должны создавать их самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...