Войти
ПрограммированиеСтатьиГрафика

Практическое использование расширений: анизотропная фильтрация в OpenGL

Автор:

Кратко о фильтрации текстур - для чего она существует? Вопреки сложившемуся мнению о том, что фильтрация предназначена только для улучшения качества изображения - скажу так - это лишь окончательный результат который складывается не только за счет самой фильтрации. Хотя подобное замечание наиболее справедливо для билинейной фильтрации, но об этом несколько позже. Вернемся к OpenGL. При формировании образа текстуры в памяти программист задает два уровня фильтрации текстур - говоря более простым и понятным языком это фильтры максимальной и минимальной дистанции, какая из функций фильтрации будет применяться для формирования образа текстуры при сильном удалении или при достаточном приближении текстурного изображения. Ты, наверное, уже смотрел примеры с текстурированием - если нет - советую взглянуть.

Рассмотрим функцию при "достаточном приближении": когда один тексель(один элемент или пиксель если угодно для (лучшего понимания) текстуры) становится достаточно большим и покрывает несколько пикселей на экране для устранения ступенчатости мы используем фильтрацию. Замечу, что подобное решение не достаточно эффективно - поскольку фильтрация несколько "смазывает" изображение. Для придания более реалистичного вида необходимо увеличивать разрешение самой текстуры. При этом для каждой аппаратной реализации максимальный размер текстуры свой. Получить его можно, например, с помощью следующего кода (на заметку - текстуры должны иметь размеры (ширина, длина) кратные степени двойки.):

GLint nTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&nTexSize);

Поговорим о минимизации текстурного изображения. Тут конечно нужно упомянуть о мипмаппинге - дело в том, что при достаточном удалении текстуры, могут возникнуть нежелательные искажения и артефакты (так называемый z- или depth-aliasing) в изображении. Для того чтобы этого избежать, используется генерация и сохранение на стадии загрузки уменьшенных копий текстуры для использования на различных дистанциях при удалении. Для улучшения качества полученных изображений также используется фильтрация.

Хочу заметить, что в при использовании совместно с мипмаппингом билинейной фильтрации (впрочем и без нее) возникает эффект mip-banding'а - визуально заметный переход от одного мипмап уровня к другому. Для борьбы с этим используется более требовательная ко времени исполнения трилинейная фильтрация.

Что же тогда такое анизотропная фильтрация? Дело в том, что билинейная и трилинейная фильтрация не совсем корректно рассчитывает цвет текселя - а точнее рассчитывает его неверно (отталкиваясь от законов нашего зрения) для наклонных плоскостей. Использование анизотропной фильтрации дополняет текущие режимы фильтрации, позволяя регулировать угол анизотропии. Чем больше угол - тем выше качество и реалистичность самой фильтрации, тем выше, в то же время, затраты на обсчет. Не стоит ожидать сказочного улучшения качества результата - скорее наоборот - на больших углах мы получим большую "смазанность" изображения - тем не менее результирующее изображение является более реалистичным.

В OpenGL анизотропная фильтрация реализуется расширением GL_EXT_texture_filter_anisotropic. Возможно со временем появятся другие аппаратно-специфичные варианты анизотропной фильтрации - однако я ориентировался именно на это расширение.

Вот ПРИМЕР. Для изменения режима фильтрации левой и правой текстуры используй клавиши '1' и '2'. Углы расположения полигонов меняются клавишами курсора. Приближение и удаление полигонов осуществляется "серыми" плюсом и минусом. В полноэкранном режиме завершить работу приложения можно клавишами Alt+F4. Файлы mainaux.cpp и mainaux.h содержат функцию и константы для универсальной функции поиска вхождения в строку и могут использоваться не только для обработки строки расширения в OpenGL. Поддержка расширения определяется на этапе инициализации:

  // проверим вхождение...

  if (!IsInString(pszExtStr,"GL_EXT_texture_filter_anisotropic"))
  {
    // анизотропная фильтрация не поддерживается

    MessageBox(NULL,"\nAnisotropic texture filtering not found !",
              "Skipping filtering...",MB_OK | MB_ICONINFORMATION);

    LogMsg("GL_EXT_texture_filter_anisotropic not found !\n");
    g_nMaxTex--;
  }
  else
  {
    // есть поддержка анизотропной фильтрации
    // получим максимально доступный угол анизотропии...

    glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&g_nMaxAnisotropy);
    LogMsg("MAX anisotropy: %d\n",g_nMaxAnisotropy);
  }

В случае отсутствия анизотропной фильтрации, пример так же будет работоспособен, однако будут доступны всего три режима - отсутствие фильтрации, билинейная и трилинейная. Если анизотропная фильтрация доступна - то в примере будет доступен еще один уровень фильтрации - с достаточно высоким углом анизотропии для трилинейной фильтрации:

  // если есть поддержка анизотропной фильтрации определенная ранее

  if (g_nMaxTex == (MAX_TEXTURES-1))
  {
    LogMsg("Using anisotropy level: %f\n",(float)(g_nMaxAnisotropy-0.1));

    // используем четвертую текстуру текстуру(отсчет с нуля)...

    glBindTexture(GL_TEXTURE_2D,texture[3]);

    // устанавливаем  угол анизотропии...

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,
                    g_nMaxAnisotropy-0.1);

    // трилинейная фильтрация...

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

    // мипмап уровни...

    gluBuild2DMipmaps(GL_TEXTURE_2D,3,pTexture->sizeX,pTexture->sizeY,
                      GL_RGB,GL_UNSIGNED_BYTE,pTexture->data);
  }
Расширение анизотропной фильтрации не добавляет новых функций - лишь определения и константы.

#расширения OpenGL, #OpenGL, #фильтрация

16 февраля 2002

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