ASSIGNMENT 3

advertisement
ASSIGNMENT 3
Assignment 3.1
• Растеризация на CUDA
–
Загрузить 3d модель (stanford bunny, dragon или buddha)
–
Преобразовать вершины
–
Растеризация в разделяемой памяти
–
Простое освещение
2011
Загрузка модели
•
Используйте .obj формат – текстовый файл с простой разметкой
v -43.11835
v -12.49871
v -43.11835
v -12.49871
v -43.11835
v -12.49871
v -43.11835
v -12.49871
2.40170 28.98380
2.40170 28.98380
24.56909 28.98380
24.56909 28.98380
2.40170 50.53307
2.40170 50.53307
24.56909 50.53307
24.56909 50.53307
vn 0.00000 0.00000 -1.00000
vn 0.00000 0.00000 -1.00000
vn 0.00000 0.00000 -1.00000
vn 0.00000 0.00000 -1.00000
vn 0.00000 0.00000 1.00000
vn 0.00000 -0.00000 1.00000
vn -0.00000 0.00000 1.00000
vn 0.00000 0.00000 1.00000
f
f
f
f
f
f
f
f
f
f
f
f
1//1
4//4
5//5
8//8
1//1
6//6
2//2
8//8
4//4
7//7
3//3
5//5
3//3
2//2
6//6
7//7
2//2
5//5
4//4
6//6
3//3
8//8
1//1
7//7
4//4
1//1
8//8
5//5
6//6
1//1
8//8
2//2
7//7
4//4
5//5
3//3
V – префикс задает вершину
Vn – префикс задает нормаль
f – префикс задает грань в формате:
индекс вершины/индекс текстуры/индекс нормали.
Индекс текстуры для задания не нужен.
Индексы начинаются с ‘1’, в то время как массивы в С++ с ‘0’
2011
Загрузка модели
• Загрузку можете написать самостоятельно
• Можете взять готовую в интернете
– Например glm
• Можете спросить в группе
2011
Преобразование вершин
• Преобразование вершин бывает
– Model или «модельное». Это преобразование вершин из координатного пространства
модели в мировые координаты. Типичные преобразования – поворот, масштабирование и
перенос.
– View или «видовое». Это преобразование вершин из мировых координат в координаты
камеры. Камера – это точка в пространстве, с направлением взгляда и вектором
ориентации «вверх». В графических API камера распологается в точке (0,0,0), смотрит по
вектору (0, 0, 1) (или (0, 0, -1)), и ориентирована по вектору вверх (0,1,0).
– Projection или «проекции». Это преобразование вершин из координат камеры в
координаты пространства отсечения. После умножения на матрицу проекции xyz
координаты делятся на w. Полученные координаты лежат в пространстве отсечения (это
куб [-1, 1]2 x [0, 1]). Вершины которые оказались вне этого куба – не попадают в пирамиду
видимости.
•
Все преобразования вершин работают с векторами xyzw.
–
•
Для точек w == 1, для направлений w == 0.
Все матрицы преобразований – матрицы 4х4
– Как построить матрицу <insert name > – смотрим вызовы directx или спрашиваем в
группе.
2011
Преобразование вершин
•
Преобразование вершин :
–
Пусть N треугольников, треугольник это 3 вершины идущие подряд: A1, B1, C1, … AN, BN, CN
–
Более оптимально разложить треугольники так: A1, A2, A3, .. AN, B1, B2, B3, .. ,BN, C1, C2, C3, .. ,CN
Входной список вершин (N*3)
Входной список нормалей (N*3)
CUDA ядро (N*3) потоков: V * Model * View * Projection
N * Model
Выходной список вершин (N*3)
Выходной список нормалей (N*3)
2011
Глобальная память для буфера
кадра
Color (uchar4)
Depth (float)
Окно растеризации (framebuffer) WxH пикселей – два массива данных в глобальной памяти.
Размер – параметр.
Хорошие размеры для эксперимента – 1024х1024.
Их необходимо проинициализовать начальными значениями
Например – черный цвет и глубина равная 1.0 (бесконечно далеко)
2011
Растеризация
Всё окно разбивается на тайлы (tile).
Размер тайла – например 8x8, 16x8, 16x16, 32x2, 32x4, 32x8, 32x16 пикселей.
Вероятнее всего, оптимальный размер – 32x8, но это не известно 
Для каждого тайла запускается CUDA блок, в каждом блоке кол-во потоков == колву пикселей в тайле (это важно)
2011
Растеризация
Рассмотрим
работу
отдельного
тайла
Рассмотрим
работу
отдельного
тайла
2011
Растеризация
• CUDA ядро: пусть размер блока Bx*By
– Прочитать из глобальной памяти в разделяемую
исходные значения цвета и глубины (1 поток
читает по одному значению)
__shared __ uchar4 color[Bx*By];
__shared__ float depth[Bx*By];
– синхронизация
2011
Растеризация
• CUDA ядро: пусть размер блока Bx*By
– Вычислить границы тайла в пространстве [-1, 1]2
Выходной список вершин (N*3)
Выходной список нормалей (N*3)
– Каждый поток читает треугольник из глобальной
памяти и проверяет пересекает ли треугольник
данный тайл
• Т.е. Если N треугольников, то каждый поток пересекает
N/(Bx*By) с тайлом  чем больше потоков, тем лучше.2011
Растеризация
• CUDA ядро: пусть размер блока Bx*By
– Если треугольник пересекает тайл то его индекс в
памяти записывается в массив разделяемой
памяти __shared__ int smem_tri_idx[Bx*By]
– Если треугольник не пересекает тайл то в
разделяемую память записывается -1
– синхронизация
2011
Растеризация
Пересекает поток №:
Результат пересечения:
Поток записал в shared:
0,
1,
0,
1,
0,
-1,
2,
0,
-1,
3,
0,
-1,
4,
1,
4,
5,
1,
5,
6,
1,
6,
7
0
-1
2011
Растеризация
Пересекает поток №:
Результат пересечения:
Поток записал в shared:
0,
1,
0,
1,
0,
-1,
2,
0,
-1,
3,
0,
-1,
Не пересекающие тайл треугольники нас не интересуют!
4,
1,
4,
5,
1,
5,
6,
1,
6,
7
0
-1
2011
Растеризация
• CUDA ядро:
– Синхронизация (индексы треугольников лежат в
shared памяти)
– Цикл (по размеру блока)
• Каждый поток берет индекс треугольника
• Читает треугольник из глобальной памяти
– если индекс != -1
• Проверяет пересекает ли данный треугольник тот
пиксел, которому соответствует поток
2011
Растеризация: тайл крупным планом
2011
Растеризация: тайл крупным планом
• Как вычислить барицентрические
коодинаты?
– Разложить AP = u*AB + v*AC
– 2 ур-ния (x, y)
A
– 2 неизвестные (u, v)
– Решение через определитель
– Если u >= 0 и v >= 0 и u+v <=1
• Пиксел лежит внутри треугольника
B
• Можно интерполировать вершинные аттрибуты
P
C
2011
Растеризация: тайл крупным планом
• Нужно вычислить
– Глубину точки
• Сравнить с глубиной в разделяемой памяти
• Если тест глубины пройден, тогда обновить глубину в
разделяемой памяти и сделать расчет освещения
– Расчет освещения и запись в разделяемую память
• Вычислить единичную нормаль в точке n
• Диффузное освещение L в точке P
– Lp = max(0, dot(n, light_dir)) где light_dir – направление счета
2011
Растеризация
Разделяемая память
• CUDA ядро:
– Продолжить процесс для
следующих 64-ёх треугольников
– Когда все треугольники
закончились записать результат
из разделяемой в глобальную
память
– Можно дальше растеризовать
след. модель
Глобальная память
2011
Результат
• Резульатат растеризации записывайте в
файл
– Можете использовать devil
• http://code.google.com/p/msu-openglcourse/wiki/Devil_Basics
– Работает на нашем сервере
2011
Assignment 3.2
• Тоже самое что задание 3.1 но дополнительно на выбор:
– Растеризовать не весь список треугольников, а предварительно
составить более короткие списки треугольников
•
Используйте Thrust и операцию stream compaction
– Более сложная модель освещения (например Phong)
– Поддержка OpenGL (возможность полетать камерой)
•
Тогда проверять будем на windows машине
• Быстрое создание gl окна http://code.google.com/p/msu-openglcourse/wiki/Freeglut_GLEW_Basics
– Отложенное освещение (deferred shading)
2011
Глобальная память для буфера
кадра
Color (uchar4)
Depth (float)
2011
Глобальная память для буфера
кадра
Q1
Q2
Depth (float)
Color (uchar4)
Q3
4 списка:
Q1:
Q4
Q2:
Q3:
Q4:
2011
Глобальная память для буфера
кадра: можно иерархически
Q11
Q13
Q3
4 списка:
Q11: Q12:
Q12
Q2
Q14
Color (uchar4)
Depth (float)
Q4
Q13:
Q14:
Q2:
Q3:
Q4:
2011
Assignment 3.2
• Более сложная модель освещения:
– Очень подробное описание моделей с кодом шейдеров glsl можно найти тут:
http://steps3d.narod.ru/tutorials/lighting-tutorial.html
–
Спрашивайте в нашей группе
2011
Assignment 3.2
• Deferred shading
– Проблема в задании 3.1 в том, что когда часть потоков найдет пересечение
пиксела с треугольником а часть нет, то возникнет простой в работе:
–
•
Те потоки которые найдут пересечение с треугольником начнут вычислять освещение
•
Если освещение сложное – то это много математических инструкций
•
Остальные потоки (для которых пиксели не пересекают данный треугольник) ждут
Решение: отложить процесс освещения до самого конца
•
Если пиксел пересекает треугольник, то запоминать индекс треугольника и барицентрические
координаты u и v
•
В разделяемой памяти записывать глубину, индекс треугольника, u, v
•
После того как все треугольники проверены – вычислить освещение в тех пикселах для
которых индекс треугольника != -1
2011
Общие правила по оформлению
программ
• Если сдаете по email
– Email ДОЛЖЕН быть с темой CUDA ASSIGNEMENT 2011.N (N - номер
задания, в данном случае 2)
• Задание сложное
– И на него у вас 1 неделя
Недвусмысленный
намек от кэпа
– Не откладывайте с вопросами
2011
Общие правила по оформлению
прорамм
– Программа должна делать проверки на ошибки:
• Наличие девайса?
• Выделилась память?
• И т.д.
– Программа должна компилироваться с CUDA Toolkit 3.2
• Если писали на windows то vcproj для VS2005 / VS2008 либо
(makefile + .bat)
• Если писали на *nix то make
2011
Общие правила по оформлению
программ
• Если вы используете любые другие инклюды кроме
стандартных – не расчитывайте, что они прописаны
на проверяющей машине.
• Пример того, чего не будет на машине:
– cutil.h
(требует установки CUDA SDK)
• Пример того, что будет на машине:
– cudart.h (ставиться вместе с CUDA toolkit)
– stdio.h
(стандартная C библиотека)
– thrust
– cufft
2011
Вопросы
2011
Download