Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Наша первая программа: Подробное обсуждение





Ввод main()

Начнем с самого начала: как исполняется наша программа. Для начала взглянем, что происходит в main(). Открывающие шесть строчек используют библиотеку OpenGL Utility Toolkit для создания и открытия окна нашей программы. Так как детали каждой процедуры описаны в Appendix A, давайте взглянем на порядок выполнения команд.

int

main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGBA);

glutInitWindowSize(512, 512);

glutInitContextVersion(4, 3);

glutInitContextProfile(GLUT_CORE_PROFILE);

glutCreateWindow(argv[0]);

if (glewInit()) {

cerr << "Unable to initialize GLEW ... exiting" << endl;

exit(EXIT_FAILURE);

}

init();

glutDisplayFunc(display);

glutMainLoop();

}

 

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

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

glutInitWindowSize() задает размер окна, как вы могли догадаться. И хотя в этом примере мы не применяем эту функцию, вы можете задать изменение окна программы в соответствии с параметрами вашего дисплея.

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

Последняя группа запросов - glutCreateWindow(), функция которой ясна из названия. Если возможно создать окно с параметрами отображения, заданными вами в glutInitDisplayMode, оно и будет создано (в сопряжении с оконной системой вашего компьютера). Только после того, как GLUT создал для вас окно (сюда входит создание контекста OpenGL), вы можете начать использовать функции OpenGL.

Далее по списку, запрос glewInit() инициализирует еще одну используемую нами библиотеку - OpenGL Extesion Wrangler. GLEW облегчает работу с функциями доступа и другими интересными феноменами компьютерного программирования, представленными в разных вариациях операционных систем в OpenGL. Без GLEW пришлось бы проделать огромное количество дополнительной работы, чтобы запустить приложение.

С этого момента мы готовы наконец приступить к действительно интересной работе с OpenGL.

Процедура init(), которую мы обсудим уже сейчас, инициализирует всё необходимую нам информацию OpenGL для того, чтобы мы могли приступить к рендерингу.



Слудющая процедура, glutDisplayFunc() задает отклик дисплея. Это процедура, запрашиваемая GLUT, когда программа считает, что содержание экрана пора обновить. Мы указываем GLUT здесь куда нужно направиться: display(), об этом тоже чуть позднее. GLUT использует несколько функций отклика для обработки, к примеру, ввода пользовательских данных, изменение размера окон, и также многое другое. Полностью GLUT описан в разделе Appendix A, “Основы GLUT: The OpenGL Utility Toolkit”.

Последняя функция в main() это glutMainLoop(), которая представляет собой бесконечный цикл, работающий с оконной и операционной системой, для обработки данных ввода и прочих таких операций. Именно в glutMainLoop() запрашивает обновление окна, частота которога задана в glutDisplayFunc(). Полезно знать, что поскольку glutMainLoop() цикл бесконечный, любая команда заданная после него не может быть выполнена.

 

Запуск OpenGL

 

Следующая процедура, которую нам стоит рассмотреть - это init() из Примера 1.1. Вот еще раз код, чтобы вы вспомнили:

[код]

Инициализация нашей сетки вершинных объектов

Много чего происходит в функциях и данных init(). Начиная сверху, мы приступаем к размещению сетки вершинных объектов вызовом функции glGenVertexArrays(). OpenGL выдаст несколько наименований объектов для нашего использования; в нашем случае, NumVAOs, которые мы указали в разделе глобальных переменных кода. glGenVertexArrays() возвращает это же количество наименований в массиве, VAOs в нашем случае.

Вот полное описание glVertexArrays():

void glGenVertexArrays(GLsizei n, GLuint *arrays);

Returns n currently unused names for use as vertex-array objects in the

array arrays. The names returned are marked as used for the purposes

of allocating additional buffer objects, and initialized with values

representing the default state of the collection of uninitialized vertex

arrays.

 

Мы встретим множество команд OpenGL формы glGen* для задания наименований разным видам объектов OpenGL. Наименование это что-то вроде переменной точечного указателя в языке С, сходство в том, что пока ты не отведешь некое количество памяти и не задашь ему наименование, само наименование не особо помогает. В OpenGL точно также. Наша схема распределения называется “привязка объекта”, и выполняется она набором функций OpenGL порядка glBind*. Например, мы создаем и привязываем массив вершинных объектов с помощью команды glBindVertexArray().

void glBindVertexArray(GLuint array);

glBindVertexArray() does three things. When using the value array that

is other than zero and was returned from glGenVertexArrays(), a new

vertex-array object is created and assigned that name. When binding to a

previously created vertex-array object, that vertex array object becomes

active, which additionally affects the vertex array state stored in the

object. When binding to an array value of zero, OpenGL stops using

application-allocated vertex-array objects and returns to the default state

for vertex arrays.

A GL_INVALID_OPERATION error is generated if array is not a value

previously returned from glGenVertexArrays(), or if it is a value that has

been released by glDeleteVertexArrays().

 

Внашем случае, после создания массива вершинных объектов, мы привязываем его к запросу glBindVertexArray(). Привязка объектов таким образом - очень распространённая операция в OpenGL, но можно легко и интуитивно понять, как это работает. Когда вы привязываете объект в первый раз (т.е., когда glBind* запрашивается в первые для определенного объекта), OpenGL распределит внутреннюю память так, чтобы сделать это объект текущим, что означает, что любая операция относительно привязанного объекта, как вершинный массив в нашем случае, будет влиять на настоящее состояние объекта с настоящего момента исполнения программы. После первого запроса любой из функций glBind* новые сгенерированные объекты будут запущены в своем дефолтном состоянии и скорее всего потребуют дополнительной инициализации, прежде чем вы сможете их использовать.

Представьте привязку объектов, как железнодорожную стрелку. Когда стрелка переводится в какое-либо положение, все поезда едут на эти пути. Если снова перевести стрелку - туда и поедут все поезда опять. Так же и для объектов OpenGL. Проще говоря, вы используете привязку объектов по 2м основным причинам: сначала, когда вы впервые создаете и инициализируете объект и его данные, и потом снова, когда вы хотите его использовать и сделать “текущим”. Мы столкнемся с такой ситуацией при рассмотре строки display(), когда к glBindVertexArray будет повторное обращение.

Поскольку наш пример крайне минималистичен, мы не использыем некоторые функции, которые можно встретить в более подробных программах. Например, когда вы закончите работу с массивом объектов, его можно удалить вызовом функции glDeleteVertexArray().

void glDeleteVertexArrays(GLsizei n, GLuint *arrays);

Deletes the n vertex-arrays objects specified in arrays, enabling the names

for reuse as vertex arrays later. If a bound vertex array is deleted, the

bindings for that vertex array become zero (as if you had called

glBindBuffer() with a value of zero) and the default vertex array becomes

the current one. Unused names in arrays are released, but no changes to

the current vertex array state are made.

 

Наконец, для полноты примера, вы можете определить, было ли задано наименование для массива вершинных объектов.

GLboolean glIsVertexArray(GLuint array);

Returns GL_TRUE if array is the name of a vertex-array object that was

previously generated with glGenVertexArrays(), but has not been

subsequently deleted. Returns GL_FALSE if array is zero or a nonzero

value that is not the name of a vertex-array object.

 

Вы найдете такие примеры команд glDelete* и glls* для разных типов объектов OpenGL.

 









Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2018 zdamsam.ru Размещенные материалы защищены законодательством РФ.