Презентация 6 / 2011

Кодът и презентацията от лекция 6 са качени на сайта

- PDF файл.
- ZIP файл с презентация, картинки и клипче.

В SVN новите неща са в ревизия 646.
Има малко променени неща спрямо кода от лекцията:

- Поправих бъга, който пречеше да видим резултата от glossy шейдъра. Проблемът беше просто, че функцията genUnitDiscSample() трябваше да приема два double псевдонима (double& x, double& y), в които да пише резултатите - на лекцията пропуснах "&"-ките.
- Добавих, в кода на Reflection шейдъра и частта за glossy отражения, следната логика:

	int actual_samples = ray.depth == 0 ? this->samples : 5;
	for (int i = 0; i < actual_samples; i++) {

това е една често срещана оптимизация - когато два отражателни обекта има опасност да си прехвърлят лъчи един на друг, и единият от тях е с glossiness < 1 (т.е. има необходимост да се пуска Монте-карло с много лъчи), се получава мощна комбинаторна експлозия и рендерирането става много бавно.
Затова, може да правим пълната симулация (с 32 изстрелвани лъча) само за идващите от камерата лъчи, а другите случаи, които се виждат само след отражение или пречупване (вторичните лъчи) да използваме по-ниско качество - и да се надяваме никой да не забележи :)
- Оставих следната сцена: "дървен" под с грапаво-отражателен слой отгоре (плътност 20%, glossiness = 0.97, 32 семпъла), CSG обекта с Фонг шейдър, и "стъклено" топче (отново слоест шейдър с Френелово отражение/пречупване).
- Сцената се рендерира все пак бавно (въпреки оптимизацията), за 90 секунди на моя компютър - довечера ще си поиграя да профилирам и да го оптимизирам.

Comments

оптимизации и още нещо

Както обещах, поиграх си да оптимизирам текущия код на учебния рейтрейсър. Оптимизациите можете да разгледате в ревизии 650-652. Основните "заподозряни" се оказаха Cube::intersect() и Plane::intersect() (CsgOp-овете също, но затова си има и домашно за тях). В крайна сметка, след всички оптимизации, времето за рендериране падна с около 30%.

В ревизия 654 добавих по-различно прогресивно рендериране на кадъра. Кадърът се рендерира първо с много ниска разделителна способност (с по един лъч на 16х16 пиксела), след което минава нормален пас, но без antialiasing, като пикселите се рендят последователно на региони (от 64х64 пиксела), като регионите са подредени зигзагообразно из кадъра.
След този пас се прави needAA изчисленията, и следва финален пас с anti-aliasing.

Многонишково

Предлагам message loop-а на програмката да се сложи в някаква отделна нишка (или по-скоро renderScene). Малко е досадно, че ако кликна някъде докато се ренди, опресняването спира да работи, защото програмата не отговаря на съобщения. Особено сега когато всичко се показва постъпково.

И преди някой да е казал, че едно е да го предложа, друго е някой да седне и реализира, предлагам пач който прави точно това със нишките на SDL-a. Общо взето цялата промяна се състои в една нишка за рендване и един двоичен семафор (mutex) за синхронизация. Всичко е много базово, но си работи хубаво.

Ето го и пача: http://dl.dropbox.com/u/50182971/multithread.patch

P.S. : форума има ли прикачени файлове, че не можах да ги намеря? Не че ми е проблем да си ползвам dropbox-а за пачове.

accepted

Здравей,
качването на файлове по принцип го няма в този CMS, но може да се добави - ще го инсталирам тези дни.

Добавих предложението ти към сорсовете, макар и с малко промени - исках renderScene_НещоСи_() извикването в main() да си остане със същия смисъл, както досега - да изрендва сцената, и функцията да се върне след края на рендерирането, а не веднага.
Идеята е, че ако някои иска да си ренди анимация с рейтрейсъра, да може просто да вкара generateScene() и renderScene...() във for-цикъл.
Освен това, сега старото поведение може да се върне просто като се замени извикавнето на новата функция (renderScene_Threaded) със старата (renderScene).