+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 91.78 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Разбираемся с шейдерами в Unity3D на конкретном примере

20.11.2012 16:38
Nick_Field

Немного теории

Для понимания работы шейдеров, нужно хорошо ориентироваться в том, как видеокарта строит изображение. Общая структура визуализации 3D объекта на экране изображена на рисунке ниже:


Для начала разберемся в таком понятии, как Graphics Rendering Pipeline. Это конвейер, этапы которого проходит видеокарта для построения финального изображения. Окунемся немного в историю. Первые компьютеры использовали программный рендеринг. Всеми просчетами занимался центральный процессор. И конвейер выглядел следующим образом:

Самые первые 3D-ускорители использовали так называемый Fixed-Function Pipeline. Из названия следует, что он был фиксированным и строго последовательным. Вмешаться в построение картинки было невозможно. Сейчас мы рассмотрим все этапы этого конвейера. В дальнейшем нам это пригодится. 

  1. Входные данные. В качестве входных параметров видеокарта получает объект в виде отдельных вершин с множеством атрибутов. Например положение вершины в пространстве, её цвет, нормаль, текстурные координаты и другие.
  2. Трансформации и освещение. На этом этапе над объектом производятся геометрические операции (перемещение, вращение, масштаб). Здесь же производится расчет освещенности сцены. Для каждой вершины вычисляются значения освещенности исходя из расположения и типа источников света, а также параметров, характеризующих поверхность объекта (отражения, поглощения).
  3. Триангуляция. На этом этапе вертексы объединяются в треугольники.
  4. Растеризация. Цель этого этапа рассчитать цвет пикселей на основе тех данных, которые были уже подготовлены. Так как мы имеем информацию только о цвете вершин, то для получения цвета пикселя мы линейно интерполируем значение между значениями цветов соответствующих вершин.
  5. Попиксельная обработка. На этом этапе происходит раскраска пикселей. Входными данными являются данные предыдущего уровня. Также здесь мы можем применять дополнительные эффекты к пикселам. Например текстурирование.
  6. Формирование готового изображения. Теперь мы должны построить финальный кадр. На этом этапе учитываются данные Z-буфера для того, чтобы определить какой объект находится ближе к камере. Также здесь производится альфа-тест. Слой за слоем объекты "наносятся" на финальное изображение. Так же здесь же могут быть применены пост-эффекты. После чего готовый кадр помещается в Frame Buffer.

Итак, мы обзорно рассмотрели этапы Fixed-Function Pipeline. Как мы видим повлиять на финальное изображение мы можем лишь выбрав определенные опции определенных этапов, но написать, например, свою модель освещения мы не можем. В те времена приходилось довольствоваться тем, что поддерживал конкретный видеоадаптер. Так было до появления первых видеокарт с аппаратной поддержкой DirectX 8.0 - 8.1. Начиная с этого момента можно было писать программы для обработки вертексов и пикселей. Конвейер для такой модели показан на рисунке ниже.

В будущем планируется сделать все этапы конвейера программируемыми. 
Теперь, зная как видеокарта строит изображение, стоит немного рассказать о 3D-объектах. Модель это совокупность вершин, связей между ними, а также материалов, анимаций и пр. У вершин есть атрибуты. Например, UV-координаты. Они показывают где расположена эта вершина на текстурной развертке. Материал определяет внешний вид объекта и включает ссылку на шейдер, используемый для визуализации геометрии или частиц. Таким образом эти компоненты без материала отображаться не будут. 
Шейдер - это программа для одной из ступеней графического конвейера. Все шейдеры можно разделить на две группы: вершинные и фрагментарные (пиксельные). В Unity3D есть упрощенный подход к написанию шейдеров - Surface Shader. Это просто более высокий уровень абстракции. При компиляции Surface шейдера компилятор создаст шейдер, состоящий из вершинного и пиксельного. Язык в Unity3D свой. Называется ShaderLab. Он поддерживает вставки на CG и HLSL. 

Практика

В качестве примера рассмотрим написание шейдера, который накладывает на объект diffuse текстуру, карту нормалей, карту отражений (опираясь на Cubemap), и производит отсечение пикселей по альфа-каналу в diffuse текстуре.
Для начала рассмотрим общий синтаксис ShaderLab. Даже если мы пишем шейдер на CG или HLSL, нам все равно нужно знать синтаксис ShaderLab, для того, чтобы мы могли устанавливать параметры нашего шейдера в инспекторе.

Shader "Group/SomeShader" 
{
    // properties that will be seen in the inspector
    Properties 
     {
        _Color ("Main Color", Color) = (1,0.5,0.5,1)
     }

    // define one subshader
    SubShader 
     {
        Pass 
       {

       }
     }
    }
   Fallback "Diffuse"
} 

