Shader Learing(ShaderLab syntax篇)

Shader Learing(ShaderLab syntax篇)

回顾:
回顾Unity中,数据的传递及Shader的工作原理:



从上图我们可以看出,在渲染管线中,顶点着色器输入的数据经过顶点着色器后,顶点着色器会把相关数据传递给片段着色器,上图即表明了在Unity的顶点着色器和片段着色器中数据的传递类型和传递方向。

/*
齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点
同时也更易用于进行仿射(线性)几何变换。
*/
Shader "Custom/004_RGBCube" {
	SubShader { 
		Pass { 
        CGPROGRAM 
        #pragma vertex vert // vert function is the vertex shader 
        #pragma fragment frag // frag function is the fragment shader
        // for multiple vertex output parameters an output structure 
        // is defined:
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 col : TEXCOORD0;
        };
		//POSITION语意用于顶点着色器,用来指定这些个位置坐标值,是在变换前的顶点的object space坐标。
		//SV_POSITION语意则用于像素着色器,用来标识经过顶点着色器变换之后的顶点坐标。
        vertexOutput vert(float4 vertexPos : POSITION) 
        // vertex shader 
        {
           vertexOutput output; // we don't need to type 'struct' here
           output.pos =  mul(UNITY_MATRIX_MVP, vertexPos);
           output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0);
              // Here the vertex shader writes output data
              // to the output structure. We add 0.5 to the 
              // x, y, and z coordinates, because the 
              // coordinates of the cube are between -0.5 and
              // 0.5 but we need them between 0.0 and 1.0. 
            return output;
        }
        float4 frag(vertexOutput input) : COLOR // fragment shader
        {
            return input.col; 
              // Here the fragment shader returns the "col" input 
              // parameter with semantic TEXCOORD0 as nameless
              // output parameter with semantic COLOR.
        }
        ENDCG  
      }
   }
}

ShaderBuilt-in Vertex Input:
我们知道Unity Shader编程中,可以使用结构体来把顶点输入数据,如上面的示例,其实在Unity Shader编程中,有很多内建的结构体可以让我们很方便的使用,下面使用Unity内建的结构体实现上面的示例:

Shader "Custom/005_Build_InShader" {
	SubShader { 
      Pass { 
         CGPROGRAM 
        #pragma vertex vert  
        #pragma fragment frag 
        #include "UnityCG.cginc"
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 col : TEXCOORD0;
        };
        vertexOutput vert(appdata_full input) 
        {
           vertexOutput output;
           output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
           output.col = input.texcoord;

           return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
           return input.col; 
        }
        ENDCG  
     }
   }
}

/*
struct vertexInput {
         float4 vertex : POSITION; // position (in object coordinates, 
								 // i.e. local or model coordinates)
         float4 tangent : TANGENT;  
								// vector orthogonal to the surface normal
         float3 normal : NORMAL; // surface normal vector (in object
								// coordinates; usually normalized to unit length)
         float4 texcoord : TEXCOORD0;  // 0th set of texture 
									// coordinates (a.k.a. “UV”; between 0 and 1) 
         float4 texcoord1 : TEXCOORD1; // 1st set of tex. coors. 
         float4 texcoord2 : TEXCOORD2; // 2nd set of tex. coors. 
         float4 texcoord3 : TEXCOORD3; // 3rd set of tex. coors. 
         fixed4 color : COLOR; // color (usually constant)
      };
	预定义结构体:
	pre-defined input structures appdata_base, appdata_tan, appdata_full
	and appdata_img for the most common cases. 
	These are defined in the file UnityCG.cginc 
	(in the directory Unity > Editor > Data > CGIncludes):

	struct appdata_base {
      float4 vertex : POSITION;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
	};
	struct appdata_tan {
      float4 vertex : POSITION;
      float4 tangent : TANGENT;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
    };
    struct appdata_full {
      float4 vertex : POSITION;
      float4 tangent : TANGENT;
      float3 normal : NORMAL;
      float4 texcoord : TEXCOORD0;
      float4 texcoord1 : TEXCOORD1;
      float4 texcoord2 : TEXCOORD2;
      float4 texcoord3 : TEXCOORD3;
      fixed4 color : COLOR;
      // and additional texture coordinates only on XBOX360
    };
    struct appdata_img {
      float4 vertex : POSITION;
      half2 texcoord : TEXCOORD0;
    };
*/

