从前面三节课了解的shader基础概念以及结构 可以写出下面的基本着色器代码
Shader "UnityShader/Basic_Unlit"{
//编辑器显示属性
Properties
{
_Color("Tint",Color) = (0,0,0,1)
_MainTex("Texture",2D)="white"{}
}
SubShader
{
//这个材质完全不透明 并且与其他不透明的几何体同时渲染
Tags{"RenderType" = "Opaque" "Queue" = "Geometry"}
Pass
{
CGPROGRAM
//纹理以及纹理变换
sampler2D _MainTex;
float4 _MainTex_ST;
//纹理着色
fixed4 _Color;
//顶点着色器读取的网格数据
struct appdata
{
float4 vertex:POSITION;
float2 uv : TEXCOORD0;
};
//从顶点传递到片段着色器的数据同时被光栅化插值
struct v2f
{
float4 position:SV_POSITION;
float2 uv: TEXCOORD0;
};
ENDCG
}
}
Fallback "VertextLit"
}
创建着色阶段
每一个着色阶段表示为一个hlsl方法 要定义程序中哪个函数代表什么阶段,还需要在程序中添加#pragma语句。对于顶点阶段很重要的是,它获取顶模型点数据并返回插值器。对于片段阶段来说,重要的是,它吸收插值器并返回写入渲染目标的向量。
//定义顶点片段着色器方法
#pragma vertex vert
#pragma fragment frag
//顶点着色器方法
v2f vert(appdata v)
{
//顶点着色器阶段处理
}
//片段着色器方法
fixed4 frag(v2f i):SV_TARGET
{
//片段着色器代码
}
顶点着色器处理阶段
在定义顶点阶段的函数的开头,我们创建将在最后返回的插值器结构。然后,我们将其填充数据并返回。顶点阶段的主要工作是将顶点位置从局部模型空间转换为可以渲染它们的剪贴空间。这是通过矩阵乘法在内部完成的,但是我们不必理解,因为Unity给了我们函数,可以为我们做矩阵乘法。要在我们的着色器中使用这些宏(以及许多其他有用的代码),我们通过#include“ UnityCG.cginc”导入一个包含文件。将位置从本地空间转换为剪辑空间的函数称为UnityObjectToClipPos。 UnityCG文件还具有一个宏(类似于函数),可帮助我们将与顶点数据一起传递的uv坐标转换为遵守我们在编辑器中设置的平铺和偏移量的uv坐标,它名为TRANSFORM_TEX并采用基本uv坐标以及纹理名称作为参数。
应用该代码后,顶点函数应如下所示:
//顶点着色器方法
v2f vert(appdata v)
{
//顶点着色器阶段处理
v2f o;
//将顶点位置信息从模型空间转换到剪切空间
o.position = UnityObjectToClipPos(v.vertex);
//将纹理变换应用于UV坐标,并将其传递给v2f结构
o.uv = TRANSFORM_TEX(v.uv,_MainTex);
return o;
}
片段着色器处理阶段
在片段化阶段,我们使用插值器,并使用它们和uniform datat来确定像素应具有的颜色。 最简单的版本可以是return float4(1,1,1,1); 对于完全白色的网格,但是在大多数情况下,我们想使用稍微复杂一点的结果并使用纹理。为了访问纹理,我们通常使用tex2D函数,该函数将纹理作为第一个参数,将uv坐标作为第二个参数,然后返回该坐标处的颜色。 在此示例中,我们将保存结果颜色,将其与定义为uniform data的颜色相乘,然后返回结果。
//片段着色器方法
fixed4 frag(v2f i):SV_TARGET
{
//片段着色器代码
//读取纹理在uv坐标处的颜色
fixed4 col = tex2D(_MainTex,i,uv);
//纹理颜色乘以定义的着色颜色_Color
col*=_Color;
//返回最终在显示器绘制的颜色
return col;
}
最终得到第一个最基本的着色器如下
Shader "UnityShader/Basic_Unlit"{
//编辑器显示属性
Properties
{
_Color("Tint",Color) = (0,0,0,1)
_MainTex("Texture",2D)="white"{}
}
SubShader
{
//这个材质完全不透明 并且与其他不透明的几何体同时渲染
Tags{"RenderType" = "Opaque" "Queue" = "Geometry"}
Pass
{
CGPROGRAM
//纹理以及纹理变换
sampler2D _MainTex;
float4 _MainTex_ST;
//纹理着色
fixed4 _Color;
//顶点着色器读取的网格数据
struct appdata
{
float4 vertex:POSITION;
float2 uv : TEXCOORD0;
};
//从顶点传递到片段着色器的数据同时被光栅化插值
struct v2f
{
float4 position:SV_POSITION;
float2 uv: TEXCOORD0;
};
#include "UnityCG.cginc"
//定义顶点片段着色器方法
#pragma vertex vert
#pragma fragment frag
//顶点着色器方法
v2f vert(appdata v)
{
//顶点着色器阶段处理
v2f o;
//将顶点位置信息从模型空间转换到剪切空间
o.position = UnityObjectToClipPos(v.vertex);
//将纹理变换应用于UV坐标,并将其传递给v2f结构
o.uv = TRANSFORM_TEX(v.uv,_MainTex);
return o;
}
//片段着色器方法
fixed4 frag(v2f i):SV_TARGET
{
//片段着色器代码
//读取纹理在uv坐标处的颜色
fixed4 col = tex2D(_MainTex,i.uv);
//纹理颜色乘以定义的着色颜色_Color
col*=_Color;
//返回最终在显示器绘制的颜色
return col;
}
ENDCG
}
}
Fallback "VertextLit"
}