Как процессор и графический процессор взаимодействуют для визуализации компьютерной графики?

Центральный процессор (CPU) и графический процессор (GPU) вашего компьютера взаимодействуют каждый раз, когда вы используете компьютер, чтобы предоставить вам четкий и отзывчивый визуальный интерфейс. Читайте дальше, чтобы лучше понять, как они работают вместе.

Фото sskennel .

Сегодняшняя сессия «Вопросы и ответы» приходит к нам благодаря SuperUser — подразделению Stack Exchange, объединяющей сообщества веб-сайтов вопросов и ответов.

Вопрос

Читатель SuperUser Сатья задал вопрос:

Здесь вы можете увидеть скриншот небольшой программы на C ++ под названием Triangle.exe с вращающимся треугольником на основе OpenGL API.

По общему признанию очень простой пример, но я думаю, что это применимо к другим операциям с графическими картами.

Мне было просто любопытно, и я хотел узнать весь процесс от двойного щелчка на Triangle.exe под Windows XP, пока не смогу увидеть вращающийся треугольник на мониторе. Что происходит, как взаимодействуют процессор (который сначала обрабатывает .exe) и графический процессор (который, наконец, выводит треугольник на экран)?

Я полагаю, что для отображения этого вращающегося треугольника в первую очередь используется следующее аппаратное/программное обеспечение:

Оборудование

  • жесткий диск
  • Системная память (RAM)
  • ЦПУ
  • Видеопамять
  • GPU
  • ЖК дисплей

Программное обеспечение

  • Операционная система
  • DirectX/OpenGL API
  • Nvidia Driver

Может кто-нибудь объяснить процесс, может быть, с какой-то блок-схем для иллюстрации?

Это не должно быть сложное объяснение, которое охватывает каждый отдельный шаг (предположим, что оно выходит за рамки), а объяснение, за которым может следовать специалист по ИТ.

Я уверен, что многие люди, которые бы назвали себя ИТ-специалистами, не могли правильно описать этот процесс.

Ответ

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

Изображение от JasonC, доступно здесь в качестве обоев.

Он пишет:

Я решил написать немного о программном аспекте и о том, как компоненты взаимодействуют друг с другом. Может быть, это проливает некоторый свет на определенные области.

Презентация

Что нужно, чтобы нарисовать на экране то единственное изображение, которое вы разместили в своем вопросе?

Есть много способов нарисовать треугольник на экране. Для простоты предположим, что буферы вершин не использовались. ( буфер вершин — это область памяти, в которой вы храните координаты.) Предположим, что программа просто сообщила конвейеру графической обработки о каждой отдельной вершине (вершина — просто координата в пространстве) в строке.

Но , прежде чем мы сможем что-то нарисовать, мы должны сначала запустить некоторые строительные леса. почему мы увидим позже:

  // Очистить экран и буфер глубины
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Сброс текущей матрицы просмотра модели
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
// Рисуем с использованием треугольников
glBegin (GL_TRIANGLES);
// Красный
glColor3f (1.0f, 0.0f, 0.0f);
// Вершина треугольника (передняя часть)
glVertex3f (0,0f, 1,0f, 0,0f);
// Зеленый
glColor3f (0.0f, 1.0f, 0.0f);
// слева от треугольника (спереди)
glVertex3f (-1.0f, -1.0f, 1.0f);
// синий
glColor3f (0.0f, 0.0f, 1.0f);
// справа от треугольника (спереди)
glVertex3f (1.0f, -1.0f, 1.0f);
// Закончено рисование
glEnd ();  

Так, что это сделало?

Когда вы пишете программу, которая хочет использовать видеокарту, вы обычно выбираете какой-то интерфейс для драйвера. Некоторые хорошо известные интерфейсы для драйвера:

  • OpenGL
  • Direct3D
  • CUDA

Для этого примера мы будем использовать OpenGL. Теперь ваш интерфейс с драйвером — это то, что дает вам все инструменты, необходимые для того, чтобы ваша программа говорила с графической картой (или драйвером, который затем говорит) на карту).

Этот интерфейс должен предоставить вам определенные инструменты . Эти инструменты принимают форму API, который вы можете вызывать из вашей программы.

Этот API — это то, что мы видим, используя в приведенном выше примере. Давайте посмотрим поближе.

Леса

Прежде чем вы действительно сможете сделать какой-либо рисунок, вам нужно выполнить настройку . Вы должны определить ваш видовой экран (область, которая будет фактически отображаться), вашу перспективу ( камера в вашем мире), какое сглаживание вы будете использовать (чтобы сгладить края вашего треугольника) ) …

Но мы не будем смотреть на все это. Мы просто взглянем на то, что вам нужно делать каждый кадр .Подобно:

Очистка экрана

Графический конвейер не собирается очищать экран для каждого кадра. Вы должны сказать это. Зачем? Вот почему:

Если вы не очищаете экран, вы просто рисуете над ним каждый кадр. Вот почему мы вызываем glClear с установленным GL_COLOR_BUFFER_BIT . Другой бит ( GL_DEPTH_BUFFER_BIT ) сообщает OpenGL очистить буфер глубину . Этот буфер используется для определения того, какие пиксели находятся перед (или позади) другими пикселями.

Преобразование


Источник изображения

Преобразование — это та часть, где мы берем все входные координаты (вершины нашего треугольника) и применяем нашу матрицу ModelView. Это матрица, которая объясняет , как наша модель (вершины) вращается, масштабируется и переводится (перемещается).

