ДР 2013/Л6/Група2

В началото на лекция 7 бях споменал, че за текущата (тогава) сцена съм добавил специален хак за Reflection шейдъра. Хакът (хеш bef15e6c) изглежда така, за glossy случая:

	int samplesWanted = ray.depth == 0 ? numSamples : 5;
	for (int i = 0; i < samplesWanted; i++) {
		...

Причината за него е следната.
Нека имаме следната сцена. На моята машина, тя се ренди за 26 секунди. Ако върнем кода така, както беше на написан по време на лекцията:

	for (int i = 0; i < numSamples; i++) {
		...

времето скача на 74 секунди. Същевременно се вижда, че основната част от времето се губи в регионите точно под сферата и в непосредствена близост до нея.
Какво, всъщност, се случва там?
Идващите от камера лъчи попадат първо в пода, и шейдърът пуска множество лъчи, за да оцени грапавото отражение:

Голяма част от тях стигат до сферата. Там, стъкления шейдър разделя лъчите на две. Пречупените не са проблем, но отразените отиват обратно до пода и там отново става мощно семплиране с много лъчи:

Така, само един лъч от камерата предизвиква лавина от хиляди лъчи. Същевременно е ясно, че не необходимо смятането на толкова много лъчи (един Color едва ли би могъл да обхване толкова информация), съществено е да "смятаме с пълна точност" само първото грапаво отражение, а следващите можем да минем и с по-малко лъчи.
Точно това прави и поправката горе.

Само че, има проблем.
Лъчите, които се пречупват право през топчето и стигат до пода, също се подлагат на "маловажна третировка", при това незаслужено - техният резултат се вижда добре във финалния кадър. В резултат, областта от пода, пречупена през топчето, е видимо шумна:

Още по-ярък пример може да си създадем, ако премахнем грапавостта на пода (0.97 -> 1.0), а на самото топче сложим само Reflection шейдър с glossiness 0.90 и 100 семпъла:


Ясно се вижда "разликата в качеството" на самото топче и на отражението му!

Задачата е да измислите и реализирате някакъв подход, с който да може да определите дали лъчът си струва да се семплира качествено, или не, и който подход да решава всички показани случаи: да не се отказваме съвсем от оптимизацията (и да предотвратяваме комбинаторната експлозия в първия пример), но да си възвърнем качеството в примери №2 и №3.

Очаква се да получите нещо такова като резултат: пример 2, пример 3.

Времето за рендериране не трябва да се увеличава значително - не повече от 30% спрямо оригинала.

Подобно на задачка №1, тук има всевъзможни начини да постигнете исканото в условието. Няма да ви развалям удоволствието да си ги проучите сами; но, отново, ако стигнете до задънена улица или имате проблем, ще помагам(е), а подсказка мога да добавя след няколко дни, ако изявите желание.