Shader "ShaderStudy/FirstSimpleShader"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert (float4 v : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(v);
}
fixed4 frag () : SV_Target
{
return fixed4(1.0, 1.0, 1.0, 1.0);
}
ENDCG
}
}
}
这是一个最简单的shader.
Shader "ShaderStudy/FirstSimpleShader" 定义了shader的名字,以及在unity中可以被查找到的路径.
SubShader:一个shader中可以定义多个SubShader.程序在运行的时候,会根据运行的环境(如显卡的配置等)来选择第一个可以在目标平台上使用的SubShader来进行渲染.
Pass:一个Pass代表了一次渲染的流程.
接着是CGPROGRAM/ENDCG所包围的CG代码片段.在这个语义块中,我们可以使用Cg/HLSL语音来编写.
后面的两行定义了顶点着色器和片元着色器的名字.
#program vertex vert //#program vertex 代表后面定义的是vertex函数,函数名是vert
#program fragment frag //#program fragment 代表后面定义的是fragment函数,函数名是frag
float4 vert (float4 v : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(v);
}
这是顶点着色器代码,它是逐顶点执行的,也就是模型的每一个顶点都会把自己顶点的数据作为参数调用一遍这个函数.在这个例子中,我们只传入了顶点POSITION参数.这里的POSITION是Cg/HLSL语言中的语义,后面的SV_POSITION也是.这些语义代表了这个参数的含义.如POSITION将会告诉Unity把顶点中的坐标数据填入v传入函数.SV_POSITION将告诉Unity顶点着色器vert输出的float4是模型顶点转换到裁剪空间的坐标,这个数据会作为参数传入fragment片元着色器中.如果没有这些语义的定义,渲染器将完全不知道这些参数是什么,要用什么数据来填充这些参数.顶点着色器中唯一的一行代码是对顶点进行了转换,把模型空间转换到裁剪空间.
fixed4 frag () : SV_Target
{
return fixed4(1.0, 1.0, 1.0, 1.0);
}
片元着色器是逐像素运行的,在顶点着色器中输出的SV_POSITION会进入渲染流程,裁剪完后所有合格的像素都会调用这个函数计算这个像素输出的颜色.它的输出SV_Target告诉Unity把用户的输出颜色存储到一个渲染目标中,这里将输出到默认的帧缓存中.这里我们直接返回了fixed4(1.0, 1.0, 1.0, 1.0),白色.
这就是我们第一个最简单的shader.