Первым ключевым словом идет Shader. После него в кавычках указывается имя шейдера. Причем можно указать через "/" путь, где будет лежать шейдер в выпадающем меню при настройке материала в редакторе. После этого идет описание параметров Properties { }, которые будут видны в инспекторе и с которыми cможет взаимодействовать пользователь. 
Каждый шейдер в Unity3D содержит в своем теле как минимум один Subshader. Когда необходимо отобразить геометрию, движок ищет необходимый шейдер и использует первый Subshader из списка, который может обработать видеокарта. Это сделано для того, чтобы один и тот же шейдер мог корректно отображаться на различных видеокартах, поддерживающих разные шейдерные модели. Ключевое словоPass { } определяет блок инструкций одного прохода. Шейдер может содержать от одного до нескольких проходов. Использование нескольких проходов может быть полезно например в случае оптимизации шейдеров для старого железа или для достижения особых эффектов (outline, toon shading и др).
Если Unity3D в теле шейдера не нашла ни одного SubShader"a, который корректно может отобразить геометрию, используется откат к другому шейдеру, объявленному после Fallback инструкции. В примере выше будет использован Diffuse шейдер, если видеокарта не сможет корректно отобразить текущий.

Теперь рассмотрим конкретный пример.

Shader "Example/Bumped Reflection Clip" 
  {
    Properties 
    {
     _MainTex ("Texture", 2D) = "white" {}
     _BumpMap ("Bumpmap", 2D) = "bump" {}
     _Cube ("Cubemap", CUBE) = "" {}
     _Value ("Reflection Power", Range(0,1)) = 0.5
    }
    
    SubShader 
    {
     Tags { "RenderType" = "Opaque" }
     Cull Off
     CGPROGRAM
      
     #pragma surface surf Lambert
     struct Input 
      {
       float2 uv_MainTex;
       float2 uv_BumpMap;
       float3 worldRefl;
       INTERNAL_DATA
      };
          
     sampler2D _MainTex;
     sampler2D _BumpMap;
     samplerCUBE _Cube;
     float _Value;

     void surf (Input IN, inout SurfaceOutput o) 
      {
       float4 tex = tex2D (_MainTex, IN.uv_MainTex);
       clip (tex.a - 0.5);
       o.Albedo = tex.rgb;
       o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
       float4 refl = texCUBE (_Cube, WorldReflectionVector (IN, o.Normal));
       o.Emission = refl.rgb * _Value * refl.a;
      }
     ENDCG
    } 
  Fallback "Diffuse"
} 

Поле Properties cодержит четыре переменные, которые будут отображены в инспекторе Unity3D.
_MainTex - в скобках указано имя, отображаемое в инспекторе, тип и значение по умолчанию.
_MainTex и _BumpMap - текстуры, _Cube - кубомапа для отражений, _Value - ползунок степени эффекта отражений.
Тег { "RenderType" = "Opaque" } помечает шейдер как непрозрачный. Это влияет на очередь отрисовки.
Cull Off указывает, что в шейдере не будет производится отсечения по направлениям нормалей. Существуют три варианта отсечение полигонов: нормали которых направлены от камеры, в камеру, и без отсечения. Последний вариант означает то, что мы будем видеть полигон с двух сторон.
При написании кода мы будем использовать вставку на языке CG. Вставка обрамляется двумя ключевыми словами: CGPROGRAMENDCG.
#pragma surface surf Lambert - объявление функции surface-шейдера и дополнительные параметры. В данном случае функция называется surf, а в качестве дополнительных параметров указана модель освещения по Ламберту.
Теперь рассмотрим входную структуру. Все возможные переменные входной структуры можно посмотреть всправке. Мы же рассмотрим только те, что использовали. 
Переменные uv_MainTex и uv_BumpMap - это UV координаты, необходимые шейдеру для правильного наложения текстур на объект. Эти переменные обязательно должны называться так же, как и названия переменных текстур с префиксом uv_ или uv2_ для первого и второго каналов соответственно. worldRefl иINTERNAL_DATA используются для отражений.
Теперь рассмотрим функцию шейдера surf.
Первым шагом мы получаем четырехкомпонентный вектор, в котором хранится информация о цвете пикселя текстуры. Переменная tex будет хранить информацию о нем. После чего функцией clip мы указываем, какие пиксели мы пропускаем при рендеринге. Т.к. отсекаем мы по информации, которая хранится в альфа-канале, то в параметрах указываем tex.a.
После отсечения мы производим наложение нашей основной текстуры на объект следующей строчкой:

o.Albedo = tex.rgb;

Переменная o это наша выходная структура. Все её поля можно посмотреть в справке по SurfaceShaders. 
Следующим шагом мы применяем карту нормалей:

o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));

После чего производим наложение отражения:

float4 refl = texCUBE (_Cube, WorldReflectionVector (IN, o.Normal));
o.Emission = refl.rgb * _Value * refl.a;

Тут стоит отметить, что полученную информацию об отражении мы умножаем на _Value, чтобы в инспекторе мы могли управлять степенью эффекта.
Ну и в конце не забываем дописать Fallback на случай того, если видеокарта не сможет корректно отобразить этот шейдер.

А вот то, что у нас получилось:

Ссылки по теме

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2019. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года