Unity Shader 学习之旅-初探
unity shader 图形图像
美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉
最简单的顶点片元着色器
顶点片元着色器基本结构
Unity Shader基本结构:Shader ,Properties,SubShder,Fallback等。
结构
-
- Shader "ShaderName"{
- Properties{
-
- }
-
- SubShader{
-
- Pass{
-
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
-
-
-
- ENDCG
-
- }
- }
-
- SubShader{
-
- }
-
-
- Fallback "VertexLit"
- }
一个简单的示例
- Shader "UnityShaderBoook/SimplerShader"{
-
-
- 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中没有赋予它更丰富的内容,如法线,纹理等,所以他不会表现出任何深度,阴影等,当然也不会受到光照的影响。
注意:
- POSITION和SV_POSITION都是CG/HLSL中的语义,他们是不可省略的,这些语义用来告诉系统输入值和输出值的含义。POSTION告诉Unity这里将模型的顶点数据传入到v参数,而SV_POSITION则告诉Unity顶点着色器输出的是裁剪空间中的顶点坐标。
- UnityObjectToClipPos(v) 是mul(UNITY_MATRIX_MVP,v)更新后的函数,他是Unity内置函数,用来帮我们进行顶点坐标从模型空间转换到裁剪空间的转换。
- SV_TARGET 是HLSL中的系统语义,它输出的是一个float4类型的变量,它等同于告诉渲染器,把用户的输出颜色存储到一个渲染目标中,有时也使用COLOR代替,考虑到平台的通用性最好使用SV_TARGET。
- 模型空间:模型空间我们可以理解为模型自身的局部坐标,一个模型上的顶点位置信息,都是依托自身的局部坐标的,但当我们把它放到场景中的时候,就需要我们转换这些信息来使用。
- 裁剪空间:可以简单的理解为Unity中摄像机视椎体包围的空间,不在其空间内的信息将会被剔除,保留的信息后续会被投影到屏幕上被看到。
顶点着色器与片元着色器之间通信
片元着色器是无法直接获取陈模型的顶点信息的,这时就需要我们通过使用结构体作为媒介,有顶点着色器向片元着色器传递一些数据,如:模型法线,纹理坐标等。
示例
-
-
- Shader "UnityShaderBoook/vert2frag"{
- Properties {
- _Color ("Color Tint", Color) = (1, 1, 1, 1)
- }
-
- SubShader{
-
-
- Pass{
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- uniform fixed4 _Color;
-
- struct a2v{
- float4 vertex:POSITION;
- float4 normal:NORMAL;
- float4 texcoord:TEXCOORD0;
- };
-
-
- struct v2f{
- float4 pos:SV_POSITION;
- fixed3 color:COLOR0;
- };
-
- v2f vert(a2v v) {
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
- o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
- return o;
- }
-
-
-
- fixed4 frag(v2f i):SV_TARGET{
- fixed3 c = i.color;
- c *= _Color.rgb;
- return fixed4(c, 1.0);
- }
-
- ENDCG
- }
- }
-
-
- }
注意: 顶点着色器是逐个顶点调用的,片元着色器是逐片元调用的。片元着色器中的输入实际是吧顶点着色器的输出插值后得到的结果。