Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
калачева перевод.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
237.97 Кб
Скачать

Наш первый рендеринг в OpenGl

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

void

display(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glBindVertexArray(VAOs[Triangles]);

glDrawArrays(GL_TRIANGLES, 0, NumVertices);

glFlush();

}

Мы начинаем рендеринг с очищения кадрового буфера. Это делается командой glClear().

void glClear(GLbitfield mask);

Clears the specified buffers to their current clearing values. The mask

argument is a bitwise logical OR combination of the values listed in

Таблица 1.3 Очистка буфера

Буфер

Именование

Буфер цвета

GL_COLOR_BUFFER_BIT

Буфер глубины

GL_DEPTH_BUFFER_BIT

Стенсил буфер

GL_STENSIL_BUFFER_BIT

Мы обсудим стенсил и глубину, а также подробно поговорим про буфер цвета в Главе 4, “Color, Pixles and Framebuffers”.

Возможно вы спросите, как же установить цвет очистки для glClear(). Дефолтный цвет очистки в OpenGL - черный. Настроить другой цвет можно командой glClreaColour().

void glClearColor(GLclampf red, GLclampf green, GLclampf blue,

GLclampf alpha);

Sets the current clear color for use in clearing color buffers in RGBA mode.

(See Chapter 4 for more information on RGBA mode.) The red, green,

blue, and alpha values are clamped if necessary to the range [0, 1]. The

default clear color is (0,0,0,0), which is the RGBA representation of black.

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

На примере цвета очистки, предположим вы хотите, чтобы очистка экрана всегда была белой. Вам нужно вызвать glClreaColor(1,1,1,1). Но где делать этот запрос? Конечно можно задать его непосредственно перед glClrear() в display(), но тогда первый запрос будет резервным - OpenGL будет менять цвет с белого на черный каждый последующий раз при очистке. Более логично было бы прописать значение цвета очистки в init(). Таким образом мы можем сократить дополнительные внесения изменений в код программы. Все значения по умолчанию устанавливаются init(). Хотя конечно, ничего плохого в том, чтобы вносить каждый раз временные изменения, но это может замедлить выполнение вашей программы.

Попробуйте

Пропишите запрос glClrear() в triangles.cpp.

Рисование в OpenGl

Следующие два запроса, которые мы совершим, дадут команду к отрисовке и рендерингу вершин, которые мы запросим. Сначала мы вызываем glBindVertexArray() для выбора массива вершин, который хотим использовать как вершинные данные.

Далее мы вызываем glDrawArrays(), которая собственно и посылает вершинные данные в конвейер OpenGL.

"> void glDrawArrays(GLenum mode, GLint first, GLsizei count);

Constructs a sequence of geometric primitives using the elements from

the currently bound vertex array starting at first and ending at

first + count − 1. mode specifies what kinds of primitives are constructed

and is one of GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP,

GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, and

GL_PATCHES.

В нашем примере, мы запрашивает рендеринг отдельных треугольников, устанавливая метод рендеринга GL_TRIANGLES, начиная с нулевого байта, как мы указали в glVertexAttribPointer() для буфера, и до числа, указанного в NumVertices (у нас их 6).

Попробуйте

Измените triangles.cpp для визуализации разных типов геометрических примитивов, таких как GL_POINTS или GL_LINES. Могут быть использованы любые из вышеупомянутых примитивов, но некоторые результаты могут оказаться не совсем тем, что вы ожидаете. В случае GL_PATCHES вы не сможете увидеть резуьтат, так как для его отображения требуется мозаичный шейдер, о котором Глава 9.

Наконец, позледний запрос в display() - это glFlush(), который запрашивает сброс всех запросов в очереди на сервер OpenGL и их обработку. Вскоре мы заместим команду glFlush() приемом, который позволяет создать плавную анимацию, но для этого нужно немного больше предварительной подготовки, чем мы проводим в нашем первом примере.

void glFlush(void);

Forces previously issued OpenGL commands to begin execution, thus

guaranteeing that they complete in finite time.

Продвинутый уровень

В какой-то точке своей карьеры программиста OpenGL вы зададитесь вопросом: “Сколько времени это отняло?”. “Это” может быть временем визуализации объекта, отрисовки полого экрана, или любой другой команды, выполняемой OpenGL. Чтобы делать это точно, вам нужно знать, когда OpenGL заканчивает выполнение команд, которые вы хотите измерить.

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

void glFinish(void);

Forces the completion of all pending OpenGL commands and waits for

their completion.

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