CPage
GameDev.ru / Страницы / CPage [Форум / Инфо]

CPage

Эта запись является краткой историей про то как я выполнял тектурирование ландшафта в своем движке.
Все началось несколько месяцев назад, когда я писал игру на конкурс стратегий: нужно было отрисовывать ландшафт.
Тогда я удовлетворился очень простым решением, а именно:
никакого куллинга (а зачем если весь ландшафт 128х128 квадов? )
простое смешивание 2х текстур в шейдере.

Смотрится оно просто:
Изображение


Однако, где-то неделю назад захотелось сделать лучше.

Что мы хотим?
поддержку большого количества текстур, например 32 текстуры.
процедурное смешивание.

Что имеем?
  openGL 2.1 + GLSL 1.0
SM3
GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 4 (что-бы запускалось, и на домашнем ПК, и на ноутбуке)


Что делать?
На таком GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS развернуться довольно сложно, но можно:
  1. Рисуем ладшафт в отдельный фрейм-буффер: во фрагмент пишем: ( RG = texCoord, B - освещенность, A - не используется )
    результат:
    Изображение - savepic.org — сервис хранения изображений
  2. Включаем аддитивный бленд и для каждой задействованой текстурки рисуем FSQ(full screen quad):
  В шейдер передаем:
    1 - текстура подученная на этапе №1.
    2 - дуффузная текстура ( трава/песок/eth ).
    3 - маска, в которой находится вклад текстуры(2) в каждый из тайлов.
    4 - текстура с 2d шумом.
  В шейдере:
    читаем из текстуры №1 uv координаты.
    к uv прибавляем значение полученное из текстуры с шумом.
    вычисляем по uv координатам номер тайла + используя uv координаты, делаем выборку из диффузной текстуры.
    вычисляем освещение( я вычислял по Ламберту )

Результат
Изображение - savepic.ru — сервис хранения изображений - я доволен.
   
   
PS
1. лучше рисовать треугольник, вместо квадрата.
  Дело в том, что в связи в особенностями реализации функции texture2D может появиться диагональная полоса посередине экрана, при использовании квадрата.
2. Шейдер: http://pastebin.com/wqCmN2HU
3. Хороший результат получается, если вместо текстуры шума использовать карту нормалей.
4. На новеньком железе такие приключения совсем не обязательны.
5. Фрагментный шейдер очень тяжелый - стараемся экономить на фрагментах.
6. Надеюсь, что не сильно накосячил с орфографией :-)

16 июля 2011

Вы вероятно уже знаете что такое расширения OpenGL.
Если это не так, то можете ознакомится с ними прочитав эту статью.

Обычно код инициализации расширения выглядит примерно так:

bool Init_GL_ARB_multitexture()
{
  // Проверяем наличие расширения
  if(!IsExtEnable("GL_ARB_multitexture"))
    return false;
  
  // Получить адрес функции и присвоить его глобальному указателю
  glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)
    wglGetProcAddress("glActiveTextureARB");
  glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)
    wglGetProcAddress("glClientActiveTextureARB");
  glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)
    wglGetProcAddress("glMultiTexCoord2fARB");
  return true;
}

Однако очень быстро надоедает прописывать 'магические комбинации букв', такие как  (PFNGLACTIVETEXTUREARBPROC).
Также не очень приятно писать дважды имя нужной функции.
Хочу рассказать вам о том как я сейчас избавляюсь от этих неудобств:

Начнем с (PFNGLWHATIWANTARBPROC):

template< class T >
bool initGlExtensionFuncPtr(T &func, const char * name){
  func = (T)getProcAddress(name); //wglGetProcAddress( name ) или glXGetProcAddress( name ) или handMadeGetProcAddress( name );
  return (func!=0);
  }

Теперь наш код будет выглядеть примерно так:

  initGlExtensionFuncPtr(glActiveTextureARB, "glActiveTextureARB");
  initGlExtensionFuncPtr(glClientActiveTextureARB, "glClientActiveTextureARB");
  initGlExtensionFuncPtr(glMultiTexCoord2fARB, "glMultiTexCoord2fARB");

С помощью макросов его можно сделать еще короче:

#define init(X) initGlExtensionFuncPtr(X, #X)
  init(glActiveTextureARB);
  init(glClientActiveTextureARB);
  init(glMultiTexCoord2fARB);
#undef init 

Также многие рекомендуют проверять все функции на ноль, 'на всякий случай'; добавим эту проверку в наш код и посмотрим что получилось:

#define init(X) initGlExtensionFuncPtr(X, #X)
bool Init_GL_ARB_multitexture()
{
  return
  // Проверяем наличие расширения
    IsExtEnable("GL_ARB_multitexture") && 
  // Получить адрес функции и присвоить его глобальному указателю
    init(glActiveTextureARB) &&
    init(glClientActiveTextureARB) &&
    init(glMultiTexCoord2fARB);
}
#undef init 

PS
  http://www.gamedev.ru/code/articles/?id=4267
  http://www.opengl.org/registry/
  http://www.opengl.org/documentation/

Комментарии [5]
7 янв. 2011

Вот. Запилил редактор. Делает вид что работает)
Изображение - savepic.net — сервис хранения изображений

Хм. Надо бы начать делать систему заклинаний.
И героев добавить.
И узнать как дела у art-отдела
И скелетку реализовать
И поесть
И поспать
...

Комментарии [1]
26 ноя. 2010

Поработал над небом:

Изменил цветовую гамму; Добавил цветовую диференциацию деревьев.
Вроде стало лучше.

23 ноя. 2010

Вот решил создать персональную страничку)
Планирую выкладывать сюда информацию о ходе разаботки своих проектов.

23 ноя. 2010

2001—2017 © GameDev.ru — Разработка игр