Skip to content

About

CPU software rasterizer developed as a part of a university computer graphics course

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Шаблон для заданий «Растеризатор»

Шаблон содержит готовый код для того, что не относится к самой растеризации: чтение .obj, чтение и сохранение картинок, создание окна и вывод в него массива пикселей. Всё остальное (векторы и матрицы, растеризатор, шейдеры, буферы) пишете вы.

Состав

CMakeLists.txt
external/            сторонние библиотеки (header-only)
  stb_image.h          чтение PNG/JPG/...
  stb_image_write.h    запись PNG
  tinyobj_loader_c.h   парсер .obj
resources/           тестовые модели и текстуры (включая скайбокс)
src/
  vectors.h            типы vec2, vec3 (минимум, нужный утилитам)
  image_utils.h/.c     load_image_f32_rgb, save_image_f32_png_rgb
  mesh_utils.h/.c      load_obj, free_mesh
  main_cli.c           пример без окна: меш + картинка -> PNG
  main_app.c           пример с окном: вывод массива пикселей в реальном времени

Сборка под Linux

Шаблон написан на C (C11). Нужны компилятор (gcc или clang), CMake не ниже 3.10 и GLFW 3.3+. На Debian/Ubuntu:

sudo apt install build-essential cmake libglfw3-dev

Сборка (из корня шаблона):

cmake -S . -B build
cmake --build build -j

По умолчанию собирается Release (-O3 -march=native). Для отладки соберите отдельную Debug-версию в другую папку:

cmake -S . -B build_debug -DCMAKE_BUILD_TYPE=Debug
cmake --build build_debug -j

Измерять скорость растеризатора имеет смысл только в Release-сборке.

Сборка под Windows

Сборка CMake(из корня шаблона):

cmake --build build -j --config Release

Запуск

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

main_cli

./build/main_cli [mesh.obj] [texture.png|jpg] [output.png]

Загружает меш (по умолчанию resources/Bunny.obj), печатает число вершин и треугольников, затем загружает картинку (по умолчанию resources/textures/porcelain.jpg) и сохраняет её с переставленными красным и синим каналами (по умолчанию в swapped_rb.png).

main_app

./build/main_app [width] [height]

Открывает окно (по умолчанию 640×480) и каждый кадр заполняет на CPU массив RGBA8 цветом, который плавно меняется со временем; массив выводится в окно через glDrawPixels. Скорость смены цвета умножается на длительность кадра, поэтому не зависит от FPS. Раз в секунду в консоль печатается среднее время кадра. Выход - Esc или закрытие окна.

Вертикальная синхронизация выключена (glfwSwapInterval(0)), чтобы время кадра показывало реальную скорость программы, а не частоту монитора.

Соглашения

Векторы (vectors.h)

В шаблоне есть только типы vec2, vec3 и функции make2, make3 - то, что нужно загрузчику мешей. Операции над векторами, vec4, матрицы и прочую математику дописывайте сами (в этот же файл или в свой).

Картинки (image_utils.h)

  • Картинка - массив float размером w * h * channels, каналы пикселя лежат подряд (RGBRGB...).
  • Строки хранятся снизу вверх: пиксель (x, y) лежит по адресу data[(y * w + x) * channels], y = 0 - нижняя строка картинки. Так же устроены буфер glDrawPixels в main_app и текстурная координата v в .obj. Если вы выберете другое соглашение, поменяйте его везде.
  • load_image_f32_rgb(filename, &w, &h, gamma) загружает RGB-картинку (3 канала), переводит значения в [0, 1] и возводит в степень gamma (gamma = 1 - без преобразования). Возвращает массив, который нужно освободить через free(), или NULL при ошибке.
  • save_image_f32_png_rgb(data, filename, w, h, channels, gamma) возводит значения в степень 1/gamma, обрезает в [0, 255] и пишет PNG. Принимает 1 (только красный канал), 2 (R, G) или 3 и больше (RGB, остальные каналы игнорируются) каналов, поэтому в PNG можно сохранить и кадровый буфер, и, например, буфер глубины.

Меши (mesh_utils.h)

  • Все атрибуты вершины индексируются одним индексом: verts[i], normals[i], tcs[i]. Треугольник t - вершины indices[3*t], indices[3*t+1], indices[3*t+2].
  • В .obj у позиций, нормалей и текстурных координат индексы раздельные. При загрузке каждая уникальная тройка (позиция, текстурная координата, нормаль) становится отдельной вершиной, поэтому вершин в меше может оказаться больше, чем строк v в файле (например, на швах развёртки).
  • Многоугольники разбиваются на треугольники.
  • Нормали и текстурные координаты не генерируются: если в файле их нет (или они заданы не для всех вершин), normals / tcs равны NULL.
  • При ошибке load_obj возвращает пустой меш (num_triangles == 0). Освобождается меш через free_mesh.
  • Файлы материалов (.mtl) не используются.

Ресурсы

Файл Нормали Текст. коорд. Комментарий
Bunny.obj есть есть ~144 тыс. треугольников, хорош для проверки производительности
Roman Centurion.obj есть есть
Chicken_01.obj есть есть
cornell_box.obj нет нет для проверки пересчёта нормалей

Текстуры лежат в resources/textures, грани скайбокса - в resources/textures/skybox.

Как добавлять свой код

Новые .c-файлы добавьте в список add_library(raster_utils ...) в CMakeLists.txt - тогда они будут доступны обеим программам. Можно также завести свои исполняемые файлы по образцу main_cli и main_app.

OpenMP подключается автоматически, если компилятор его поддерживает (#pragma omp parallel for).

About

CPU software rasterizer developed as a part of a university computer graphics course

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages