在unityshader中我们可以用三种形式来编写unityshader
1. 表面着色器
需要的代码量少,渲染代价比较大,当unity提供一个表面着色器的时候本质上是背后仍旧转化成对应的顶点片元着色器,表面着色器定义在subshader中并不是pass中,表面着色器不需要我们关心使用多少个pass,每个pass如何渲染,unity背后为我们做了这些事情。
编写表面着色器有几个规则:
1)表面着色器的实现代码需要放在CGPROGRAM..ENDCG代码块中,而不是Pass结构中,它会自己编译到各个Pass。
2)使用#pragma surface..命令来指明它是一个表面着色器。
pragma surface 表面函数光照模型[可选参数]
其中表面函数用来说明哪个Cg函数包含有表面着色器代码,表面函数的形式为:
void surf(Input IN,inoutSurfaceOutPut 0)
光照模型可以是内置的Lambert和BlinnPhong,或者是自定义的光照模型。
表面函数的作用是接收输入的UV或者附加数据,然后进行处理,最后将结构填充到输出结构体SurfaceOutPut中。
SurfaceOut描述了表面的各种参数,它的标准结构为:
struct SurfaceOutput{
half3 Albedo;//反射光
half3 Normal;//法线
half3 Emission;//自发光
half Specular;//高光
half Gloss;//光泽度
half Alpha;//透明度
};
Shader "Custom/Diffuse Simple" {
SubShader{
Tags{"RenderType" = "Opaque"}
CGPROGRAM//表面着色器的实现代码
//指明着色器类型,表面函数和光照模型
#pragma surface surf Lambert
struct Input{//输入的数据结构体
float color : COLOR;
};
void surf(Input IN,inoutSurfaceOutput o){//表面函数
o.Albedo = 1;//输出颜色值
}
ENDCG;
}
Fallback "Diffuse"//备选着色器
}
2. 顶点/片元着色器
与表面着色器一样,顶点片段着色器也需要用Cg/HLSL来编写核心的实现代码,代码用CGPROGRAM ENDCG语句包围起来,放在ShaderLab的Pass命令中,形式如下:
Pass{
//通道设置
CGPROGRAM
//本段Cg代码的编译命令
#pragma vertexvert
#pragma fragment frag
//Cg代码
ENDCG
//其他通道设置
}
3.固定功能管线着色器Fixed Function Shaders
固定功能管线着色器的关键代码一般都在Pass的材质设置Material{}和纹理设置SetTexture{}部分。
Shader "Custom/VertexList" {
Properties {
_Color("Main Color",Color) = (0,1,1,0.5)
_SpecColor("Spec Color",Color) = (1,1,1,1)
_Emission("Emissive Color",Color) = (0,0,0,0)
_Shininess("Shininess",Range(0.01,1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Pass{
Material{
Diffuse[_Color]
Ambient[_Color]
Shininess[_Shininess]
Specular[_SpecColor]
Emission[_Emission]
}
Lighting On
SeparateSpecular On//启用高光颜色
//设置纹理
SetTexture[_MainTex]{
//设置颜色常量
constantColor[_Color]
//混合命令
combine texture * primary DOUBLE,
texture *constant
}
}
}
}
现如今大多数GPU都支持可编程管线,这种固定管线方式已经被逐渐抛弃。
点击关注我的微博,给大家带来欢乐