Unity Shader基础练习(三)CG入门

区分Unity 中3大Shader

没有嵌套CG语言,也就是代码段中没有CGPROGARAM和ENDCG关键字的,就是固定功能着色器。
嵌套了CG语言,代码段中有surf函数的,就是表面着色器。
嵌套了CG语言,代码段中有#pragma vertex name和 #pragma fragment frag声明的,就是顶点着色器&片段着色器。
从这里开始不加;会报错

Shader "Sbin/vf" {
    
    SubShader {
        pass{
        //CG代码写到限定范围内
        CGPROGRAM
        //CG类似类的声明 都要小写不然不报错也不显示
        #pragma vertex vert  
        #pragma fragment frag
        //顶点    //变量 传入 2阶向量 //传出一个四阶 pos
        void vert(in float2 objPos:POSITION,out float4 pos:POSITION)
        {
          pos=float4(objPos,0,1);
        }
        //COLOR=COLOR0
        void frag(out float4 col:COLOR0)
        {
          col=float4(1,0,0,1);
        }
        ENDCG
        }
    }

}
image.png

然后成了这样 说是以后再解释 我的Game视图什么也看不见 视屏却有


image.png
Shader "Sbin/vf" {
    
    SubShader {
        pass{
        //CG代码写到限定范围内
        CGPROGRAM
        //CG类似类的声明 都要小写不然不报错也不显示
        #pragma vertex vert  
        #pragma fragment frag
        //顶点    //变量 传入 2阶向量 //传出一个四阶 pos
        void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
        {
          pos=float4(objPos,0,1);
          col=float4(0,0,1,1);//也可以这样赋值 不过frag里的col赋值会覆盖这个
        }
        //COLOR=COLOR0 片段着色器
        void frag(inout float4 col:COLOR)
        {       
          col=float4(0,1,0,1);
        }
        ENDCG
        }
    }

}

还是显示不出来 运行会报错但是不知道哪里错了
找到原因了


image.png

把matrail的渲染队列调为transparent


image.png

然后就Game视图有图了 但是还是运行会报
image.png

image.png

右边显示没有错误 很神奇
这是人家视频的效果


image.png
Shader "Sbin/vf" {

    SubShader{
        pass {
        //CG代码写到限定范围内
        CGPROGRAM
            //CG类似类的声明 都要小写不然不报错也不显示
            #pragma vertex vert  
            #pragma fragment frag
            //顶点    //变量 传入 2阶向量 //传出一个四阶 pos
            void vert(in float2 objPos:POSITION,out float4 pos : POSITION,out float4 col : COLOR)
            {
              pos = float4(objPos,0,1);
              col = pos;//也可以这样赋值 不过frag里的col赋值会覆盖这个
            }
        //COLOR=COLOR0 片段着色器
        void frag(inout float4 col:COLOR)
        {
          //col = float4(0,1,0,1);
        }
        ENDCG
        }
    }

}
image.png

我换了2018版本的就好了但是图是反过来的

CG基本数据类型

float half fixed bool int sampler*
顶点和片段profile是某硬件可支持的预算的一种特性

