ПрограммированиеПодсказкиГрафика

Три с половиной способа подружить альфа-тест с DXT1

Автор:

Как известно, при использовании фильтрации DXT1-текстур с включенным альфа-тестом (>= 128) или с clip(difftex.a-0.5) в шейдере, появляется темная обводка на границе с прозрачными текселями из-за того, что цвет прозрачных текселей в DXT1 всегда черный. И хотя упоминаний о данной проблеме можно найти немало в интернетах, решений предлагается совсем немного (честно говоря, нашел я всего одно, в списке ниже идет первым).

1. Как советуют авторы у себя в блогах здесь, здесь и много где еще, можно использовать premultiplied alpha, а именно выставлять блендинг в режим (ONE, INVSRCALPHA). Так как по сути DXT1 и есть формат с premultiplied alpha. Но по мне так, уж больно жирно включать блендинг для текстур с однобитной альфой.

2. Можно попытаться восстановить (приближенное) значение цвета на пути к прозрачным текселям (в прозрачных, где альфа = 0, цвет уже не важен). Уже знания того, что DXT1 — формат с premultiplied alpha, достаточно, чтобы догадаться как это можно сделать — просто поделив rgb-компоненты на alpha-компоненту после семплирования DXT1-текстуры (с фильтрацией, разумеется). Но, если интересно, вот математическое обоснование: возьмем случай 1D-текстуры с билинейной фильтрацией; интерполяцию от непрозрачного текселя с цветом (color, 1) к прозрачному с цветом (0, 0, 0, 0) по параметру интерполяции p (от 0 до 1) можно записать так:

lerp(color, 0, p) = color*(1-p) = t.rgb //для цвета
lerp(1, 0, p) = 1 * (1-p) = 1-p = t.a   //для альфы

Собственно мы имеем только значение t — результат выборки из текстуры, а восстановить нужно исходный цвет color (цвет непрозрачного текселя).
Решение «системы уравнений» тривиально: 1-p = t.a => color*t.a = t.rgb => color = t.rgb/t.a.
С 2D-текстурами получается немного интереснее — восстановленный таким способом цвет получается как нечто среднее из цветов непрозрачных текселей, окружающих прозрачный.

3. Решение для бедных: просто выставить ALPHAREF не в 128, а, например, в 200 или 230. С увеличением значения, черноты у границ становится все меньше, однако сами границы приобретают неприятный квадратно-резаный характер.

3½. Радикальный способ — не использовать DXT1 :). Особенно актуально, когда та же текстура (листвы напр.) используется с блендингом и без (т.е. просто с альфа-тестом) на разных объектах или на разных настройках качества, тогда разумно использовать скажем DXT5, у которого альфа отделена от цвета и таких проблем с альфа-тестом нет.

19 мая 2010

Комментарии [5]