Введение.
Здесь я собираюсь объяснить, что вам нужно сделать, чтобы создать шейдер в Unity.
Вы получите объект с одним цветом, но мы можем расширить его позже. Если вы обнаружите, что у вас проблемы с пониманием всего, я рекомендую вам сначала прочитать руководство по основам языка hlsl.
Фреймворк Shaderlab
При написании шейдеров в Unity мы не можем начать с написания кода, сначала нужно сказать Unity, как он должен использовать наш шейдер. Вот почему мы начинаем с определения раздела «Шейдер» с именем шейдера и внутри этого раздела «SubShader». Мы можем определить несколько подшейдеров в каждом шейдере и рассказать Unity, когда использовать какой, но большую часть времени мы хотим использовать один и тот же субшадер везде, поэтому мы пока пишем только один.
Shader "Tutorial/02_Simple"{
Subshader{
}
}
В этом субшадере мы напишем наш шейдерный проход. Когда подшейдер отображается, все проходы выводятся последовательно, но пока нам нужен только один проход. В этом проходе мы добавляем несколько тегов, чтобы рассказать Unity, как
мы хотим, чтобы он обрабатывал этот проход. Для этого шейдера мы хотим, чтобы объект, который мы визуализируем, был полностью непрозрачным, и мы хотим, чтобы он визуализировался вместе с другими непрозрачными объектами.
Shader "Tutorial/02_Simple"{
Subshader{
Pass{
Tags{
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
}
}
}
HLSL Код
После того, как мы все это сделали, мы можем начать запись hlsl-части шейдера. Важно понимать, как информация поступает в шейдер. Сначала информация из 3d модели предоставляется вершинному шейдеру, который изменяет информацию о положении и параметрах вершин, а затем результат проходит через растеризатор, который преобразует вершины и треугольники в пиксели, которые можно рисовать на экране. Но в этот момент шейдер еще не знает, какой цвет имеет каждый пиксель, поэтому для каждого пикселя объекта вызывается фрагментный шейдер. Он получает вывод вершинного шейдера с интерполированными значениями между вершинами. Затем фрагментный шейдер возвращает цвет, который будет нарисован на экране.
Чтобы сообщить Unity, что мы пишем здесь код hlsl, мы начинаем эту часть с CGPROGRAM и
заканчиваем ее с помощью ENDCG. Чтобы использовать полезные функции, предоставляемые нам Unity, мы включаем файл UnityCG.cginc.
Shader "Tutorial/02_Simple"{
Subshader{
Pass{
Tags{
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
CGPROGRAM
#include "unityCG.cginc"
ENDCG
}
}
}
}
Начнем с добавления структуры для входных данных. Его обычно называют «appdata», и пока мы получим только вершинные позиции объекта. Чтобы сделать это, мы должны пометить переменную, которая будет заполнена позицией пространства объектов с помощью атрибута position.
struct appdata {
float4 vertex : POSITION;
}
Затем мы записываем структуру, которая будет возвращена вершинным шейдером. Пока нам нужно только положение вершин относительно экрана.
Чтобы Unity знало, что это данные в переменной, мы отмечаем его атрибутом sv_position.
struct v2f {
float4 vertex : SV_POSITION;
}
Далее пишем вершинный шейдер, он возвращает вершину в структуре v2f фрагментному шейдеру и принимает информацию об объекте в appdata. Сначала мы инициализируем новый экземпляр структуры, затем заполняем его положением экрана в вершине и возвращаем его для обработки растеризатором. Функция UnityObjectToClipPos находится внутри файла UnityCG.cginc и позволяет нам не беспокоиться о матричном умножении на данный момент.
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
И, наконец, мы пишем фрагментарный шейдер. Пока мы просто вернем красный цвет, изменим это на что-то более интересное в следующих уроках. Мы должны отметить функцию как sv_target, поэтому Unity знает, что результат этой функции будет отображаться на экране.
fixed4 frag(v2f i) : SV_TARGET{
return fixed4(0.5, 0, 0, 1);
}
После написания наших типов данных и функций мы должны
сказать Unity, какая
функция используется для чего, это делается с помощью #pragma shaderFunction, поэтому мы пишем #pragma vertex vert, чтобы показать Unity наш вершинный шейдер и #pragma frag, чтобы показать Unity наш фрагментный шейдер.
Shader "Tutorial/01_Basic"{
SubShader{
Tags{
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
Pass{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_TARGET{
return fixed4(0.5, 0, 0, 1);
}
ENDCG
}
}
}
Со всем этим мы теперь должны иметь возможность применить наш новый шейдер к материалу и увидеть его в цвете, который возвращает фрагмент шейдера.
Надеюсь, это помогло вам написать свой первый шейдер, и вы узнаете гораздо больше в будущем.
Здесь вы можете найти исходный код шейдера: https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/002_basic/basic_color.shader
Здесь вы можете найти исходный код шейдера: https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/002_basic/basic_color.shader
Переводчик Беляев В.А. ака seaman
Комментариев нет:
Отправить комментарий