Shader "Sbin/vf" {

    SubShader{
        pass {
        //CG代码写到限定范围内
        CGPROGRAM
            //CG类似类的声明 都要小写不然不报错也不显示
            #pragma vertex vert  
            #pragma fragment frag
            //顶点    //变量 传入 2阶向量 //传出一个四阶 pos
            void vert(in float2 objPos:POSITION,out float4 pos : POSITION,out float4 col : COLOR)
            {
              pos = float4(objPos,0,1);
              col = pos;//也可以这样赋值 不过frag里的col赋值会覆盖这个
            }
        //COLOR=COLOR0 片段着色器
        void frag(inout float4 col:COLOR)
        {
          //col = float4(0,1,0,1);
          
          fixed r=-0.5;
          fixed g=-0.5;
          fixed b=0;
          fixed a=0;
          //CG里的构造器 
          col=float4(r,g,b,a);
          //CG的基本类型 根据不同精度定义的数据类型 CG不含有指针
          //fixed1=fixed 描述的是9位整数被规格化到-1到1 就是2的8次方 256跟颜色的最大值对应
          //fixed2=fixed(1,0);
          //float可以变为float2 float3 float4 没有五阶
          //half half2 half3 half4
          //fixed fixed2 fixed3 fixed4
        }
        ENDCG
        }
    }

}
![image.png](https://upload-images.jianshu.io/upload_images/15146729-5666734f1a3c801e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
官方已经到了5.0 DX11
Shader "Sbin/vf" {

    SubShader{
        pass {
        //CG代码写到限定范围内
        CGPROGRAM
            #include "UnityCG.cginc"
        //CG类似类的声明 都要小写不然不报错也不显示
            #pragma vertex vert  
            #pragma fragment frag
            //定义宏
            #define MACROFL FL4(fl4.ab,fl3.zy);
            typedef float4 FL4;//声明别名
           //结构体  2018新版本不能为空
            struct v2f{
                  float4 pos:POSITION;
                  float2 uv:TEXCOORD0;
              };
            //顶点    //变量 传入 2阶向量 //传出一个四阶 pos
        void vert(in float2 objPos:POSITION,out float4 pos : POSITION,out float4 col : COLOR)
        {
              pos = float4(objPos,0,1);
              col = pos;//也可以这样赋值 不过frag里的col赋值会覆盖这个

        }
        //COLOR=COLOR0 片段着色器
        void frag(inout float4 col:COLOR)
        {
          //col = float4(0,1,0,1);
          
          fixed r=-0.5;
          fixed g=-0.5;
          fixed b=0;
          fixed a=0;
          //CG里的构造器 
          col=float4(r,g,b,a);

          bool bl=false;
          col=bl?col:fixed4(0,1,0,1);//true是黑 false是绿

          //int 一般会被当作float使用
          //描述是几维向量
          float2 fl2=float2(1,0);
          float3 fl3=float3(1,0,1);
          float4 fl4=float4(1,1,0,1);
          
          //Swizzle操作 
          //float4 fl=float4(fl2,0,1);//红色
          //float4 fl=float4(fl2.xy,0,1);//xyzw 或者 rgba按照一定顺序去取可以截取这个值
          //float4 fl=float4(fl4.wzyx);//紫色
           //float4 fl=float4(fl4.ab,fl3.zy);//紫色
            //宏的使用
           FL4 fl=MACROFL //紫色
           col=fl;

          //CG的基本类型 根据不同精度定义的数据类型 CG不含有指针
          //fixed1=fixed 描述的是9位整数被规格化到-1到1 就是2的8次方 256跟颜色的最大值对应
          //fixed2=fixed(1,0);
          //float可以变为float2 float3 float4 没有五阶
          //half half2 half3 half4
          //fixed fixed2 fixed3 fixed4
           //2行4列的矩阵 通常用4x4不会报错但是会黄色警告
          // float2x4 M2x4={1,0,0,1,0,1,0,1};//便于阅读也可以{(1,0,0,1),(0,1,0,1)}
             float4x4 M2x4={1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0};
           col=M2x4[0];//取矩阵第一行 红色     
           col=M2x4[1];//取矩阵第二行 绿色
           //数组 
           float arr[4]={1,0.5,0.5,1};//橙红色
           col=float4(arr[0],arr[1],arr[2],arr[3]);
           //结构体赋值 改值操作
           v2f o;
           o.pos=fl4;
           o.uv=fl2;
        }
        ENDCG
        }
    }

}

CG的条件语句

if..else
while
Do...while
for
switch...case(有用但是最好别用,没有良好的支持,容易乱)

我这边试的也有错

Shader "Sbin/vf1" {
  SubShader {
    pass{   
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
      
   void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
   {
    pos=float4(objPos,0,1);
    if(pos.x<0 && pos.y<0)
    {
      col=float4(1,0,0,1);
    }
    else if(pos.x<0)
    {
      col=float4(0,1,0,1);
    }
    else if(pos.y>0)
    {
      col=float4(1,1,0,1);
    }
    else
    {
      col=float4(0,0,1,1);
    }
    //col=pos;
   }

    void frag(inout float4 col:COLOR)
    {
      //最好别用有一定问题 用if else代替
      // int i=0;
      // switch(i)
      // {
      //   case 0:
      //   col=float4(1,0,0,1);
      //   break;
      //   case 1:
      //   col=float4(0,1,0,1);
      //   break;
      //   case 2:
      //   col=float4(0,0,1,1);
      //   break;
      // }
    }
    ENDCG
  }
  }
  
}
image.png

老师是这样的我的进不来
之后的还可以

Shader "Sbin/vf1" {
  SubShader {
    pass{   
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
      
   void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
   {
    pos=float4(objPos,0,1);
    col=pos;
   }

    void frag(inout float4 col:COLOR)
    {
    //测试while
     int i=0;
     while(i<10)
     {
       i++;
     }
     if(i==10)
     {
     col=float4(0,0,0,1);
     }
     //看下do while
     i=0;
     do{
     i++;
     }
     while(i<10);
     if(i=10)
      col=float4(1,1,1,1);

      //for 循环有上限 老师的是1023 我的直接报黄说被迫执行一次循环
      i=0;
      for(i=0;i<10;i++)
      {
       if(i=10)
       col=float4(0.5f,0.5f,0,1);
      }
      

    }
    ENDCG
  }
  }
  
}

这个也动不了 之后把上面提示的错误信息删掉就好了

// Upgrade NOTE: excluded shader from DX11, OpenGL ES 2.0 because it uses unsized arrays
#pragma exclude_renderers d3d11 gles
Shader "Sbin/vf1" {
  SubShader {
    pass{   
    CGPROGRAM
// Upgrade NOTE: excluded shader from DX11, OpenGL ES 2.0 because it uses unsized arrays
#pragma exclude_renderers d3d11 gles
    #pragma vertex vert
    #pragma fragment frag
     void Func(out float4 c);
   float Func2(float arr[2])
   {
     float sum=0;
     for (int i=0;i

自定义函数

这样每次在头声明函数很麻烦
创建一个cginc的文件


image.png

里面放自己的函数

   //函数必须在调用之前 或者在之前声明
  void Func(out float4 c)
    {
    //CG参数以值拷贝进行传递
    c=float4(0,1,0,1);
    }
  float Func2(float arr[2])
  {
    float sum=0;
    for (int i=0;i
Shader "Sbin/vf1" {
SubShader {
  pass{   
  CGPROGRAM
  #pragma vertex vert
#pragma fragment frag
  //自定义函数
 #include "sbin.cginc"
 
 void vert(in float2 objPos:POSITION,out float4 pos:POSITION,out float4 col:COLOR)
 {
  pos=float4(objPos,0,1);
  col=pos;
 }

  void frag(inout float4 col:COLOR)
  {
      Func(col);
    //维度必须相同传递 没有维度不行 
    float arr[2]={0.5,0.5};
    //我的Func2挂掉了 说我的GPU不支持明暗编辑器 把上面自动生成的提示删了就好了
    col.x= Func2(arr);
  }

  
  ENDCG
}
}

}
image.png

是黄色
当Shader和.cginc在同一目录情况下可以直接名字引用
如果放在不同文件夹 应该是安路径找 但是我的就可以直接用 回报黄 然后多试了几下还是会报错 第一个是我放的文件夹 建议这么写

include "Cginc/sbin.cginc"

找到unity安装包路径 这个就是unity自带的CG库 我们可以调用 为我们节省很多时间
Editor/Data/CGIncludes(MAC下是Content/CGIncludes)

Unity函数

这个文库很全
https://wenku.baidu.com/view/3a9db318fad6195f312ba675.html
常用的lerp(a,b,f)是个差值

image.png

感觉像是个max()min()结合体
image.png

还有这个sin cos结合函数
image.png

就是把矩阵行变成列
image.png

这个模 就是向量v开平方相加除根号
image.png

为什么这么简单的要封装起来,因为他们的算是优化速度最快的,自己写的话不一定有他们快 就跟自己Json写的序列化反序列化 不如人家谷歌那群人写的Protobuf得快
这个是Shader源码
https://github.com/1004019267/ShaderTest/tree/master

你可能感兴趣的:(Unity Shader基础练习(三)CG入门)