Шейдеры в Unity пишутся на специальном языке, который называется ShaderLab. Язык этот не сложный и в этой статье я его попытаюсь описать.
Конечно большая часть этого урока – содержание справки Unity, но так как у многих проблемы с английским – этот урок будет полезным.
Синтаксис шейдера на языке ShaderLab
// Блок Shader – коневой блок
// он является контейнером для описания шейдера
// через пробел в кавычках указывается имя шейдера
Shader "Имя_шейдера" {
// Блок параметров, которые пользователь может визуально
// настраивать в инспекторе, при выборе данного шейдера
// для материала. Все параметры, описанные в блоке Properties
// в остальных местах шейдера должны применяться
// в квадратных скобках.
Properties {
// Список параметров
// например, следующая строка описывает параметр _Color
// отображаемый в инспекторе как "Main Color" типа
// Color с начальным значением (1,.5,.5,1):
_Color ("Main Color", Color) = (1,.5,.5,1)
// Unity не поддерживает отображение типа Matrix4x4
// но не смотря на это его можно передавать в шейдер
// программным путем.
//
_SpecColor ("Spec Color", Color) = (1,1,1,1)
_Emission ("Emmisive Color", Color) = (0,0,0,0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" {}
}
// SubShader – контейнер, определяющий технику
// визуализации материала.
// Блоков SubShader может быть много, Unity выбирает
// первый подходящий шейдер для видеокарты пользователя
SubShader {
// Pass – блок, описывающий один проход визуализации
// для сложных материалов таких проходов может быть несколько
Pass {
// Блок Material назначает параметры материала,
// которые будут использованы при расчете освещения.
// например, в данном примере устанавливаются все
// параметры, необходимые для полноценного вершинного
// освещения.
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
// Директива Lighting On|Off определяет
// использование освещения.
// Для того чтобы установленные значения блока
// Material имели силу – освещение должно быть включено
Lighting On
// Директива SeparateSpecular определяет, стоит ли
// добавлять зеркальную (бликовую) составляющую в
// конце прохода. Чтобы директива имела силу –
// освещения должно быть включено (Lighting On)
SeparateSpecular On
// дополнительные директивы будут описвны ниже
// Блок SetTexture устанавливает текстуру и метод
// ее наложения. После названия блока SetTexture
// в квадратных скобках передается имя параметра,
// указанного в блоке Properties.
// Внутри блока может присутствовать от одной
// до трех команд (Combine, Matrix и ConstantColor).
// Количество текстурных слотов у разных видеокарт
// разное, так что количество блоков SetTexture
// должно выбираться в зависимости от того, какие
// видеокарты Вы хотите поддерживать. Например,
// видеокарты NVIDIA TNT2, GeForce 256, GeForce 2,
// GeForce 4MX имеют 2 текстурных блока, а такие как
// ATI Radeon 9500 и выше – 4 для D3D и 6-8 для OpenGL
SetTexture [_MainTex] {
// Возможности команды Combine можно посмотреть
// в справке, замечу, что расчет альфы и цвета
// можно разделить. Формулы комбинации цветов
// записываются в это случае через запятую.
Combine texture * primary DOUBLE, texture * primary
}
}
}
// Директива Fallback определяет то, как поведет себя Unity,
// если ни одна из техник, определенных в блоках SubShader
// не поддерживается видеокартой.
// Имеется две формы записи директивы:
// Fallback Off – отключает любые предупреждения о том, что
// ни один из SubShader не поддерживается
// Fallback "имя_шейдера" – передает все параметры (Properties)
// и управление другому шейдеру.
Fallback "Имя_другого_шейдера"
}
Файл шейдера должен иметь кодировку ASCII.
Приведенный в качестве описания синтаксиса шейдер является аналогом материала, используемого в Blitz3d.
Как и обещал, привожу список основных директив блока Pass:
- Cull Back | Front | Off
Устанавливает тип куллинга полигонов. - ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
Устанавливает режим теста глубины. - ZWrite On | Off
Устанавливает режим записи глубины. - Fog { блок описания тумана }
Устанавливает параметры тумана. - AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
Включает альфатест. - Blend SourceBlendMode DestBlendMode
Устанавливает режим альфасмешивания. - Color Color value
Устанавливает цвет, если вершинное освещение отключено. - ColorMask RGB | A | 0 | любая комбинация R, G, B, A
Маска записи цвета. ColorMask 0 выключает рендеринг для всех цветовых каналов. - Offset OffsetFactor , OffsetUnits
Устанавливает офсет (смещение) глубины. - ColorMaterial</strong> AmbientAndDiffuse | Emission
Использует цвета вершин для расчета освещения.
Шейдерные программы
Так же существует возможность применять шейдерные программы, написанные на языке Cg для сложных материалов, в которых необходимы специфические расчеты. Для этого вместо или внутри блока Pass необходимо использовать блок CGPROGRAM
CGPROGRAM
// директивы компиляции:
#pragma vertex vert
#pragma fragment frag
// Cg код
ENDCG
#pragma vertex и #pragma fragment определяют соответственно вершинную и фрагментную функции. Существует так же #pragma target, значениями которой могут быть default и 3.0. В первом случае для компиляции используются vs 1.1 и ps 2.0, во втором – vs 3.0 и ps 3.0. При компиляции для 3.0 – обе директивы #pragma vertex и #pragma fragment должны присутствовать.
Подробнее об этом
ShaderPrograms
В Unity 3 появились новые возможности для реализации шейдеров – Surface Shaders. Используя эти возможности можно облегчить себе жизнь при написании шейдеров на языке Cg. Подробнее -
SurfaceShaders,
примеры таких шейдеров.
Конечно же я не могу охватить все возможности языка ShaderLab, надеюсь и этого хватит, чтобы понять его структуру и двигаться дальше. Удачи!
Более углубленно ShaderLab можно изучить читая справку
UPD: Так же хорошей практикой будет разбор
встроенных шейдеров юнити