uniform:
uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。

Shader "Custom/006_Uniforms" {
	SubShader {
      Pass {
         CGPROGRAM
        #pragma vertex vert  
        #pragma fragment frag 
        // uniform float4x4 _Object2World; 
        // automatic definition of a Unity-specific uniform parameter
        struct vertexInput {
           float4 vertex : POSITION;
        };
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 position_in_world_space : TEXCOORD0;
        };
        vertexOutput vert(vertexInput input) 
        {
            vertexOutput output; 
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.position_in_world_space = 
               mul(_Object2World, input.vertex);
               // transformation of input.vertex from object 
               // coordinates to world coordinates;
            return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
            float dist = distance(input.position_in_world_space, 
            float4(0.0, 0.0, 0.0, 1.0));
               // computes the distance between the fragment position 
               // and the origin (the 4th coordinate should always be 
               // 1 for points).
            if (dist < 5.0)
            {
               return float4(0.0, 1.0, 0.0, 1.0); 
                  // color near origin
            }
            else
            {
               return float4(0.1, 0.1, 0.1, 1.0); 
                  // color far from origin
            }
        }
        ENDCG  
      }
   }
}
/*
uniform float4 _Time, _SinTime, _CosTime; // time values
   uniform float4 _ProjectionParams;
							  // x = 1 or -1 (-1 if projection is flipped)
							  // y = near plane; z = far plane; w = 1/far plane
   uniform float4 _ScreenParams; 
					    // x = width; y = height; z = 1 + 1/width; w = 1 + 1/height
   uniform float3 _WorldSpaceCameraPos;
   uniform float4x4 _Object2World;      // model matrix
   uniform float4x4 _World2Object;     // inverse model matrix 
   uniform float4 _WorldSpaceLightPos0; 
   // position or direction of light source for forward rendering

   uniform float4x4 UNITY_MATRIX_MVP;   // model view projection matrix 
   uniform float4x4 UNITY_MATRIX_MV;   // model view matrix
   uniform float4x4 UNITY_MATRIX_V;   // view matrix
   uniform float4x4 UNITY_MATRIX_P;   // projection matrix
   uniform float4x4 UNITY_MATRIX_VP;   // view projection matrix
   uniform float4x4 UNITY_MATRIX_T_MV; 
      // transpose of model view matrix
   uniform float4x4 UNITY_MATRIX_IT_MV; 
      // transpose of the inverse model view matrix
   uniform float4 UNITY_LIGHTMODEL_AMBIENT; // ambient color
   */

Uniform应用的第二个示例:

Shader "Custom/007_UserSpecifiedUniforms" {
	Properties {
    _Point ("a point in world space", Vector) = (0., 0., 0., 1.0)
    _DistanceNear ("threshold distance", Float) = 5.0
    _ColorNear ("color near to point", Color) = (0.0, 1.0, 0.0, 1.0)
    _ColorFar ("color far from point", Color) = (0.3, 0.3, 0.3, 1.0)
   }
   SubShader {
      Pass {
        CGPROGRAM
        #pragma vertex vert  
        #pragma fragment frag 
        #include "UnityCG.cginc" 
            // defines _Object2World and _World2Object
         // uniforms corresponding to properties
        uniform float4 _Point;
        uniform float _DistanceNear;
        uniform float4 _ColorNear;
        uniform float4 _ColorFar;
        struct vertexInput {
           float4 vertex : POSITION;
        };
        struct vertexOutput {
           float4 pos : SV_POSITION;
           float4 position_in_world_space : TEXCOORD0;
        };
        vertexOutput vert(vertexInput input) 
        {
            vertexOutput output; 
            output.pos =  mul(UNITY_MATRIX_MVP, input.vertex);
            output.position_in_world_space = 
               mul(_Object2World, input.vertex);
            return output;
        }
        float4 frag(vertexOutput input) : COLOR 
        {
            float dist = distance(input.position_in_world_space, 
               _Point);
               // computes the distance between the fragment position 
               // and the position _Point.
            
            if (dist < _DistanceNear)
            {
               return _ColorNear; 
            }
            else
            {
               return _ColorFar; 
            }
        }
        ENDCG  
      }
   }
}

