Презентация 12 / 2015

Лекция 12 е качена в интеренет, заедно с обещаните фиксове по кода:

PDF, ZIP (.odp + картинки), Video.

В написания по време на лекцията код, за съжаление, има доста бъгове, които са отстранени в github. Конкретно:

  • [e8200c] отстранява грешното генериране на случайни изходящи лъчи (hemisphereSample). Кодът за генериране на Θ и ɸ е верен, но превръщането в сферични координати не е, тъй като очакваната параметризация от mathworld е различна.
    Това генерираше лъчи, които не само не са равномерно разпределени, ами са и много силно концентрирани към полюсите, т.е. в посока ±Y. В резултат, ламбертовия материал на пода се държеше по-скоро като матово огледало.
  • [d5ca0e] сменя изчисляваната вероятност на Lambert::spawnRay да е 1/(2π), а не 1/π. Причината е, че макар и BRDF-ът да е 1/π навсякъде (за да може интеграла от BRDF-а * cos(ωout, normal) около цялата полусфера да е точно 1), то вероятностната плътност на генерираните лъчи не зависи от косинуса, тя е равномерна върху цялата 2π полусфера, т.е. 1/2π. Ефектът от тази промяна е само, че GI ефектът се засилва, т.к. преди беше 2 пъти по-слаб от очакваното.
    Примери: преди, след прилагане на промяната (двата рендера са с 12000 пътя на пиксел и са отнели ~45 часа рендене).
  • [2bafe0] добавя explicitLightSample. Всички хакове от лекцията са премахнати и вече изчисляването на светлината по пътя е просто

    L * pathMultiplier * brdfAtPoint / pdf

    Където:

    • L е светлината на лампата (цвят * мощност)
    • pathMultiplier е произведението на всички BRDF-и по пътя (и cos term-ове от уравнението на Каджия, където е подходящо)
    • brdfAtPoint е BRDF-а в последната точка от пътя (и cos term-а от уравнението на Каджия, ако е подходящо). Забележете, че този множител е 0, ако материала е Reflection/Refraction, тъй като техния eval() връща 0.
    • pdf е вероятността да се генерира лъч към точно тази лампа. pdf = (1 / solidAngle) * (1 / numLights), т.е., за дадената светлина, оценяваме, че вероятността случайно да я уцелим, е 1 / solidAngle, понеже проекцията на лампата върху единичната полусфера над точката има площ solidAngle. Ако приемем, че всяка част от лампата е равно-вероятна да бъде уцелена, то вероятностната плътност е 1 / solidAngle. Множителят 1 / numLights идва поради това, че избираме една случайна от всички numLights лампи.

    Ето как изглежда подобрението от изричното семплиране: без, със, при 12000 пътя на пиксел. Ето и как изглежа boxed.qdmg с изрично семплиране.

Бъговете тук прекрасно илюстрират това, което ви бях казвал по-рано: GI алгоритмите е тривиално да се омажат.