[unity3d] base atlas shader


Встроенные шейдеры Unity совершенно не годятся для текстурных атласов, хотя казалось бы с помощью параметров Tiling и Offset можно получить любой фрагмент текстуры. Проблема в UV координатах.
Ниже на присунке, два экземпляра модели world_bridge c разными материалами : верхний с атласом. Как видите в превью материала всё выглядит отлично.



Для выхода из положения в Shader Forge был нарисован базовый Diffuse шейдер. На вход подаются те же Tiling, Offset и угол поворота фрейма (использовался для лучшей упаковки в атлас).


Если использовать не tex2Dgrad, а tex2D то результат получается гораздо хуже при тех же входных данных.



Собственно сами входные данные рассчитываются так:


float left  =  frame_x / atlas_w; float right = (frame_x + frame_w) / atlas_w;
float top = (atlas_h - frame_y) / atlas_h; float bot = (atlas_h - frame_y - frame_h) / atlas_h;
float size_x = right - left; float size_y = top - bot;
mat.SetVector("_RGB_Coords", new Vector4(size_x, size_y , left, bot));


Надо заметить, что толщина (px) защитных бордюров вокруг фреймов должна соответствовать количеству уровней mipMap. Иначе при отдалении карты будут ощутимо видны артефакты ( в англоязычном сегменте интернетов это так называемый texture atlas mipmap bleeding ).

Получается целый ряд проблем :

  • если отключить генерацию mip-map будут артефакты, если включить mip-map будут артефакты; 
  • ограничить глубину mip-map в unity нельзя (или я просто не знаю как), здесь нет аналога opengl GL_TEXTURE_MAX_LEVEL или MaxLOD из D3D10_SAMPLER_DESC. Можно паковать текстуры в DDS формат т.к. он позволяет не только ограничить уровень mip-maps, но и запаковать нарисованные вручную уровни mip-maps. Но этот формат понимает PC (DX, openGL), Sony PS и немного андроида в лице не самого массового nVidia Tegra.
Если есть возможность, прошу гоставить голос вот здесь, запрос в статусе "запланировано", но датирован аж 2013 годом. 


Комментарии