/*
Shader的属性可以在脚本中被使用:
eg:
GetComponent(Renderer).sharedMaterial.SetVector("_Point", 
      Vector4(1.0, 0.0, 0.0, 1.0));
   GetComponent(Renderer).sharedMaterial.SetFloat("_DistanceNear", 
      10.0);
   GetComponent(Renderer).sharedMaterial.SetColor("_ColorNear", 
      Color(1.0, 0.0, 0.0));
   GetComponent(Renderer).sharedMaterial.SetColor("_ColorFar", 
      Color(1.0, 1.0, 1.0));
*/

这样,我们可以通过持有属性来达到修改的目的。
Pass(通道):RenderSetup+固定功能着色器命令
Unity中一个SubShader(渲染方案)是由一个个Pass块来执行的。每个Pass都会消耗对应的一个DrawCall。在满足渲染效果的情况下尽可能地减少Pass的数量。
Pass(通道编程)
1个Pass块可以使一个几何物体被一次渲染。
Pass { [Name and Tags] [RenderSetup] [TextureSetup] }
最基础的pass命令包含有1个可选的渲染设置命令列表,及1个可选的可用纹理列表。
一个Pass 可以定义它的名字和任意数量的标签-name/value 字符串 将Pass的含义告诉给渲染引擎。

Render Setup 渲染设置
Pass设置了一系列的显卡状态,比如说alpha混合是否开启,是否允许雾化等等。 这些命令有:


①Color color

Shader "Custom/NewShader" {
	SubShader {
        Pass { Color (1,0,0,0) }  //将对象设置为固体颜色
    }
}

②Material {Material Block}  定义一个使用顶点光照管线的材质

Shader "Custom/NewShader" {
	SubShader {
        Pass {
            Material {  //材质块用于定义对象的材质属性
                Diffuse (1,1,1,1)
                Ambient (1,1,1,1)
            }
            Lighting On
        }
    }
}

③Lighting On|Off     开启或关闭顶点光照

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", COLOR) = (1,1,1,1)
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
                Ambient [_Color]
            }
            Lighting On
 //对于在材质块中定义的设置有任何影响,您必须启用灯光与灯光的命令。如果灯光是关闭的,颜色是直接从颜色命令。
        }
    }
}

④SeparateSpecular On|Off  此命令使镜面照明添加到着色通道的末端,所以镜面照明不受纹理的影响。
⑤ColorMaterial AmbientAndDiffuse|Emission  使用每个顶点颜色代替材质中设置的颜色。

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]//Diffuse color: 漫反射颜色分量。这是一个对象的基本颜色。
                Ambient [_Color]//Ambient color: 环境颜色分量。这是对象的颜色,在照明窗口中被环境光照射
                Shininess [_Shininess]//Shininess number: 突出的清晰度,在1和0之间
                Specular [_SpecColor]//Specular color: 对象的高光的颜色
                Emission [_Emission]//Emission color: 物体不被任何光线击中时的颜色
            }
            Lighting On
            SeparateSpecular On
            SetTexture [_MainTex] {
                Combine texture * primary DOUBLE, texture * primary
            }
        }
    }
}



⑥Cull Back|Front|Off     设置多边形剔除模式,控制多边形应该剔除(不绘制)的面

Shader "Custom/NewShader" {  //对象只渲染对象的背面
  SubShader {
        Pass {
            Material {
                Diffuse (1,1,1,1)
            }
            Lighting On
            Cull Front
        }
    }
}

⑦ZWrite On|Off     设置深度写模式,控制像素从这个对象是否写入深度缓冲

Shader "Custom/NewShader" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader {
    Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    LOD 200
    // extra pass that renders to depth buffer only
    Pass {
        ZWrite On     // 开启深度缓冲写
        ColorMask 0   //关闭所有渲染染色通道
    }
    // paste in forward rendering passes from Transparent/Diffuse
    UsePass "Transparent/Diffuse/FORWARD"
}
//Fallback "Transparent/VertexLit"
}

