vertex阶段数据是怎么来的?
gameobject的Mesh Renderer组件会每一帧把mesh的所有数据信息发往GPU。
这也就是所谓的draw call
。每一次的draw call都会有性能消耗,因此每次向GPU发送一个较大容量的mesh数据比发送若干个小mesh数据更高效。
mesh数据包括三角面列表,每个三角面由3个顶点定义,每个顶点又包含若干属性,这些属性通过vertex输入参数传入vertex shader中后都是可读的。这些参数往往通过语义(semantic
)来指定,比如POSITION,NORMAL,TEXCOORD0,TEXCOORD1,TEXCOORD2,TANGENT,COLOR。
语义详解:
https://docs.unity3d.com/Manual/SL-ShaderSemantics.html
vertex输入参数,及对其进行可视化
vertex的输入参数:
struct vertexInput {
float4 vertex : POSITION; // position (in object coordinates,
// i.e. local or model coordinates)
float4 tangent : TANGENT;
// vector orthogonal to the surface normal
float3 normal : NORMAL; // surface normal vector (in object
// coordinates; usually normalized to unit length)
float4 texcoord : TEXCOORD0; // 0th set of texture
// coordinates (a.k.a. “UV”; between 0 and 1)
float4 texcoord1 : TEXCOORD1; // 1st set of tex. coors.
float4 texcoord2 : TEXCOORD2; // 2nd set of tex. coors.
float4 texcoord3 : TEXCOORD3; // 3rd set of tex. coors.
fixed4 color : COLOR; // color (usually constant)
};
可视化shader:
Shader "My/DebuggingOfShaders"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct vertexInput{
float4 vertex:POSITION;//in object coordinates,i.e. local or model coordinates
float4 tangent:TANGENT;//vector orthogonal to the surface normal
float3 normal:NORMAL;//surface normal vector(in object coordinates,usually normalized to unit length)
float4 texcoord0:TEXCOORD0;//0th set of texture coordinates(a.k.a. "UV", between 0 and 1)
float4 texcoord1:TEXCOORD1;//1st set of tex. coors.
float4 texcoord2:TEXCOORD2;//2nd set of tex. coors.
float4 texcoord3:TEXCOORD3;//3rd set of tex. coors.
fixed4 color:COLOR;//color(usually constant)
};
struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:TEXCOORD0;
};
vertexOutput vert (vertexInput input)
{
vertexOutput output;
output.pos=UnityObjectToClipPos(input.vertex);
output.col=input.texcoord0;
//other possibilities to play with:
//output.col=input.vertex;
//output.col=input.tangent;
//output.col=float4(input.normal,1.0);
//output.col=float4((input.normal+float3(1.0,1.0,1.0))*0.5,1.0);//basicly normal value is between -1 and 1,here map the value to 0 and 1,which can fit color range
//output.col=input.texcoord1;
//output.col=input.color;
return output;
}
fixed4 frag (vertexOutput input) : COLOR
{
return input.col;
}
ENDCG
}
}
}
预定义输入结构体
Unity3D中UnityCG.cginc(Unity->Editor->Data->CGIncludes)中已经预定义了一些常用的输入结构体,包括appdata_base
,appdata_tan
,appdata_full
,appdata_img
。
struct appdata_base {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct appdata_tan {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct appdata_full {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
fixed4 color : COLOR;
// and additional texture coordinates only on XBOX360
};
struct appdata_img {
float4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
};
在shader脚本中只需要通过#include "UnityCG.cginc"
引入该文件,就可以任意使用上述结构了。
一些常识
图片的坐标范围[0,1]
标准化后的法线范围[-1,1]; normal是3纬结构,只有x,y,z值
COLOR范围[0,1],当设置COLOR的值小于0,或者大于1;会分别被设置为0,1