ДР/2015/Л13/Средна

Progressive refinement render

В лекция 13 демонстрирахме realtime рейтрейсинг на наистина лека сцена, meshes.qdmg. Действително, не сме пробвали да пуснем интерактивен режим на smallpt.qdmg, която беше с GI - понеже там кадърът се ренди по 15 секунди, даже и с multithreading! Но това е при 40 пътя на пиксел. При 1 път на пиксел (възможният минимум!), скоростта би била 0.37s/кадър, т.е. ~3 FPS, което не е ужасно зле. Особено ако се намали разделителната способност, човек би могъл да си играе интерактивно с такава сцена.

Проблемът е, че кадърът става ужасно шумен при само 1 път на пиксел. Идеята на прогресивното рендериране е да почнем, показвайки на потребителя такъв "ужасен" кадър, и после да продължим да рендим нови кадри, като допълваме техните резултати към досегашния и усреднявайки всеки път наново. Така гледката постепенно се избистря пред потребителя, a ефективните пътища на пиксел постоянно се увеличават. Това е докато нещо по сцената не се смени - потребителят натисне бутон за движение, или мръдне мишката да речем - тогава цялата натрупана работа се изхвърля и се започва ново прогресивно натрупване от 1 paths per pixel с новия изглед.

Очакваното поведение е нещо такова: SmallPT@320x240. Забележете, че не е необходимо тази опция да работи само за GI. Спокойно може да се приложи и при други тежки откъм семпли/пиксел сцени, например с DOF: Meshes with DOF (във видеото съм си добавил клавишни шорткъти за сменяне на Camera::focalPlaneDist, ако се чудите как сменям фокуса).

Като реализация - при интерактивен режим, вместо резултатите да се записват във vfb[y][x], те трябва да се акумулират в нов подобен масив, например accum[y][x]. След всеки изренден така кадър, на екрана трябва да се покаже (за всеки пиксел) accum[y][x] / accumFrames, където accumFrames е броя изрендени кадри от последната промяна на позицията или изгледа на камерата. В момента в който човекът бутне нещо по камерата в mainloop(), accum трябва да се зачисти и accumFrames започва отначало от 0.