Вообще, я полагал что tex.Sample() правильно рассчитывает LOD текстуры только при содействии растеризатора. На самом деле это неправда! Оказалось, что LOD рассчитывается по производным правильно и в том случае, если рассчитанные при рэйкасте текстурные координаты приблизительно совпадают с интерполированными координатами из вершинного шейдера. При интерполяции через барицентрические координаты это именно так. Единственное, что не работает - выборка на рёбрах треугольника, т. к. производные от текстурных координат там неправильные. Представьте, что ребро треугольника проходит по центру квада 2x2. В одном пикселе мы получили пересечение и посчитали текстурные координаты, в другом пикселе - пересечения нет и текстурные координаты, скажем, равны 0. Тогда уже не получается правильно посчитать производные от текстурных координат к площади экрана, а значит, и степень наклона поверхности к экрану, и выбрать правильный LOD тоже нельзя. Получаются некрасивые "зазубрины" на рёбрах треугольников:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwmLtZ-Pqk0FhPai6ckKTKTa7qizXEb5gfrwb9bwVBISD0EK869fcyRbPrxEgqAXCVWqOGHoIYhOf_k4WKgAK6M_5z5VYZOoHa37jFyqUI0jPIb-Q-Lzg5gaNSREXuoP41G5aO_TGwtE1A/s400/wrong_lod.png)
Не знаю, как эту ситуацию обрабатывает растеризатор, возможно, берётся LOD соседнего пикселя, или каким-то образом производные "достраиваются" в граничном кваде. Я заборол это следующим образом: считаю ddx() и ddy() от текстурных координат вне условия и проверяю abs значения. Если оно выше чем заданный эпсилон - производные неверные, мы на ребре треугольника. Тогда я просто делаю tex.SampleLevel() из нулевого MIP'а, иначе обычную выборку с анизотропной фильтрацией. Такой хак практически не виден даже при больших углах обзора:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgXVCogh_R7VdLoP9anbGomXqEAGgHOLdcC9WCKnvXtLFB5O5HgxN4S3EyDCYd_VDn7p0q3HPZIf4HVgrNzqsczdjjf0zI_nL3-ANQbXjsoTVU8tf8KAqaPbv12ZHWW9_X1BkKJjboZEm7/s400/chess_board.png)
[update]
Перечитал про производные и нашёл способ, гарантированно находящий неправильные производные на открытых рёбрах треугольников. Надо будет как-нить написать отдельный пост про это.
PS. И всё же, как растеризатор считает LOD на открытых рёбрах?
Комментариев нет:
Отправить комментарий