Para Cg/HLSL vertex programs, los
datos del vértice del Mesh se pasan como inputs de la
función shader del vértice. Cada input necesita tener una semántica especificada para esto: por ejemplo, input POSITION
es la posición del vértice, y NORMAL
es la normal del vértice.
A menudo, los inputs de datos del vértice se declaran en una estructura, en vez de listarlos uno por uno. Varias estructuras de vértices de uso común se definen en el archivo include UnityCG.cginc, y en la mayoría de los casos es simplemente suficiente utilizar estos. Las estructuras son:
appdata_base
: posición, normal y una coordenada de textura.appdata_tan
: posición, tangente, normal y una coordenada de textura.appdata_full
: posición, tangente, normal, y cuatro coordenadas de textura y color.Ejemplo: Este shader colorea el mesh basado en sus valores normales y utiliza appdata_base
como input del vertex program.
Shader "VertexInputSimple" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color.xyz = v.normal * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
Para acceder a diferentes datos del vértice, debe declarar la estructura de vértices por usted mismo, o agregar parámetros input al vertex shader. Los datos del vértice se identifican por semántica Cg/HLSL, y debe ser de la siguiente lista:
POSITION
es la posición del vértice, típicamente un float3
o float4
.NORMAL
es la normal del vértice, típicamente un float3
.TEXCOORD0
es la primera coordenada UV, típicamente un float2
, float3
o float4
.TEXCOORD1
, TEXCOORD2
y TEXCOORD3
son la 2da, 3ra y 4ta coordenada UV, respectivamente.TANGENT
es el vector tangenete (utilizado para normal mapping), típicamente un float4
.COLOR
es el color por-vértice, típicamente un float4
.Cuando los datos del mesh contienen pocos componentes que se necesitan por el
input del vértice, el resto es llenado con ceros, excepto por el
componente .w
que predetermina a 1. Por ejemplo, las coordenadas de textura del mesh
a menudo son vectores 2D con simplemente componente x y y. Si un vertex
shader declara un input float4
con una semántica TEXCOORD0
, el
valor recibido por el vertex shader contendrá (x,y,0,1).
El siguiente ejemplo shader utiliza las posiciones del vértice y la primera coordenada de textura como los inputs del vertex shader (definido en la estructura appdata). Este shader es útil para depurar las coordenadas UV del mesh.
Shader "Debug/UV 1" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, UV
struct appdata {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
o.uv = float4( v.texcoord.xy, 0, 0 );
return o;
}
half4 frag( v2f i ) : SV_Target {
half4 c = frac( i.uv );
if (any(saturate(i.uv) - i.uv))
c.b = 0.5;
return c;
}
ENDCG
}
}
}
Aquí las coordenadas UV están visualizadas como colores rojo y verde, mientras un tinte azul adicional ha sido aplicado a las coordenadas a fueras del rango 0 a 1:
Similarmente, este sombreador visualiza el segundo conjunto UV del modelo:
Shader "Debug/UV 2" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, second UV
struct appdata {
float4 vertex : POSITION;
float4 texcoord1 : TEXCOORD1;
};
struct v2f {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
o.uv = float4( v.texcoord1.xy, 0, 0 );
return o;
}
half4 frag( v2f i ) : SV_Target {
half4 c = frac( i.uv );
if (any(saturate(i.uv) - i.uv))
c.b = 0.5;
return c;
}
ENDCG
}
}
}
El siguiente shader utilizar la posición del vértice y los colores por-vértice como inputs del vertex shader (definido en la estructura appdata).
Shader "Debug/Vertex color" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, color
struct appdata {
float4 vertex : POSITION;
fixed4 color : COLOR;
};
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
El siguiente shader utilizar la posición del vértice y la normal como inputs del vertex shader (definido en la estructura appdata). La normal de los componentes X,Y & Z se visualizan como como colores RGB. Ya que los componentes de la normal están en el rango –1 a 1, nosotros escalamos y las sesgamos para que los colores del output se muestren en el rango de 0 a 1.
Shader "Debug/Normals" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, normal
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
o.color.xyz = v.normal * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
Las tangentes y los vectores binormales son utilizados para normal mapping. En Unity solo el vector tangente es almacenado en vértices y los binormales se derivan de los valores normales y tangentes.
El siguiente shader utilizar la posición del vértice y la tangente como como inputs del shader (definido en la estructura appdata). Las tangentes de los componentes x,y y z se visualizan como colores RGB. Ya que las componentes de las normales están en el rango –1 a 1, nosotros escalamos y las sesgamos para que los colores output estén en un rango de 0 a 1 que se pueda mostrar.
Shader "Debug/Tangents" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, tangent
struct appdata {
float4 vertex : POSITION;
float4 tangent : TANGENT;
};
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
o.color = v.tangent * 0.5 + 0.5;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
El siguiente shader visualiza bi-tangentes. Este utiliza los valores de la posición del vértice, normal y tangente como inputs del vertex. La bi-tangente (a veces llamada binormal) se calcula desde los valores de la normal y tangente. Este necesita ser escalado y segado a un rango de 0 a 1 mostrable.
Shader "Debug/Bitangents" {
SubShader {
Pass {
Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// vertex input: position, normal, tangent
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct v2f {
float4 pos : SV_POSITION;
float4 color : COLOR;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex );
// calculate bitangent
float3 bitangent = cross( v.normal, v.tangent.xyz ) * v.tangent.w;
o.color.xyz = bitangent * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}