среда, 11 ноября 2009 г.

Raycaster and MIP-filtering

На днях реализовал MIP-фильтрацию при рэйкастинге.

Вообще, я полагал что tex.Sample() правильно рассчитывает LOD текстуры только при содействии растеризатора. На самом деле это неправда! Оказалось, что LOD рассчитывается по производным правильно и в том случае, если рассчитанные при рэйкасте текстурные координаты приблизительно совпадают с интерполированными координатами из вершинного шейдера. При интерполяции через барицентрические координаты это именно так. Единственное, что не работает - выборка на рёбрах треугольника, т. к. производные от текстурных координат там неправильные. Представьте, что ребро треугольника проходит по центру квада 2x2. В одном пикселе мы получили пересечение и посчитали текстурные координаты, в другом пикселе - пересечения нет и текстурные координаты, скажем, равны 0. Тогда уже не получается правильно посчитать производные от текстурных координат к площади экрана, а значит, и степень наклона поверхности к экрану, и выбрать правильный LOD тоже нельзя. Получаются некрасивые "зазубрины" на рёбрах треугольников:



Не знаю, как эту ситуацию обрабатывает растеризатор, возможно, берётся LOD соседнего пикселя, или каким-то образом производные "достраиваются" в граничном кваде. Я заборол это следующим образом: считаю ddx() и ddy() от текстурных координат вне условия и проверяю abs значения. Если оно выше чем заданный эпсилон - производные неверные, мы на ребре треугольника. Тогда я просто делаю tex.SampleLevel() из нулевого MIP'а, иначе обычную выборку с анизотропной фильтрацией. Такой хак практически не виден даже при больших углах обзора:



[update]
Перечитал про производные и нашёл способ, гарантированно находящий неправильные производные на открытых рёбрах треугольников. Надо будет как-нить написать отдельный пост про это.

PS. И всё же, как растеризатор считает LOD на открытых рёбрах?

Комментариев нет:

Отправить комментарий