Введение.
Иногда у вас нет текстурных координат на вашем объекте, но вы хотите, чтобы текстуры нескольких объектов были выровнены или у вас есть другая причина для генерации собственных UV-координат ... В этом уроке мы начнем с самого простого способа генерации собственных координаты, planar mapping.
Этот урок опирается на простой текстурированный шейдер, но вы можете использовать эту технику с любым шейдером, включая поверхностные шейдеры.
Основа.
Начнем с удаления координат uv из входной структуры, поскольку мы создадим собственные координаты текстуры.
struct appdata{
float vertex : POSITION;
};
Так как UV-координаты все еще должны быть интерполированы между вершинами, как это было раньше, мы вычисляем новые UV в вершинном шейдере. В начале мы можем установить UV-координаты для значений x и z координат объекта. Этого достаточно, чтобы текстура появилась на нашей модели, и будет выглядеть как будто она выжата на ней сверху.
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = v.vertex.xz;
return o;
}
Настраиваемый тайлинг.
Это не учитывает масштабирование текстуры, и мы можем захотеть, чтобы текстура не вращалась и не двигалась вместе с объектом, как сейчас.
Чтобы исправить масштабирование и смещение текстуры, мы просто поместим макрос TRANSFORM_TEX вокруг координат uv.
v2f vert(appdata v){
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.vertex.xz, _MainTex);
return o;
}
Текстурные координаты, основанные на мировой позиции.
Чтобы взять положение объекта и вращение, мы должны использовать положение вершины в мире (ранее мы использовали положение относительно центра объекта). Чтобы вычислить мировое положение, мы умножаем объект на мировую матрицу (здесь я не буду вдаваться в матричное умножение). После того, как мы получим мировое положение, мы используем это, чтобы установить uv-координаты.
v2f vert(appdata v){
v2f o;
//рассчитываем позицию вершины в пространстве объекта
o.position = UnityObjectToClipPos(v.vertex);
//рассчитываем позицию вершины в мировом пространстве
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
//изменяем UV на основе тайлинга и смещения текстуры
o.uv = TRANSFORM_TEX(worldPos.xz, _MainTex);
return o;
}
Как вы видите, у этой техники есть некоторые недостатки, в основном, что она работает только с тайлящимися текстурами и имеет растяжение по бокам, но это можно смягчить с помощью более продвинутых методов, таких как трипланарный маппинг, о котором я расскажу в более позднем уроке.
Shader "Tutorial/008_Planar_Mapping"{
//показываем значения свойств для редактирования в инспекторе
Properties{
_Color ("Tint", Color) = (0, 0, 0, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader{
//материал полностью непрозрачный и визуализируется в то же время что остальная непрозрачная геометрия
Tags{ "RenderType"="Opaque" "Queue"="Geometry"}
Pass{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
//текстура и ее тайлинг/смещение
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
struct appdata{
float4 vertex : POSITION;
};
struct v2f{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v){
v2f o;
// рассчитываем позицию вершины в пространстве объекта
o.position = UnityObjectToClipPos(v.vertex);
// рассчитываем позицию вершины в мировом пространстве
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
// изменяем UV на основе тайлинга и смещения текстуры
o.uv = TRANSFORM_TEX(worldPos.xz, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_TARGET{
//читаем текстуру в UV позиции
fixed4 col = tex2D(_MainTex, i.uv);
// умножаем цвет текстуры на цвет оттенка
col *= _Color;
return col;
}
ENDCG
}
}
FallBack "Standard" //fallback добавляет проход рассчета тени для получения теней на других объектах
}
Вы можете найти код к уроку тут:
https://github.com/ronja-tutorials/ShaderTutorials/blob/master/Assets/008_Planar_Mapping/planar_mapping.shader
Перевод Беляев В.А. ака seaman
Комментариев нет:
Отправить комментарий