Unity Shader从入门到**
Shader很简单
一、概念
Shader其实就是专门用来渲染图形的一种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果。小到每一个像素点,大到整个屏幕
Shader分为两类 :
1.顶点Shader(3D图形都是由一个个三角面片组成的,顶点Shader就是计算每个三角面片上的顶点,并为最终像素渲染做准备)。
2.像素Shader,顾名思义,就是以像素为单位,计算光照、颜色的一系列算法。 几个不同的图形API都有各自的Shader语言,在DirectX中,顶点shader叫做 Vertex Shader ,像素Shader叫做 Pixel Shader; 在OpenGL中,顶点Shader也叫做 Vertex Shader ,但像素Shader叫做 Fragment Shader,也就是我们常说的片断Shader或者片元Shader。
Shader编程语言
既然Shader是一段代码,那必然要用一种语言来书写它,目前主流的有三种语言:
基于OpenGL的OpenGL Shading Language,简称GLSL。
基于DirectX的High Level Shading Language,简称HLSL。
还有NVIDIA公司的C for Graphic,简称Cg语言。
GLSL与HLSL分别是基于OpenGL和Direct3D的接口,两者不能混用。而Cg语言是用于图形的C语言,这其实说明了当时设计人员的一个初衷,就是让基于图形硬件的编程变得和C语言编程一样方便,自由。正如C++和 Java的语法是基于C的,Cg语言本身也是基于C语言的。如果您使用过C、C++、Java其中任意一个,那么Cg的语法也是比较容易掌握的。Cg语言极力保留了C语言的大部分语义,力图让开发人员从硬件细节中解脱出来,Cg同时拥有高级语言的好处,如代码的易重用性,可读性高等。
Cg语言是Microsoft和NVIDIA相互协作在标准硬件光照语言的语法和语义上达成了一致,所以,HLSL和Cg其实是同一种语言。
二、学习笔记
1.结构
基本的结构
Shader "MyFirstShader"
{
Properties//属性
{
}
SubShaders//子shader块(shader逻辑处理块,可以有多个)
{
}
FallBack "Diffuse"//备用材质
CutomEditor "EditorName"//自定义界面
}
1.1.属性
格式
[Attribute]_Name ("Display Name",Type) = Default Value
//[ 标记 ] 变量名("面板上的显示名",类型)= 默认值
1.1.1属性类型
①.Color颜色
_Color("我是Color",color) = (1,1,1,1)
②.Int整数
//(面板中即便可以输入小数,shader也只取其整数部分)
_Int("我是Int",Int) = 1
③.Float浮点数
_Float("我是Float",Float) = 0.5
Float相关标记
//[Range]:限制参数范围
_Float("我是Float", Range( 0 , 1)) = 0.5
//[IntRange]:向下取整
[IntRange]_Float("我是Float", Range( 0 , 1)) = 1
//[Toggle]:开关(0代表关,1代表开)
[Toggle]_Float("我是Float", Range( 0 , 1)) = 1
//[Enum]下拉列表
[Enum(UnityEngine.Rendering.CullMode)]_Float("我是Float", Float) = 1
④.Vector四维数
_Vector("我是Vector",Vector) = (0,0,0,0)
⑤.2D纹理
_MainTex("我是2D纹理",2D) = "white" {}
2D纹理相关标记
//[NoScaleOffset]:隐藏掉Tiling(贴图重复度)和Offest(贴图偏移值)参数
[NoScaleOffset]_MainTex("我是2D纹理", 2D) = "white" {}
//[Normal]:指定参数为法线贴图
[Normal]_MainTex("我是2D纹理", 2D) = "white" {}
//默认值
//white 白
//black 黑
//gray 灰
//bump 法线图
⑥.3D纹理
_MainTex("我是3D纹理",3d) = "" {}
⑦.Cube立方体纹理
_MainTex("我是Cube纹理", CUBE) = "" {}
通用属性标记
//[Header]:属性说明,使用后会在面板中参数上方出现文本
[Header(This is Header )]_Int("我是Int", Int) = 1
1.2 SubShaders 里有什么
1.2.1 Pass
Pass的意思就是:渲染一次模型
1.一个Shader中,至少有一个SubShader
2.每个SubShaders 至少有一个 Pass
1.2.2 Pass里有什么
1.2.2.1 .CGPROGRAM 和ENDCG
每个Pass里必须有CGPROGRAM 和ENDCG,代码就写在CGPROGRAM 和ENDCG中间
1.2.2.2 #pragma
声明的顶点着色器与片断着色器
关键词 #pragma
//定义顶点着色器为name,通常情况下会起名为vert。
#pragma vertex name
//定义片断着色器为name,通常情况下会起名为frag。
#pragma fragment name
1.2.2.3 实现声明
float4 vert ( float4 vertex : POSITION ) : SV_POSITION
{
return UnityObjectToClipPos(vertex);
}
fixed4 frag () : SV_Target
{
return _Color;
}
完整shader
Shader "Unlit/MyFirstShader"
{
Properties
{
_Color("Color", Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
float4 vert ( float4 vertex : POSITION ) : SV_POSITION
{
return UnityObjectToClipPos(vertex);
}
fixed4 frag () : SV_Target
{
return _Color;
}
ENDCG
}
}
}
ENDCG
1.2.2.4属性的使用
//再次声明
fixed4 _Color;
开头我们定义过一个属性_Color,但是想要在pass里使用,就需要再声明一次,名字要和上边一致
关键词用的fixed4,代表四维向量
Cg/HLSL中声明属性的常用关键词有以下几种
float
//高精度类型,32位,通常用于世界坐标下的位置,纹理UV,或涉及复杂函数的标量计算,如三角函数、幂运算等。
half
//中精度类型,16位,数值范围为[-60000,+60000],通常用于本地坐标下的位置、方向向量、HDR颜色等。
fixed
//低精度类型,11位,数值范围为[-2,+2],通常用于常规的颜色与贴图,以及低精度间的一些运算变量等。
//在PC平台不管你Shader中写的是half还是fixed,统统都会被当作float来处理。half与fixed仅在一些移动设备上有效。
//比较常用的一个规则是,除了位置和坐标用float以外,其余的全部用half。主要原因也是因为大部分的现代GPU只支持32位与16位,也就是说只支持float和half,不支持fixed。
interger
//整型类型,通常用于循环与数组的索引。
//在 Direct3D 9 和 OpenGL ES 2.0平台上整型可能会被直接用浮点数来处理,在Direct3D 11、OpenGL ES 3等现代GPU上可以正确的以整型类型来处理。
sampler2D、sampler3D与samplerCUBE
//纹理,默认情况下在移动平台纹理会被自动转换成低精度的纹理类型,如果你需要中精度的或者高精度的需要用以下方式来声明:
sampler2D_half(中精度2D纹理)
sampler2D_float(高精度2D纹理)
sampler3D_half(中精度3D纹理)
sampler3D_float(高精度3D纹理)
samplerCUBE_halft(中精度立方体纹理)
samplerCUBE_float(高精度立方体纹理)
1.2.2 struct
关键字:struct
作用:存放变量
调用:结构体名+“.”+变量名
struct appdata{
float4 vertex:POSITION;
}
//还可以定义这些语义的变量
struct appdata
{
float4 vertex : POSITION; //顶点
float4 tangent : TANGENT; //切线
float3 normal : NORMAL; //法线
float4 texcoord : TEXCOORD0; //UV1
float4 texcoord1 : TEXCOORD1; //UV2
float4 texcoord2 : TEXCOORD2; //UV3
float4 texcoord3 : TEXCOORD3; //UV4
fixed4 color : COLOR; //顶点色
};
1.2.3 自定义函数
fixed checker(float2 uv)
{
float2 repeatUV = uv*10;
float2 c = fliir(repeatUV)/2;
float checker = frac(c.x+c.y)*2;
return checker;
}
自定义函数在代码中的调用
Shader "Unlit/MyFirstShader"
{
Properties
{
_Color("Color", Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
fixed4 _Color;
struct appdata
{
float4 vertex:POSITION;
float2 uv:TEXCOORO;
};
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORO;
};
float4 vert ( float4 vertex : POSITION ) : SV_POSITION
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
o.uv = v.uv;
return o;
}
foxed checker(float2 uv)
{
float2 repeatUV = uv*10;
float2 c = floor(repeatUV)/2;
float checker = frac(c.x+c.y)*2;
return checker;
}
fixed4 frag (v2f i) : SV_Target
{
fixed col = checker(i.uv);
return col;
}
ENDCG
}
}
}
ENDCG
//关于片段着色器的语义
Shader "Unlit/MyFirstShader"
{
Properties
{
_FrontTex("FrontTex", 2d) = "white"{}
_BackTex("BackTex", 2d) = "white"{}
}
SubShader
{
cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
sampler2D _FrontTex;
sampler2D _BackTex;
struct appdata
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=v.texcoord;
return o;
}
fixed4 frag (v2f i,float face:VFACE) : SV_Target
{
fixed4 col=1;
col = face > 0 ? tex2D(_FrontTex,i.uv) : tex2D(_BackTex,i.uv);
return col;
}
ENDCG
}
}
}
1.2.2 SubShader Tags
SubShader中的Tags必须放置于SubShader中的Tags内,具体参数有以下这些:
1.Queue
//渲染队列,指定对象什么时候渲染,每个队列其实都是利用一个整数进行索引的。
有以下取值:
Background
//值为1000,此队列的对象最先进行渲染。
Geometry
//Queue的默认值,值为2000,通常用于不透明对象,比如场景中的物件与角色等。
AlphaTest
//值为2450,要么完全透明要么完全不透明,多用于利用贴图来实现边缘透明的效果,也就是美术常说的透贴。
Transparent
//值为3000,常用于半透明对象,渲染时从后往前进行渲染,建议需要混合的对象放入此队列。
Overlay
//值为4000,此渲染队列用于叠加效果。最后渲染的东西应该放在这里(例如镜头光晕等)。
例
Tags{ "Queue" = "Geometry" }
//↓自定义渲染队列:
Tags{ "Queue" = "Geometry+1" }
2.RenderType
自带的值有以下这些:
Opaque
Transparent
TransparentCutout
Background
Overlay
TreeOpaque
TreeTransparentCutout
TreeBillboard
Grass
GrassBillboard
原文链接:https://zhuanlan.zhihu.com/p/46745694