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<arr.Length;i++)
     {
       sum+=arr[i];
     }
     return sum;
   }
   
   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[]={0.5,0.5};
      //我的Func2挂掉了 说我的GPU不支持明暗编辑器
      col.x= Func2(arr);
    }

      //函数必须在调用之前 或者在之前声明
   void Func(out float4 c)
     {
     //CG参数以值拷贝进行传递
     c=float4(0,1,0,1);
     }
    ENDCG
  }
}
  
}

自定义函数

这样每次在头声明函数很麻烦
创建一个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<arr.Length;i++)
    {
      sum+=arr[i];
    }
    return sum;
  }
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容