⑧ZTest Less|Greater|LEqual|GEqual|Equal|NotEqual|Always     设置深度测试模式
⑨Offset Factor, Units     允许您指定两个参数的深度偏移量

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }
    SubShader {
        // We use the material in many passes by defining them in the subshader.
        // Anything defined here becomes default values for all contained passes.
        Material {
            Diffuse [_Color]
            Ambient [_Color]
            Shininess [_Shininess]
            Specular [_SpecColor]
            Emission [_Emission]
        }
        Lighting On
        SeparateSpecular On
        // Set up alpha blending
        Blend SrcAlpha OneMinusSrcAlpha
        // Render the back facing parts of the object.
        // If the object is convex, these will always be further away
        // than the front-faces.
        Pass {
            Cull Front
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
        // Render the parts of the object facing us.
        // If the object is convex, these will be closer than the
        // back-faces.
        Pass {
            Cull Back
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
    }
}


⑩SetTexture [TextureName] {Texture Block}

Shader "Custom/NewShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }
    SubShader {
        // Render the front-facing parts of the object.
        // We use a simple white material, and apply the main texture.
        Pass {
            Material {
                Diffuse (1,1,1,1)
            }
            Lighting On
            SetTexture [_MainTex] {
                Combine Primary * Texture
            }
        }
        // Now we render the back-facing triangles in the most
        // irritating color in the world: BRIGHT PINK!
        Pass {
            Color (1,0,1,1)
            Cull Front
        }
    }
}
//传统的纹理合成
//Previous 是之前SetTexture的结果。        
//Primary 是从照明计算或顶点颜色的颜色。    
//Texture 纹理是在SetTexture TextureName指定纹理的颜色(见上图)。
//Constant 是ConstantColor指定的颜色。

⑪SetTexture [_MainTex] { combine previous * texture, previous + texture }
⑫Fog {Fog Commands}     设置雾参数
⑬Mode Off|Global|Linear|Exp|Exp2
⑭Color ColorValue
⑮Density FloatValue
⑯Range FloatValue, FloatValue


⑰AlphaTest Off     开启alpha测试
⑱AlphaTest comparison AlphaValue

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (.5, .5, .5, .5)
        _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
        _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5
    }
    SubShader {
        // Set up basic lighting
        Material {
            Diffuse [_Color]
            Ambient [_Color]
        }
        Lighting On
        // Render both front and back facing polygons.
        Cull Off
        // first pass:
        // render any pixels that are more than [_Cutoff] opaque
        Pass {
            AlphaTest Greater [_Cutoff]
            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }
        // Second pass:
        // render in the semitransparent details.
        Pass {
            // Dont write to the depth buffer
            ZWrite off
            // Don't write pixels we have already written.
            ZTest Less
            // Only render pixels less or equal to the value
            AlphaTest LEqual [_Cutoff]
            // Set up alpha blending
            Blend SrcAlpha OneMinusSrcAlpha
            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }
    }
}


⑲Blend Off     设置α混合模式

Blend SrcFactor DstFactor
Blend SrcFactor DstFactor, SrcFactorA DstFactorA
BlendOp BlendOp

Shader "Custom/NewShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Transparency (A)", 2D) = "white" {}
        _Reflections ("Base (RGB) Gloss (A)", Cube) = "skybox" { TexGen CubeReflect }
    }
    SubShader {
        Tags { "Queue" = "Transparent" }
        Pass {
            Blend SrcAlpha OneMinusSrcAlpha
            Material {
                Diffuse [_Color]
            }
            Lighting On
            SetTexture [_MainTex] {
                combine texture * primary double, texture * primary
            }
        }
        Pass {
            Blend One One
            Material {
                Diffuse [_Color]
            }
            Lighting On
            SetTexture [_Reflections] {
                combine texture
                Matrix [_Reflection]
            }
        }
    }
}

Per-pixel Lighting 逐像素光照
逐像素光照管道的工作依赖于渲染对象在多个pass中。Unity3D一旦获得环境光和任何顶点的光照就开始渲染物体。然后,它在一个单独添加的pass中影响渲染的物体每1个光照的像素。
Per-vertex Lighting 逐顶点光照
逐顶点光照是Direct3d/OpenGl的标准光照模式,它的计算依赖于每一个顶点。打开光照后才能启动逐顶点光照。光照受Materialblock, ColorMaterial 和 SeparateSpecular命令影响。 
有几个特殊的pass可以重用公共的功能或实现一些高级效果。
UsePass 包含从另外的Shader中已被命名的pass。
GrabPass 抓取屏幕内容并转换成纹理,可以给之后的pass使用,用来做特效最好了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值