For Cg/HLSL vertex programs, the
Mesh vertex data is passed as inputs to the vertex
shader function. Each input needs to have semantic speficied for it: for example, POSITION
input is the vertex position, and NORMAL
is the vertex normal.
Often, vertex data inputs are declared in a structure, instead of listing them one by one. Several commonly used vertex structures are defined in UnityCG.cginc include file, and in most cases it’s enough just to use those. The structures are:
appdata_base
: el vértice consiste de posición, normal y una coordenada de textura.appdata_tan
: el vértice consiste de posición, tangente, normal y una coordenada de textura.appdata_full
: vértice consiste de posición, tangente, normal, dos texturas de coordenadas y color.Por ejemplo, este sombreador colorea el mesh basado en sus normales y simplemente utiliza appdata_base
como un input al 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 = mul (UNITY_MATRIX_MVP, 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
}
}
}
To access different vertex data, you need to declare the vertex structure yourself, or add input parameters to the vertex shader. Vertex data is identified by Cg/HLSL semantics, and must be from the following list:
POSITION
is the vertex position, typically a float3
or float4
.float4 tangent
es el vector tangente (utilizado para normal mapping)TEXCOORD0
is the first UV coordinate, typically float2
, float3
or float4
.TEXCOORD1
, TEXCOORD2
and TEXCOORD3
are the 2nd, 3rd and 4th UV coordinates, respectively.float4 tangent
es el vector tangente (utilizado para normal mapping)float4 tangent
es el vector tangente (utilizado para normal mapping)When the mesh data contains fewer components than are needed by the vertex
shader input, the rest are filled with zeroes, except for the .w
component which defaults to 1. For example, mesh texture coordinates
are often 2D vectors with just x and y components. If a vertex
shader declares a float4
input with TEXCOORD0
semantic, the
value received by the vertex shader will contain (x,y,0,1).
El siguiente ejemplo del sombreador utiliza una posición del vértice y la primera coordenada de textura como un input del vertex shader (definido en la estructura appdata). Es muy útil depurar coordenadas UV del mesh. Las coordenadas UV son visualizadas como colores rojos y verdes, y las coordenadas afuera del rango 0..1 tienen un tono azul adicional aplicado.
Shader "Debug/UV 1" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, 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
}
}
}
Here, UV coordinates are visualized as red and green colors, while an additional blue tint has been applied to coordinates outside of the 0 to 1 range:
Similarmente, este sombreador visualiza el segundo conjunto UV del modelo:
Shader "Debug/UV 2" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, 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 sombreador utiliza una posición del vértice y colores por-vértice como un input del vertex shader ( definido en la estructura appdata).
Shader "Debug/Vertex color" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, v.vertex );
o.color = v.color;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
El sombreador de a continuación utiliza la posición del vértice y las normales como input del vertex shader (definido en una estructura appdata). Los componentes X,Y,Z de las normales son visualizadas como colores R,G,B. Ya que los componentes de las normales están en un rango –1..1, nosotros los escalamos y los sesgamos para que los colores del output sean mostrados en un rango 0..1.
Shader "Debug/Normals" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, 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 la binormal es derivada de la normal y la tangente.
El siguiente sombreador utiliza la posición del vértice y la tangente como input del vertex shader (definido en una estructura appdata).Los componentes X,Y,Z de la tangente son visualizados en colores R,G,B. Esto se debe a que los componentes de la normal están en un rango –1..1, nosotros los escalamos y los sesgamos para que los colores output se muestren en un rango de 0..1.
Shader "Debug/Tangents" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, v.vertex );
o.color = v.tangent * 0.5 + 0.5;
return o;
}
fixed4 frag (v2f i) : SV_Target { return i.color; }
ENDCG
}
}
}
El siguiente sombreador visualiza las binormales. Utiliza la posición del vértice, normal y la tangente como input del vértice. La binormal es calculada de la normal y la tangente. Como cualquier normal o tangente, esta necesita ser escalada y sesgada a un rango de visualización de 0..1. binormal) is calculated from the normal and tangent values. It needs to be scaled and biased into a displayable 0 to 1 range.
Shader "Debug/Bitangents" {
SubShader {
Pass {
Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 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 = mul( UNITY_MATRIX_MVP, 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
}
}
}