пятница, 25 сентября 2015 г.

Procedural Textures

Решил немного поиграться с процедурными текстурами. Подобные текстуры могут быть статическими или динамическими и рассчитываются на лету, для каждого пикселя в пиксельном шейдере. Термин "тексель" здесь не применим, т. к. рассчитываются непрерывные значения, если обратное не было сделано специально. Т. е. у текстуры бесконечное разрешение.



diffuse + normalmap + phong lighting

Pixar's ToyBall

Вся мякотка в том, чтобы рассчитывать сглаженные переходы между границами разных цветов, иначе будет видна попиксельная лесенка. smoothstep, fwidth, frac и floor в помощь. Колдовать приходится много, но сглаженный результат того стоит.

Недостатком таких текстур является отсутствие фильтрации mip-уровней, из-за чего при удалении начинает сказываться point семплирование. Как решение можно написать вручную собственную фильтрацию с множеством процедурных выборок, как сделано в этом шейдере от Inigo Quilez. Врочем, писать свою фильтрацию придётся и в случае с обычными текстурами, т. к. железо делает её в fixed function на основе экранных деривативов, а при рей-трейсинге это нужно делать вручную.

понедельник, 14 сентября 2015 г.

Depth of Field Ray-Traced

Набросал за час демку рей-трейсинга Depth of Field эффекта. В сущности отличий мало от AA-метода, только лучи не параллельны друг другу, а сходятся в точке, где луч-centroid пересекается с фокальной плоскостью. Радиус Circle of Confusion можно легко варьировать.



Метод даёт правдивые результаты, но не отличается быстродействием. Нужно множество лучей (на скриншотах - 32 + jittering), чтобы снизить шум, т. е. сцена семплируется много раз.

Если у вас не простые сферки с фонгом, а что-то потяжелее, то в реал-тайме работать уже не сможет. В сущности, комбинация нескольких нечётких эффектов может замедлять рендеринг в геометрической прогрессии. Например, пиксель содержит пенумбру тени, которую считаем по 16 семплам. Но это для pinhole камеры. Если тот же самый пиксель нужно отобразить для камеры с большой апертурой, например с 32 семплами для DoF, то получится что к солнцу нужно пустить 32x16=512 лучей, и это при скромных начальных условиях. Для production quality рендера количество лучей будет измеряться тысячами.

понедельник, 7 сентября 2015 г.

AA Edge Detection

На выходных возился с оптимизацией оверсемплинга при рейтрейсинге. Идея старая: запускать множество лучей не в каждом пикселе, а только там, где наблюдается лестница алиасинга. Для этого, например, в deferred-renderer-e ищутся контуры объектов, а затем либо по stencil test либо по discard в шейдере запускается множество лучей только для тех пикселей, которые входят в контур. Вопрос как искать эти самые контуры? Путей несколько:

Для пробы я написал шейдер, который берёт depth в camera space (t на луче), определяет дельты между соседними пикселами и по threshold решает быть тут контуру или нет. Это не работает как нужно из-за того, что t меняется нелинейно в screen space, из-за этого вдалеке дельты рано или поздно становятся больше критического значения и маска заливает весь объект. Для корректной работы нужен linear z в screen space, Humus как-то писал на эту тему: A couple of notes about Z. Для этого нужно писать в depth z/w, который интерполируется растеризатором в screen space, тогда деривативы будут давать константный шаг, но в рейтрейсере так сделать не получится.

Другой вариант - брать косинус угла (dot) между соседними нормалями и если он больше некоего threshold то помечать здесь контур. Это неплохо работает, но с оговорками: например, нормали могут совпадать у геометрически разных объектов в некоторых участках изображения, тогда контур определён не будет. Или например в случае bump-mapping'а или похожих алгоритмов может давать "фальшивые" контуры. По-видимому, надёжный алгоритм должен быть многогранным и оперировать всей информацией, которая вносит вклад в создание discontinuities, как на рисунке вверху. Я решил что для стартового варианта лучше всего записывать ObjectID в отдельный канал, и если normal test ничего не дал, проверять контур по ID. В принципе на простых объектах сам ID-тест работает лучше чем тест нормалей, но предсказуемо будет давать ошибки на сложных объектах, части которых могут перекрываться на экране. Поэтому комбинация нескольких тестов тут практически обязательна.




суббота, 5 сентября 2015 г.

Interview with Nvidia engineer about DirectX 12

ВНЕЗАПНО архитектура GCN лучше подходит для DX12, чем Maxwell/Kepler.