Далее мы применяем нашу матрицу проекции. Это перемещает все координаты так, чтобы они правильно смотрели на нашу камеру.

Теперь мы снова преобразуем нашу матрицу Viewport. Мы делаем это, чтобы масштабировать нашу модель до размера нашего монитора. Теперь у нас есть набор вершин, которые готовы к визуализации!

Мы вернемся к трансформации чуть позже.

Рисование

Чтобы нарисовать треугольник, мы можем просто сказать OpenGL начать новый список треугольников , вызвав glBegin с константой GL_TRIANGLES .
Есть и другие формы, которые вы можете нарисовать. Как треугольная полоса или треугольный веер. Это прежде всего оптимизация, так как они требуют меньше связи между процессором и графическим процессором, чтобы нарисовать одинаковое количество треугольников.

После этого мы можем предоставить список наборов из 3 вершин, которые должны составлять каждый треугольник. Каждый треугольник использует 3 координаты (как в 3D-пространстве). Кроме того, я также предоставляю цвет для каждой вершины, вызывая glColor3f перед , вызывая glVertex3f .

Тень между 3-мя вершинами (3-мя углами треугольника) вычисляется OpenGL автоматически . Он будет интерполировать цвет по всей поверхности многоугольника.

взаимодействие

Теперь, когда вы нажимаете на окно. Приложение должно только захватить сообщение окна, которое сигнализирует о щелчке. Затем вы можете запустить любое действие в вашей программе, которое вы хотите.

Это становится много более сложным, если вы хотите начать взаимодействовать с 3D-сценой.

Сначала вы должны четко знать, в каком пикселе пользователь щелкнул окно. Затем, принимая во внимание вашу перспективу , вы можете рассчитать направление луча от точки щелчка мыши до вашей сцены. Затем вы можете рассчитать, пересекается ли какой-либо объект в вашей сцене с этим лучом. Теперь вы знаете, нажал ли пользователь на объект.

Итак, как вы делаете это вращаться?

преобразование

Мне известны два типа преобразований, которые обычно применяются:

  • Матричное преобразование
  • Костная трансформация

Разница в том, что кости влияют на отдельные вершины . Матрицы всегда влияют на все нарисованные вершины одинаково. Давайте посмотрим на пример.

Пример

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

Если я хочу повернуть его сейчас, я мог бы сам сделать математику (на процессоре) и просто вызвать glVertex3f с другими координатами (которые повернуты). Или я мог бы позволить GPU делать всю работу, вызывая glRotatef перед рисованием:

  // Поворот треугольника по оси Y glRotatef (сумма, 0,0f, 1,0f, 0,0f);  

amount , конечно, просто фиксированное значение. Если вы хотите анимировать , вам нужно будет отслеживать amount и увеличивать его каждый кадр.

Итак, подождите, что случилось со всеми матричными разговорами ранее?

В этом простом примере нам не нужно заботиться о матрицах. Мы просто вызываем glRotatef , и он позаботится обо всем этом за нас.

glRotate производит поворот на угол вокруг вектора x y z. Текущая матрица (seeglMatrixMode) умножается на матрицу вращения с продуктом, заменяющим текущую матрицу, так как ifglMultMatrix вызывается со следующей матрицей в качестве аргумента:

x 2 ⁡ 1 — c + cx ⁢ y z 1 — c — z ⁢ sx ⁢ z ⁡ 1 — c + y ⁢ s 0 y ⁢ x ⁡ 1 — c + z ⁢ sy 2 ⁡ 1 — c + cy ⁢ z ⁡ 1 — c — x ⁢ s 0 x ⁢ z ⁡ 1 — c — y ⁢ sy ⁢ z ⁡ 1 — c + x ⁢ sz 2 ⁡ 1 — c + c 0 0 0 0 1

Ну, спасибо за это!

Заключение

Становится очевидным, что есть много разговоров с OpenGL. Но это нам ничего не говорит. Где связь?

Единственное, что OpenGL говорит нам в этом примере, это , когда это будет сделано . Каждая операция займет определенное количество времени. Некоторые операции занимают невероятно много времени, другие — невероятно быстро.

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

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

Кроме этого, мы можем только спросить у OpenGL о возможностях нашего графического адаптера (максимальное разрешение, максимальное сглаживание, максимальная глубина цвета и т. Д.).

Но мы также можем заполнить текстуру пикселями, каждый из которых имеет определенный цвет. Таким образом, каждый пиксель содержит значение, а текстура представляет собой гигантский «файл», заполненный данными. Мы можем загрузить это в графическую карту (создав буфер текстур), затем загрузить шейдер, сказать этому шейдеру использовать нашу текстуру в качестве входных данных и выполнить некоторые чрезвычайно тяжелые вычисления для нашего «файла».

Затем мы можем «визуализировать» результат нашего вычисления (в виде новых цветов) в новую текстуру.

Вот как вы можете заставить GPU работать на вас другими способами. Я предполагаю, что CUDA работает аналогично этому аспекту, но у меня никогда не было возможности работать с ним.

Мы действительно лишь слегка коснулись всей темы. Программирование 3D-графики — адское чудовище.


Источник изображения

Есть что добавить к объяснению? Звук выключен в комментариях. Хотите узнать больше ответов от других опытных пользователей Stack Exchange? Ознакомьтесь с полной веткой обсуждения здесь.

Оцените статью
TutoryBird.Ru
Добавить комментарий