shader_shaderlab - CSDN
  • ShaderGraph从入门到实战

    千人学习 2019-09-27 10:02:05
    大智和你一起学习ShaderGraph,在实战中探索。 课程内容 ShaderGraph的基本使用 丰富的实战案例: · 全息效果 · 边缘光效果 · 溶解效果 ·&...
  • Shader开发从入门到精通

    万人学习 2020-03-15 19:43:15
    Shader编程从入门到精通视频教程,该课程主要分享2D中的Shader与3D中的Shader编程,具体功能包括颜色配置、纹理、UV动画、滤镜等。
  • Shader学习建议

    千次阅读 2019-03-11 21:27:32
    而游戏中酷炫逼真的效果又是由shader来控制实现的。所以想要提高自己技能就必须啃下shader这个硬骨头。 以下提供本人学习shader的心路历程。由于每个人学习方式不同,所以下面建议不适应所有人。学习过程如下: ...

    作为一名从业六年的游戏开发人员,搭过框架也做过优化。但是对图形渲染这块不了解。而游戏中酷炫逼真的效果又是由shader来控制实现的。所以想要提高自己技能就必须啃下shader这个硬骨头。

    以下提供本人学习shader的心路历程。由于每个人学习方式不同,所以下面建议不适应所有人。学习过程如下:
    1.作为一名客户端开发人员,首先要会应用shader做出上级分配的任务才是优先级最高的事情。几乎所有游戏引擎都提供了shader的上层封装,这也就更方便我们应用shader了。如:unity引擎中提供了unity shader,它是在底层图形api接口上做的一层封装,我们可以手写unity shader或者用unity的shader graph来拖拽实现想要的效果。unity shader的学习可以参考《Unity Shader入门精要》这本书,也可以参考本人unity shader专栏,里面是对《Unity Shader入门精要》学习的总结。

    2.会应用shader后就需要去了解底层的实现了。虽然引擎帮我们封装了接口,也提供了工具去写引擎定制的shader来帮我们实现想要的效果。但是作为unity长期用户来说,unity的bug还真不少,谁知道某一天会不会在渲染这个给你来一个bug,虽然引擎最终会修复,但也是漫长的等待。此时就必须对引擎的渲染底层有所了解,这样出问题了知道是哪里的问题并立马进行修复或者给出替代解决方案,这一点很重要。

    3.底层api选择:现在市面上主要有苹果公司的metal,微软公司的direct 3d以及跨平台的opengl。metal主要是针对苹果的a系列处理器做了优化,在苹果产品上的确性能很高。direct 3d主要在微软产品上应用,而且曾经跟opengl有场你死我活的api之争。但是很多开发者和硬件厂商还是选择支持opengl,就因为它的跨平台和高性能的特性。所以毫无悬念,本人这里也是选择opengl作为底层图形api学习的标准。

    4.opengl的学习资料:首先要了解opengl的发展历程,这个https://www.cnblogs.com/George1994/p/6418013.html链接中记录了大部分的opengl版本变化,最新的opengl已经发布到4.6了,详细的版本信息可以参照opengl官网。现在市面上比较受欢迎的书籍就是《OpenGL超级宝典(中文第5版3.3或者英文第七版4.5)》和《OpenGL编程指南(中文第九版4.5)》。建议先学习opengl超级宝典第五版,虽然现在opengl已经到最新的4.6了,而超级宝典第五版里面只是到3.3,但是并没有关系,因为3.3到4.6之间的核心架构都没变,只是引进了一些新的功能以及改善了某些功能的实现而已。而且书中细节讲解的很清晰,还有大量的例子来佐证,非常适合opengl初学者。当看完超级宝典第五版后建议再学习下opengl编程指南第九版,该书针对opengl4.5版本,不仅引入了很多有意思和高大上的技能讲解,可以继续更深层次学习3.3往后的版本技能。还可以当做api参考书,无疑是opengl界的新华字典。

    5.开始学习之旅啦!!!我会建立两个专栏,分别是opengl超级宝典第五版和opengl编程指南第九版。里面会总结学习的心得。有兴趣的朋友可以关注下。专栏会在周末空闲时间不定期更新,虽然历程有些漫长,但是静下心来慢慢撸,总会撸完的。

    展开全文
  • Shader入门教程(一)

    千次阅读 2019-11-23 17:07:19
    学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程。学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用shader编写出自己想要的特效,好...

    学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程。学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用shader编写出自己想要的特效,好了,下面我开始详细介绍shader的入门知识。

    我在这篇文章中主要介绍的内容有 
    ①Shader基础知识 
    ②Unity中Shader知识介绍 
    ③Surface Shader语法

    Shader基础知识

    什么是Shader?

    在讲什么是Shader之前我们先看看下面两段代码 

    这里写图片描述

     

    这两段代码实现的功能都是提取 2D 图像上每个像素点的颜色值,第一段代码是用c++写的,在cup上面运行,它需要循环遍历每个像素点,第二段代码是CG代码,在GPU上面运行,它只需要一行代码就能实现同样的功能。GPU是专门用来进行图形处理的,而Shader,就是GPU执行的一段针对3D对象进行操作的程序。

    维基百科上对shader的解释是这样(https://zh.wikipedia.org/wiki/%E7%9D%80%E8%89%B2%E5%99%A8

    Shader(着色器)应用于计算机图形学领域,指一组供计算机图形资源在执行渲染任务时使用的指令,用于计算图像的颜色或明暗。但近来,它也能用于处理一些特殊效果,或者视频后处理。通俗地说,着色器告诉电脑如何用特有的一种方法去绘制物体。

    程序员将着色器应用于图形处理器(GPU)的可编程流水线,来实现三维应用程序。这样的图形处理器有别于传统的固定流水线处理器,为GPU编程带来更高的灵活性和适应性。以前固有的流水线只能进行一些几何变换和像素灰度计算。现在可编程流水线还能处理所有像素、顶点、纹理的位置、色调、饱和度、明度、对比度并实时地绘制图像。着色器还能产生如模糊、高光、有体积光源、失焦、卡通渲染、色调分离、畸变、凹凸贴图、边缘检测、运动检测等效果。

    OpenGL的渲染流程

    知道了什么是shader,我们再来了解一下shader的种类,首先我先介绍一下OpenGL的渲染流程

     

    这里写图片描述

    上图便是OpenGL的渲染流程,其中每一步是干什么的我就不在这篇文章中介绍了,有兴趣的可以看看这篇博客(http://blog.csdn.net/lxdfigo/article/details/8457850),将这个流程简化之后是这样的 
    顶点变换 → 图元装配和光栅化 → 片元纹理映射和着色 → 写入帧缓存

     

    在顶点变换和片元着色这两步时,我们就可以对其编程,进行各种操作,其他的部分我们是没法进行编程的。我们的shader就是作用于顶点变换和片元着色这两个部分的。

    shader的种类

    知道了shader起作用的地点,我们现在可以了解一下shader的种类了。

    shader按管线分类一般分为固定渲染管线与可编程渲染管线。固定渲染管线就是功能固定的管线,比如物体表面光的折射,反射的算法是固定无法修改的,我们只能对这些功能进行配置,比如开启或关闭反射效果,雾化效果等。因为这种管线功能固定,无法在程序上对物体细节的表现给予更多更自由的控制,无法达到更多我们想要的画面效果。所以现在的显卡都是可编程渲染管线,也就是曾经那些我们固定无法修改的部门现在可以编程去修改,自由度高了之后,我们也就能实现更多自己想要的特效了。

    shader的开发语言

    知道了shader的种类,我在来说说shader的开发语言

    HLSL: 主要用于Direct3D。平台:windows。

    GLSL: 主要用于OpenGL。 平台:移动平台(iOS,安卓),mac(only use when you target Mac OS X or OpenGL ES 2.0)

    CG:与DirectX 9.0以上以及OpenGL 完全兼容。运行时或事先编译成GPU汇编代码。CG比HLSL、GLSL支持更多的平台,Unity Shader采用CG/HLSL作为开发语言。

    Unity中Shader知识介绍

    shader在GPU的渲染流程

     

    这里写图片描述

     

    进入GPU运算首先进行的是Vertex Processor顶点处理器,这个部分就需要我们使用Vertex Shader顶点着色器,顶点着色器运算的结果会交给Pixel Processor像素处理器,也就是片段处理器,在这个部分我需要为像素处理编写Pixel Shader像素着色器程序,这部分计算完后就输出了最终我们可以用于在屏幕上的颜色信息,我们把它叫做Frame Buffer帧缓冲。帧缓冲存储的是计算机依次显示所要的数据。

    Unity中shader的类型

    ①Fixed function shader :属于固定渲染管线 Shader, 基本用于高级Shader在老显卡无法显示时的回滚。使用的是ShaderLab语言,语法与微软的FX files 或者NVIDIA的 CgFX类似。

    ②Vertex and Fragment Shader:最强大的Shader类型,属于可编程渲染管线. 使用的是CG/HLSL语法。

    ③Surface Shader:Unity3d推崇的Shader类型,使用Unity预制的光照模型来进行光照运算。使用的也是CG/HLSL语法。

    我们先了解一下这三种shader的异同点。

    相同点: 
    ①都必须从唯一一个根Shader开始 
    ②Properties参数部分,作用及语法完全相同 
    ③具体功能都在SubShader里(Subshader会自上而下运行第一个硬件能支持的) 
    ④SubShader都可以打标签 
    ⑤都可以回滚 
    ⑥都可以处理基本的功能,例如光照漫反射(Diffuse)以及镜面反射(Specular)。但是Vertex and Fragment和Surface都能实现Fixed function实现不了的高级功能,例如基于uv计算的效果等等。

    不同点 
    ①Fixed function shader以及Vertex and Fragment Shader在subshader下面还有pass{}结构,但是Surface Shader,已经将具体内容打包在光照模型了,不能加pass{} 
    ②Fixed function shader每句代码之后没有分号“;”, 但是V&F shader以及Surface shader每句代码之后都必须加分号“;” 
    ③核心结构不同 
    Fixed function shader的SunShader中的结构为

    Material{} 
    ……
    SetTexture[_MainTex]{
        ……
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    Vertex and Fragment Shader的核心结构为

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag   
    ……       
    #include "UnityCG.cginc"
    ENDCG
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Surface Shader的核心结构是

    CGPROGRAM
    #pragma surface surf Lambert
    ……
    ENDCG
    • 1
    • 2
    • 3
    • 4

    可以看到这三种shader的Subshader内的编码实现是不一样的,这三种shader的结构如下图,他们的不同点都在SubShader里面 

    这里写图片描述

     

    因为Unity推荐Surface Shader,所以文章直接分析Surface Shader的用法,其他两种shader就不做过多介绍了。

    Surface Shader语法

    在Unity的项目面板中直接创建一个Stander surface shader,默认生成的代码如下

    Shader "Custom/DiffuseShader" {
        Properties {
            _Color ("Color", Color) = (1,1,1,1)       //设置一个默认的颜色值
            _MainTex ("Albedo (RGB)", 2D) = "white" {}  //默认的白色纹理
            _Glossiness ("Smoothness", Range(0,1)) = 0.5  //默认的光泽度
            _Metallic ("Metallic", Range(0,1)) = 0.0    //金属光泽度
        }
        SubShader {
            Tags { "RenderType"="Opaque"}
            LOD 200
    
            CGPROGRAM
            // Physically based Standard lighting model, and enable shadows on all light types
            #pragma surface surf Standard fullforwardshadows
    
            // Use shader model 3.0 target, to get nicer looking lighting
            #pragma target 3.0
    
    
            fixed4 _Color;
            sampler2D _MainTex;
            half _Glossiness;
            half _Metallic;
    
    
            struct Input {
                float2 uv_MainTex;
            };
    
    
    
            void surf (Input IN, inout SurfaceOutputStandard o) {
                // Albedo comes from a texture tinted by color
                fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                // Metallic and smoothness come from slider variables
                o.Metallic = _Metallic;
                o.Smoothness = _Glossiness;
                o.Alpha = c.a;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    接下来我来介绍一下这段代码

    Properties {}

    Properties{}是定义着色器属性的,在这里定义的属性将被作为输入提供给所有的子着色器。属性定义的格式如下

    _Name(“Display Name”, type) = defaultValue[{options}]

    _Name代表的是属性名,如Color,MainTex,Glossiness ,Metallic 等

    ”Display Name”则是在Inspector中显示的名字

    type代表属性:

        Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
        2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
        Rect - 一个非2阶数大小的贴图;
        Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样;
        Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
        Float - 任意一个浮点数;
        Vector - 一个四维数;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这段默认Properties在Inspector中的显示效果如下 

    这里写图片描述

     

    SubShader{}

    Tags :tags标签是三种类型的shader都具有的标签,它决定了硬件什么调用该子着色器

    Tags标签里面默认的“RenderType”=”Opaque”,是告诉系统应该在渲染非透明物体时调用这个SubShader
    “RenderType”=”Transparent”表示在渲染含有透明效果的物体时调用该Sunshader,
    
    Tags里面还有许多其他的我们可选的标签
    ①.”Queue”:定义渲染顺序。预制的值有这些 
        ”Background”。值为1000。比如用于天空盒。
        ”Geometry”。值为2000。大部分物体在这个队列。不透明的物体也在这里。
        ”AlphaTest”。值为2450。已进行AlphaTest的物体在这个队列。 
        ”Transparent”。值为3000。透明物体。 
        ”Overlay”。值为4000。比如镜头光晕。 
        用户可以定义任意值,比如”Queue”=”Geometry+10”
    ②“RenderType”:定义渲染类型。预制的值有这些
        ”Opaque”:绝大部分不透明的物体都使用这个; 
        ”Transparent”:绝大部分透明的物体、包括粒子特效都使用这个; 
        ”Background”:天空盒都使用这个; 
        ”Overlay”:GUI、镜头光晕都使用这个; 
    ③”ForceNoShadowCasting”:定义物体是否有阴影效果
        “true”。表示有阴影
        “false”。表示没有阴影
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    LOD:Level of Detail的缩写,它表示着色器的细节层次效果。在某些硬件比较差的系统上,我们可以设置一个低一点的值,减少细节的显示。Unity内置shader的LOD值如下

    • VertexLit kind of shaders = 100
    • Decal, Reflective VertexLit = 150
    • Diffuse = 200
    • Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
    • Bumped, Specular = 300
    • Bumped Specular = 400
    • Parallax = 500
    • Parallax Specular = 600

    CGPROGRAM 到ENDCG这一部分就这这个shader的核心内容了

    #pragma surface surf Standard fullforwardshadows
    • 1

    这段编译指令声明了我们要写一个Surface Shader,并指定了光照模型。它的写法是这样的

    #pragma surface surfaceFunction lightModel [optionalparams]
    • 1
    • surface - 声明的是一个表面着色器
    • surfaceFunction - 着色器代码的方法的名字
    • lightModel - 使用的光照模型。

    这段代码默认的surfaceFunction为surf,我们可以在源码的底部看到在这儿声明了的surf函数。默认的lightModel为Standard。

    下面我先介绍一下lightModel光照模型

    • Lambert:该光照模型能很好的表示粗糙表面的光照,但不能表现出镜面反射高光

    • Toon:最近在游戏中常用的风格之一即是Toon shading(又称 cel shading).这是一种非逼真渲染风格,通过改变了光在一个模型上反射实际情况来给人以手绘的感觉

    • BlinnPhong:仿真镜面反射材料

    • Standard:Unity5中默认的光照模式是Standard, 其引入了 物理渲染 (PBR), 但是与其它光照模型没有什么不同。相比于朗伯反射, PBR提供了一个更加逼真的光线物体作用模型,PBR考虑了材料的物理属性, 比如能量守恒以及光的散射

    接下来的这段代码

       fixed4 _Color;
       sampler2D _MainTex;
       half _Glossiness;
       half _Metallic;
    • 1
    • 2
    • 3
    • 4

    我们可以发现 _Color,_MainTex,_Glossiness,_Metallic都shader属性的声明,在上面的Properties 中已经声明过了这些属性,但是在这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字再次进行声明,其实就是链接在上面properties中声明的属性。

    我再来介绍一下shader中常用的数据类型

    3种基本数值类型:float、half和fixed。 
    这3种基本数值类型可以再组成vector和matrix,比如half3是由3个half组成、float4x4是由16个float组成。

    float:32位高精度浮点数。 
    half:16位中精度浮点数。范围是[-6万, +6万],能精确到十进制的小数点后3.3位。 
    fixed:11位低精度浮点数。范围是[-2, 2],精度是1/256。 
    Sampler2D:2D纹理属性

    接下来就是Input结构体

    struct Input {
        float2 uv_MainTex;
    };
    • 1
    • 2
    • 3

    这个结构体和surf函数中的另一个参数inout结构体是相对的,一个代表输入,一个代表输出。我们可以这样理解这两个结构体,你定义输入数据结构(Inputs Struct)、编写自己的Surface函数处理输入、最终输出修改过后的SurfaceOutput。Input其实是需要我们去定义的结构,所以我们可以把所需要参与计算的数据都放到这个Input结构中,传入surf函数使用

    默认的Input结构体中有一个uv_MainTex参数,代表了纹理的UV值,我们便可以在surf函数中直接使用这个参数了。

    知道了Input的结构体,我们在来看看Output的结构体

    struct SurfaceOutput
    {
        fixed3 Albedo;  // diffuse color  漫反射的颜色值。
        fixed3 Normal;  // tangent space normal, if written 法线坐标
        fixed3 Emission;  //自发光颜色
        half Specular;  // specular power in 0..1 range 镜面反射系数
        fixed Gloss;    // specular intensity   光泽系数
        fixed Alpha;    // alpha for transparencies  透明度系数
    };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    现在我们在来看看surf函数里面的内容,就已经能够看懂了

    我们现在在来看看surf函数里面的代码,就能知道里面是什么意思了

            void surf (Input IN, inout SurfaceOutputStandard o) {
                fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;               //将物体显示的漫反射颜色设置成在纹理的颜色值
                o.Metallic = _Metallic;         //将物体显示的金属光泽设置成在properties中定义的光泽
                o.Smoothness = _Glossiness;     //设置物体显示的光滑度
                o.Alpha = c.a;                  //设置物体显示的透明度
            }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tyuiof/article/details/52754300
    展开全文
  • Shader各种效果

    千次阅读 2018-05-16 09:09:41
    1.Shader1.0的Alpha测试Shader "Hidden/AlphaTestShader1.0" { Properties { _MainTex ("Texture", 2D) = "white" {} _AlphaTest("Alpha值",float) = 0 } ...

    1.Shader1.0的Alpha测试

    Shader "Hidden/AlphaTestShader1.0"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_AlphaTest("Alpha值",float) = 0
    	}
    	SubShader
    	{
    		AlphaTest Greater [_AlphaTest]
    		Pass
    		{
    			SetTexture[_MainTex]
    			{
    				combine texture
    			}
    		}
    	}
    }
    

    2.Shader2.0

    2.1 轮廓自发光

            两个Pass,一个渲染原本的贴图,一个渲染颜色,将顶点的xy方向扩大。

    Shader "Custom/OutLine2.0"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_TestColor("轮廓自发光颜色",Color)=(1,1,1,1)
    		_Width("轮廓宽度",Float)=1.1
    	}
    	SubShader
    	{
    		// No culling or depth
    		//Cull Off ZWrite Off ZTest Always//后期屏蔽的
    
    		Pass
    		{
    
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			float _Width;/*****************************/
    			v2f vert (appdata v)
    			{
    				v2f o;
    				
    				v.vertex.xy *= _Width;/*********************/
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;
    
    			Vector _TestColor;/************************/
    			fixed4 frag (v2f i) : SV_Target
    			{
    				fixed4 col = tex2D(_MainTex, i.uv);
    				// just invert the colors
    				//col.rgb = 1 - col.rgb;
    				return fixed4(_TestColor);/*********************/
    				//return col;
    			}
    			ENDCG
    		}
    
    			Pass
    			{
    				ZTest Always
    				CGPROGRAM
    				#pragma vertex vert
    				#pragma fragment frag
    
    				#include "UnityCG.cginc"
    
    				struct appdata
    				{
    					float4 vertex : POSITION;
    					float2 uv : TEXCOORD0;
    				};
    
    				struct v2f
    				{
    					float2 uv : TEXCOORD0;
    					float4 vertex : SV_POSITION;
    				};
    
    				v2f vert(appdata v)
    				{
    					v2f o;
    					o.vertex = UnityObjectToClipPos(v.vertex);
    					o.uv = v.uv;
    					return o;
    				}
    
    				sampler2D _MainTex;
    
    				fixed4 frag(v2f i) : SV_Target
    				{
    					fixed4 col = tex2D(_MainTex, i.uv);
    				// just invert the colors
    				//col.rgb = 1 - col.rgb;//后期屏蔽的
    				
    				return col;
    				}
    				ENDCG
    			}
    	}
    }
    

    2.2 Alpha测试

    Shader "Hidden/AlphaTestShader2.0"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_AlphaValue("Alpha值",float)=0
    	}
    	SubShader
    	{
    		// No culling or depth
    		//Cull Off ZWrite Off ZTest Always
    			Blend SrcAlpha OneMinusSrcAlpha//打开Alpha通道
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;
    
    			float _AlphaValue;
    			fixed4 frag (v2f i) : SV_Target
    			{
    				fixed4 col = tex2D(_MainTex, i.uv);
    
    			if (col.a < _AlphaValue)
    			{
    				return fixed4(0, 0, 0, 0);
    			}
    			else
    			{
    				return col;
    			}
    			}
    			ENDCG
    		}
    	}
    }
    

    3.Shader2.0 的UV动画

    3.1 UV滚动(流动)

    Shader "Custom/River"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_SpeedY("Y向流动速度",Range(0,10))=1.0
    		_SpeedX("X向流动速度",Range(0,20)) = 0
    	}
    	SubShader
    	{
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;
    
    
    			float _SpeedY;/*增***********************/
    			float _SpeedX;/*增***********************/
    			fixed4 frag (v2f i) : SV_Target
    			{
    				float2 tempUV = i.uv;/*增***********************/
    				tempUV.x += _Time.x*_SpeedX;/*增***********************/
    				tempUV.y += _Time.y*_SpeedY;/*增***********************/
    
    				fixed4 col = tex2D(_MainTex, tempUV);/*改***********************/
    				
    				return col;
    			}
    			ENDCG
    		}
    	}
    }
    

    3.2 UV波动(wave)

    Shader "Custom/Wave"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_Arange("波动幅度",float) = 1
    		_Frenquncy("波动频率",float)=0.5
    		_Speed("波动速度", float) = 0.5
    	}
    	SubShader
    	{
    		
    
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			float _Arange;/*增******************************/
    			float _Frenquncy;/*增******************************/
    			float _Speed;/*增******************************/
    			v2f vert(appdata v)
    			{
    
    				v2f o;
    
    				float timer = _Time.y*_Speed;/*增******************************/
    				float waver = _Arange * sin(timer + v.vertex.x*_Frenquncy);/*增******************************/
    
    				v.vertex.y = v.vertex.y + waver;/*增******************************/
    
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;
    
    			
    
    			fixed4 frag (v2f i) : SV_Target
    			{
    				fixed4 col = tex2D(_MainTex, i.uv);
    				// just invert the colors
    				//col.rgb = 1 - col.rgb;
    				return col;
    			}
    			ENDCG
    		}
    	}
    }
    

    3.3 UV旋转(Loading)

    Shader "Custom/Loading_Icon"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    		_RotateSpeed("旋转速度",float) = 15.0
    	}
    	SubShader
    	{
    		// No culling or depth
    		//Cull Off ZWrite Off ZTest Always
    
    		Blend SrcAlpha OneMinusSrcAlpha//打开Alpha通道
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;/**增******************************/
    			float _RotateSpeed;/**增******************************/
    			fixed4 frag (v2f i) : SV_Target
    			{
    				/**增******************************/
    				float2 tempUV = i.uv;
    
    				tempUV -= float2(0.5, 0.5);//1.平移到原点
    										  
    				if (length(tempUV) > 0.5)//防止对角线多余的长度显示
    				{
    					return fixed4(0, 0, 0, 0);
    				}
    
    				/*2.绕z轴旋转******************************/
    				float2 finalUV = 0;
    				float angle = _Time.x*_RotateSpeed;
    
    				finalUV.x = tempUV.x*cos(angle) - tempUV.y*sin(angle);
    				finalUV.y = tempUV.x*sin(angle) + tempUV.y*cos(angle);
    
    				finalUV += float2(0.5, 0.5);//3.将贴图平移回原位置
    				/**增******************************/
    				fixed4 col = tex2D(_MainTex, finalUV);/**改******************************/
    				
    				return col;
    			}
    			ENDCG
    		}
    	}
    }
    

    3.4 屏幕高斯效果

    3.4.1 Shader

    Shader "Custom/MyShader"
    {
    	Properties
    	{
    		_MainTex ("贴图", 2D) = "white" {}
    		_Amnient("高斯模糊程度",Float) = 0.001
    	}
    	SubShader
    	{
    		// No culling or depth
    		//Cull Off ZWrite Off ZTest Always
    
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				float4 vertex : SV_POSITION;
    			};
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = UnityObjectToClipPos(v.vertex);
    				o.uv = v.uv;
    				return o;
    			}
    			
    			sampler2D _MainTex;
    
    			float _Amnient;
    			fixed4 frag (v2f i) : SV_Target
    			{
    				float2 tempUV = i.uv;/*增**********************/
    				float ambient = _Amnient;/*增**********************/
    				fixed4 col = tex2D(_MainTex, tempUV);/*改**********************/
    				// just invert the colors
    				//col.rgb = 1 - col.rgb;
    				fixed4 col2 = tex2D(_MainTex, tempUV + float2(-ambient, 0));/*增**********************/
    				fixed4 col3 = tex2D(_MainTex, tempUV + float2(0,-ambient));/*增**********************/
    				fixed4 col4 = tex2D(_MainTex, tempUV + float2(ambient, 0));/*增**********************/
    				fixed4 col5 = tex2D(_MainTex, tempUV + float2(0,ambient));/*增**********************/
    
    				col = (col + col2 + col3 + col4 + col5) / 5.0;/*增**********************/
    				return col;
    			}
    			ENDCG
    		}
    	}
    }
    

    3.4.2 C#

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// <summary>
    /// 需要挂载到相机上
    /// </summary>
    public class CameraMove : MonoBehaviour {
    
        // Use this for initialization
        //public Shader myShader;
        public Material material;
    	void Start () {
            //material = new Material(myShader);
    	}
    	
    	// Update is called once per frame
    	void Update () {
    		
    	}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="source">拦截到相机所渲染的图片</param>
        /// <param name="destination">更改后返回的图片,重新交给引擎</param>
        private void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            Graphics.Blit(source, destination, material);
        }
    }
    

    4. Surface5.0

    4.1 UV 滚动

    Shader "Custom/TestParameter" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert vertex:MyVertex
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    
    		struct Input {
    			float2 uv_MainTex;
    			float3 myColor;
    		};
    
    		
    		fixed4 _Color;
    
    		void MyVertex(inout appdata_base v,out Input o)
    		{
    			UNITY_INITIALIZE_OUTPUT(Input, o);
    			o.myColor = _Color.rgb*abs(v.normal);
    		}
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
    			o.Albedo = c.rgb*IN.myColor;
    			
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    4.2 高光

    Shader "Custom/CustomLighting" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_SpeclPower("高光强度",float) = 1
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Simple
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    
    		struct Input {
    			float2 uv_MainTex;
    		};
    
    
    		fixed4 _Color;
    
    		
    		UNITY_INSTANCING_BUFFER_START(Props)
    			// put more per-instance properties here
    		UNITY_INSTANCING_BUFFER_END(Props)
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    			o.Albedo = c.rgb;
    			
    			o.Alpha = c.a;
    		}
    
    		float _SpeclPower;
    		///自定义的灯光入口函数
    		half4 LightingSimple(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
    		{
    			float NDotL = dot(lightDir, s.Normal);
    
    			half4 result = 0;
    			//result.rgb = s.Albedo* _LightColor0*NDotL*atten;//漫反射
    
    
    			half3 H = viewDir - lightDir;
    			float HDotN = dot(H, s.Normal);
    
    			result.rgb = s.Albedo* _LightColor0*NDotL*atten+HDotN* s.Albedo* _LightColor0*_SpeclPower;
    			result.a = s.Alpha;
    
    			return result;
    		}
    
    		ENDCG
    	}
    	FallBack "Diffuse"
    

    }

    4.3 法线贴图

            可以使对比度增强,使凸的地方看起来更凸。

    Shader "Custom/NormalMap" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_NormalMap("法线贴图", 2D) = "white" {}
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    		sampler2D _NormalMap;
    		struct Input {
    			float2 uv_MainTex;
    			float2 uv_NormalMap;
    		};
    
    	
    		fixed4 _Color;
    
    		
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    			
    			o.Normal= UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
    			o.Albedo = c.rgb;
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    4.4 边缘自发光

    Shader "Custom/NormalOutLine" {
    	Properties {
    		_Color ("自发光颜色", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_NormalTex("法线贴图", 2D) = "white" {}
    		_EmisionPower("自发光强度",float) = 1
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    		sampler2D _NormalTex;
    		struct Input {
    			float2 uv_MainTex;
    			float2 uv_NormalTex;
    
    			float3 viewDir;
    		};
    
    		
    		fixed4 _Color;
    		float _EmisionPower;
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
    			o.Albedo = c.rgb;
    
    			//读取法线
    			float3 tempNormal= UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex));
    			
    			o.Normal = tempNormal;
    			//算出法线和视角的点乘
    			float tempFloat=1- clamp(dot(IN.viewDir, tempNormal),0, 1);//clamp()让取值变到一个范围
    			
    			o.Emission = _Color *pow(tempFloat,_EmisionPower);
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    4.5 Fog

        当需要在某个物体周围呈现雾效,而不是整个场景中呈现雾效,就需要写Shader。

    Shader "Custom/TestFog" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_FogStart("雾的起点",float) = 1
    			_FogEnd("雾的终点",float) = 1
    			_FogColor("雾的颜色",Color)=(1,1,1,1)
    	}
    		SubShader{
    			Tags { "RenderType" = "Opaque" }
    			LOD 200
    
    			CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf   Lambert    vertex:MyVertex    finalcolor:FinalColor
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    
    		struct Input {
    			float2 uv_MainTex;
    
    			float fogData;
    		};
    
    		
    		fixed4 _Color;
    		float _FogStart;
    		float _FogEnd;
    		fixed4 _FogColor;
    		void FinalColor(Input IN,SurfaceOutput o,inout fixed4 color)
    		{
    			//color *= float4(1, 0, 0, 1);
    
    			color = lerp(_FogColor, color, IN.fogData);
    		}
    
    		
    		void MyVertex(inout appdata_full v, out Input data)
    		{
    			UNITY_INITIALIZE_OUTPUT(Input, data);//初始化
    			
    			float tempZ = _FogEnd - length(UnityObjectToViewPos(v.vertex).xyz);
    
    			data.fogData = tempZ/(_FogEnd- _FogStart);
    		}
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    			o.Albedo = c.rgb;
    			
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    4.6 菲尼尔反射

    Shader "Custom/TestFresnel" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_CubeMap("CubeMap",Cube) = ""{}
    		_Rate("折射率",float) = 1
    
    		_FresnelBias("菲尼尔偏移",float) = 1
    			_FresnelScale("菲尼尔缩放系数",float) = 1
    			_FresnelPower("菲尼尔指数",float) = 0.5
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert vertex:MyVertex
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    		samplerCUBE _CubeMap;
    		struct Input {
    			float2 uv_MainTex;
    			float3 worldRefl;//反射
    
    			float refract;//折射
    			float reflectFact;//定义的反射系数
    
    		};
    
    		
    		fixed4 _Color;
    		float _Rate;
    		float _FresnelBias;
    		float  _FresnelScale;
    		float	_FresnelPower;
    		void MyVertex(inout appdata_full v, out Input data)
    		{
    			UNITY_INITIALIZE_OUTPUT(Input, data);//初始化
    
    			//右世界变成物体的
    			float3 localNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
    			//入射角
    			float3 viewDir = -WorldSpaceViewDir(v.vertex);
    
    			data.refract = refract(viewDir, localNormal, _Rate);
    
    			data.reflectFact = _FresnelBias + _FresnelScale * pow(1 + dot(viewDir, localNormal), _FresnelPower);
    		}
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			//fixed4 cflect = tex2D (_MainTex, IN.worldRefl);//反射
    			//fixed4 cfract = tex2D(_MainTex, IN.refract);
    
    			fixed4 cflect = texCUBE(_CubeMap, IN.worldRefl);//反射
    			fixed4 cfract = texCUBE(_CubeMap, IN.refract);
    
    
    			o.Albedo = IN.reflectFact*cflect.rgb + (1 - IN.reflectFact)*cfract.rgb;
    			
    			
    			o.Alpha = cflect.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    4.7 BRDF

            双向反射分布函数(Bidirectional Reflectance Distribution Function,BRDF)用来定义给定入射方向上的辐射照度(irradiance)如何影响给定出射方向上的辐射率(radiance)。更笼统地说,它描述了入射光线经过某个表面反射后如何在各个出射方向上分布--这可以是从理想镜面反射到漫反射、各向同性(isotropic)或者各向异性(anisotropic)的各种反射。

    Shader "Custom/TestBRDF" {
    	Properties {
    		_SpeColor ("高光颜色", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_SpecPower("高光强度",float)=1
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf  BRDFLigthing
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    
    		struct Input {
    			float2 uv_MainTex;
    		};
    
    		
    		fixed4 _SpeColor;
    		float _SpecPower;
    
    		#define PI 3.1415926
    		half4 LightingBRDFLigthing(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
    		{
    			float3 H = normalize(lightDir + viewDir);
    			float3 N = normalize(s.Normal);
    			
    			float d = (_SpecPower + 2)*pow(dot(N, H),_SpecPower) / 8.0;
    
    			float f = _SpeColor + (1 - _SpeColor)*pow(1 - dot(H, N), 5);
    
    			float k = 2 / (sqrt(PI*(_SpecPower + 2)));
    
    			float v = 1 / (dot(N, lightDir)*(1 - k) + k)*(dot(N, viewDir)*(1 - k) + k);
    
    
    			float all = d * f*v;
    			float diff = dot(lightDir, N);
    
    			float tempResult = all + (1 - all)*diff;
    
    			half4 finalColor = 0;
    			finalColor.rgb = tempResult * s.Albedo*_LightColor0.rgb;
    
    			finalColor.a = s.Alpha;
    
    			return finalColor;
    		}
    
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
    			o.Albedo = c.rgb;
    			
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    5. CubeMap

    5.1 真反射

        利用CubeMap做真反射;新建一个相机,对准需要反射的内容,新建一个Render Texture,并将此Render Texture赋予反射摄像机的Target Texture;新建一个材质球(标准材质球即可),在贴图通道赋予新建的Render Texture,最后将材质赋予需要有反射性的物体,该物体就会实时反射后一个新建摄像机的内容。但是真反射非常消耗性能。


    5.2 假反射

            也需要建一个需要反射出的内容的CubeMap,一般需要反射的为天空盒。

    Shader "Custom/FalseRelf" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_CubeMap("CubeMap",Cube) = ""{}
    		_CubePower("CubePower",float) = 1
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    		
    	samplerCUBE _CubeMap;
    		struct Input {
    			float2 uv_MainTex;
    
    			float3 worldRefl;//反射角
    		};
    
    		
    		fixed4 _Color;
    		float _CubePower;
    		
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    
    			o.Emission= texCUBE(_CubeMap, IN.worldRefl)*_CubePower;
    			o.Albedo = c.rgb;
    			
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    

    }

    5.3 折

            也需要建一个需要折射看到的内容的CubeMap。

    Shader "Custom/Refract" {
    	Properties {
    		_Color ("Color", Color) = (1,1,1,1)
    		_MainTex ("Albedo (RGB)", 2D) = "white" {}
    		_Rate("折射率",float) = 1
    		_CubeMap("CubeMap",Cube) = ""{}
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf Lambert vertex:MyVertex
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		sampler2D _MainTex;
    		samplerCUBE _CubeMap;
    		struct Input {
    			float2 uv_MainTex;
    
    			float3 refr;
    		};
    
    		float _Rate;
    		void MyVertex(inout appdata_full v,out Input data)
    		{
    			UNITY_INITIALIZE_OUTPUT(Input, data);//初始化
    
    			//右世界变成物体的
    			float3 localNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
    
    			//入射角
    			float3 viewDir=- WorldSpaceViewDir(v.vertex);
    
    			data.refr= refract(viewDir, localNormal, _Rate);
    		}
    		fixed4 _Color;
    		
    		
    		void surf (Input IN, inout SurfaceOutput o) {
    			// Albedo comes from a texture tinted by color
    			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    
    			o.Emission= texCUBE(_CubeMap, IN.refr).rgb;
    			o.Albedo = c.rgb;
    
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    

    展开全文
  • Shader入门-2

    千次阅读 2018-08-15 17:23:33
    Hello Shader 百行文档不如一个实例,下面给出一段简单的Shader代码,然后根据代码来验证下上面说到的结构和阐述一些基本的Shader语法。因为本文是针对Unity3D来写Shader的,所以也使用Unity3D来演示吧。首先,新建...

    Hello Shader

    百行文档不如一个实例,下面给出一段简单的Shader代码,然后根据代码来验证下上面说到的结构和阐述一些基本的Shader语法。因为本文是针对Unity3D来写Shader的,所以也使用Unity3D来演示吧。首先,新建一个Shader,可以在Project面板中找到,Create,选择Shader,然后将其命名为Emission

    在Unity3D中新建一个Shader

    随便用个文本编辑器打开刚才新建的Shader:

    Shader "Custom/Ill_RimLight" 
    {
        Properties {
            _Color ("Main Color", Color) = (.5,.5,.5,1)
            _OutlineColor ("Rim Color", Color) = (0,0,0,1)
            _Outline ("Rim width", Range (.002, 0.03)) = .005
            _MainTex ("Base (RGB)", 2D) = "white" { }
            _Illum ("Illumin (A)", 2D) = "white" { }
            _EmissionLM ("Emission (Lightmapper)", Float) = 0
        }
        
        SubShader 
        {
    
            Tags { "RenderType"="Opaque" }
            LOD 200
        
            CGPROGRAM
            #pragma surface surf Lambert
    
            sampler2D _MainTex;
            sampler2D _Illum;
            fixed4 _Color;
    
            struct Input {
                float2 uv_MainTex;
                float2 uv_Illum;
            };
    
            void surf (Input IN, inout SurfaceOutput o) {
                fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
                fixed4 c = tex * _Color;
                o.Albedo = c.rgb;
                o.Emission = c.rgb * tex2D(_Illum, IN.uv_Illum).a;
                o.Alpha = c.a;
            }
            ENDCG
    
            Pass 
            {
                CGINCLUDE
                #include "UnityCG.cginc"
        
                struct appdata {
                    float4 vertex : POSITION;
                    float3 normal : NORMAL;
                };
    
                struct v2f {
                    float4 pos : POSITION;
                    float4 color : COLOR;
                };
        
                uniform float _Outline;
                uniform float4 _OutlineColor;
        
                v2f vert(appdata v) {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
    
                    float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
                    float2 offset = TransformViewToProjection(norm.xy);
    
                    o.pos.xy += offset * o.pos.z * _Outline;
                    o.color = _OutlineColor;
                    return o;
                }
                ENDCG
    
                Name "OUTLINE"
                Tags { "LightMode" = "Always" }
                Cull Front
                ZWrite On
                ColorMask RGB
                Blend SrcAlpha OneMinusSrcAlpha
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                half4 frag(v2f i) :COLOR { return i.color; }
                ENDCG
            }
        } 
        
        Fallback "Self-Illumin/VertexLit"
    }
    
    

    如果您之前没怎么看过Shader代码的话,估计细节上会看不太懂。Shader的构成,比如一个Properties部分,一个SubShader,以及一个FallBack。另外,第一行只是这个Shader的声明并为其指定了一个名字,比如我们的实例Shader,你可以在材质面板选择Shader时在对应的位置找到这个Shader。

     

    接下来我们讲逐句讲解这个Shader,以期明了每一个语句的意义。

    属性

    Properties{}中定义着色器属性,在这里定义的属性将被作为输入提供给所有的子着色器。每一条属性的定义的语法是这样的:

    _Name("Display Name", type) = defaultValue[{options}]

    • _Name - 属性的名字,简单说就是变量名,在之后整个Shader代码中将使用这个名字来获取该属性的内容
    • Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容
    • type - 这个属性的类型,可能的type所表示的内容有以下几种:
      • Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
      • 2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
      • Rect - 一个非2阶数大小的贴图;
      • Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样;
      • Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
      • Float - 任意一个浮点数;
      • Vector - 一个四维数;
    • defaultValue 定义了这个属性的默认值,通过输入一个符合格式的默认值来指定对应属性的初始值(某些效果可能需要某些特定的参数值来达到需要的效果,虽然这些值可以在之后在进行调整,但是如果默认就指定为想要的值的话就省去了一个个调整的时间,方便很多)。
      • Color - 以0~1定义的rgba颜色,比如(1,1,1,1);
      • 2D/Rect/Cube - 对于贴图来说,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者”white”,”black”,”gray”,”bump”中的一个
      • Float,Range - 某个指定的浮点数
      • Vector - 一个4维数,写为 (x,y,z,w)
    • 另外还有一个{option},它只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},当我们需要打开特定选项时可以把其写在这对花括号内。如果需要同时打开多个选项,可以使用空白分隔。可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,这些都是OpenGL中TexGen的模式,具体的留到后面有机会再说。

    所以,一组属性的申明看起来也许会是这个样子的

    //Define a color with a default value of semi-transparent blue
    _MainColor ("Main Color", Color) = (0,0,1,0.5)
    //Define a texture with a default of white
    _Texture ("Texture", 2D) = "white" {}
    

    现在看懂上面那段Shader(以及其他所有Shader)的Properties部分应该不会有任何问题了。接下来就是SubShader部分了。

    Tags

    表面着色器可以被若干的标签(tags)所修饰,而硬件将通过判定这些标签来决定什么时候调用该着色器。比如我们的例子中SubShader的第一句

    Tags { "RenderType"="Opaque" }

    告诉了系统应该在渲染非透明物体时调用我们。Unity定义了一系列这样的渲染过程,与RenderType是Opaque相对应的显而易见的是"RenderType" = "Transparent",表示渲染含有透明效果的物体时调用。在这里Tags其实暗示了你的Shader输出的是什么,如果输出中都是非透明物体,那写在Opaque里;如果想渲染透明或者半透明的像素,那应该写在Transparent中。

    另外比较有用的标签还有"IgnoreProjector"="True"(不被Projectors影响),"ForceNoShadowCasting"="True"(从不产生阴影)以及"Queue"="xxx"(指定渲染顺序队列)。这里想要着重说一下的是Queue这个标签,如果你使用Unity做过一些透明和不透明物体的混合的话,很可能已经遇到过不透明物体无法呈现在透明物体之后的情况。这种情况很可能是由于Shader的渲染顺序不正确导致的。Queue指定了物体的渲染顺序,预定义的Queue有:

    • Background - 最早被调用的渲染,用来渲染天空盒或者背景
    • Geometry - 这是默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的)
    • AlphaTest - 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
    • Transparent - 以从后往前的顺序渲染透明物体
    • Overlay - 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)

    这些预定义的值本质上是一组定义整数,Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000,最后Overlay = 4000。在我们实际设置Queue值时,不仅能使用上面的几个预定义值,我们也可以指定自己的Queue值,写成类似这样:"Queue"="Transparent+100",表示一个在Transparent之后100的Queue上进行调用。通过调整Queue值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技巧有时候很有用处。

    LOD

    LOD很简单,它是Level of Detail的缩写,在这里例子里我们指定了其为200(其实这是Unity的内建Diffuse着色器的设定值)。这个数值决定了我们能用什么样的Shader。在Unity的Quality Settings中我们可以设定允许的最大LOD,当设定的LOD小于SubShader所指定的LOD时,这个SubShader将不可用。Unity内建Shader定义了一组LOD的数值,我们在实现自己的Shader的时候可以将其作为参考来设定自己的LOD数值,这样在之后调整根据设备图形性能来调整画质时可以进行比较精确的控制。

    • VertexLit及其系列 = 100
    • Decal, Reflective VertexLit = 150
    • Diffuse = 200
    • Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
    • Bumped, Specular = 300
    • Bumped Specular = 400
    • Parallax = 500
    • Parallax Specular = 600

    Shader本体

    前面杂项说完了,终于可以开始看看最主要的部分了,也就是将输入转变为输出的代码部分。为了方便看,请容许我把上面的SubShader的主题部分抄写一遍

    CGPROGRAM
    #pragma surface surf Lambert
    
    sampler2D _MainTex;
            sampler2D _Illum;
            fixed4 _Color;
    
            struct Input {
                float2 uv_MainTex;
                float2 uv_Illum;
            };
    
            void surf (Input IN, inout SurfaceOutput o) {
                fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
                fixed4 c = tex * _Color;
                o.Albedo = c.rgb;
                o.Emission = c.rgb * tex2D(_Illum, IN.uv_Illum).a;
                o.Alpha = c.a;
            }
    ENDCG
    

    还是逐行来看,首先是CGPROGRAM。这是一个开始标记,表明从这里开始是一段CG程序(我们在写Unity的Shader时用的是Cg/HLSL语言)。最后一行的ENDCG与CGPROGRAM是对应的,表明CG程序到此结束。

    接下来是是一个编译指令:#pragma surface surf Lambert,它声明了我们要写一个表面Shader,并指定了光照模型。它的写法是这样的

    #pragma surface surfaceFunction lightModel [optionalparams]

    • surface - 声明的是一个表面着色器
    • surfaceFunction - 着色器代码的方法的名字
    • lightModel - 使用的光照模型。

    所以在我们的例子中,我们声明了一个表面着色器,实际的代码在surf函数中(在下面能找到该函数),使用Lambert(也就是普通的diffuse)作为光照模型。

    接下来一句sampler2D _MainTex;,sampler2D是个啥?其实在CG中,sampler2D就是和texture所绑定的一个数据容器接口。等等..这个说法还是太复杂了,简单理解的话,所谓加载以后的texture(贴图)说白了不过是一块内存存储的,使用了RGB(也许还有A)通道,且每个通道8bits的数据。而具体地想知道像素与坐标的对应关系,以及获取这些数据,我们总不能一次一次去自己计算内存地址或者偏移,因此可以通过sampler2D来对贴图进行操作。更简单地理解,sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3D,samplerCube等等格式。

    解释通了sampler2D是什么之后,还需要解释下为什么在这里需要一句对_MainTex的声明,之前我们不是已经在Properties里声明过它是贴图了么。答案是我们用来实例的这个shader其实是由两个相对独立的块组成的,外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;而现在我们是在CGPROGRAM...ENDCG这样一个代码块中,这是一段CG程序。对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明。于是其实sampler2D _MainTex;做的事情就是再次声明并链接了_MainTex,使得接下来的CG程序能够使用这个变量。

    终于可以继续了。接下来是一个struct结构体。相信大家对于结构体已经很熟悉了,我们先跳过之,直接看下面的的surf函数。上面的#pragma段已经指出了我们的着色器代码的方法的名字叫做surf,那没跑儿了,就是这段代码是我们的着色器的工作核心。我们已经说过不止一次,着色器就是给定了输入,然后给出输出进行着色的代码。CG规定了声明为表面着色器的方法(就是我们这里的surf)的参数类型和名字,因此我们没有权利决定surf的输入输出参数的类型,只能按照规定写。这个规定就是第一个参数是一个Input结构,第二个参数是一个inout的SurfaceOutput结构。

    它们分别是什么呢?Input其实是需要我们去定义的结构,这给我们提供了一个机会,可以把所需要参与计算的数据都放到这个Input结构中,传入surf函数使用;SurfaceOutput是已经定义好了里面类型输出结构,但是一开始的时候内容暂时是空白的,我们需要向里面填写输出,这样就可以完成着色了。先仔细看看INPUT吧,现在可以跳回来看上面定义的INPUT结构体了:

    struct Input {
    	float2 uv_MainTex;
    };
    

    作为输入的结构体必须命名为Input,这个结构体中定义了一个float2的变量…你没看错我也没打错,就是float2,表示浮点数的float后面紧跟一个数字2,这又是什么意思呢?float和vec都可以在之后加入一个2到4的数字,来表示被打包在一起的2到4个同类型数。比如下面的这些定义:

    //Define a 2d vector variable
    vec2 coordinate;
    //Define a color variable
    float4 color;
    //Multiply out a color
    float3 multipliedColor = color.rgb * coordinate.x;
    

    在访问这些值时,我们即可以只使用名称来获得整组值,也可以使用下标的方式(比如.xyzw,.rgba或它们的部分比如.x等等)来获得某个值。在这个例子里,我们声明了一个叫做uv_MainTex的包含两个浮点数的变量。

    如果你对3D开发稍有耳闻的话,一定不会对uv这两个字母感到陌生。UV mapping的作用是将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段。在CG程序中,我们有这样的约定,在一个贴图变量(在我们例子中是_MainTex)之前加上uv两个字母,就代表提取它的uv值(其实就是两个代表贴图上点的二维坐标 )。我们之后就可以在surf程序中直接通过访问uv_MainTex来取得这张贴图当前需要计算的点的坐标值了。

    如果你坚持看到这里了,那要恭喜你,因为离最后成功读完一个Shader只有一步之遥。我们回到surf函数,它的两有参数,第一个是Input,我们已经明白了:在计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出。第二个参数是一个可写的SurfaceOutput,SurfaceOutput是预定义的输出结构,我们的surf函数的目标就是根据输入把这个输出结构填上。SurfaceOutput结构体的定义如下

    struct SurfaceOutput {
        half3 Albedo;     //像素的颜色
        half3 Normal;     //像素的法向值
        half3 Emission;   //像素的发散颜色
        half Specular;    //像素的镜面高光
        half Gloss;       //像素的发光强度
        half Alpha;       //像素的透明度
    };
    

    这里的half和我们常见float与double类似,都表示浮点数,只不过精度不一样。也许你很熟悉单精度浮点数(float或者single)和双精度浮点数(double),这里的half指的是半精度浮点数,精度最低,运算性能相对比高精度浮点数高一些,因此被大量使用。

    在例子中,我们做的事情非常简单:

    half4 c = tex2D (_MainTex, IN.uv_MainTex);
    o.Albedo = c.rgb;
    o.Alpha = c.a;
    

    这里用到了一个tex2d函数,这是CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。这里对_MainTex在输入点上进行了采样,并将其颜色的rbg值赋予了输出的像素颜色,将a值赋予透明度。于是,着色器就明白了应当怎样工作:即找到贴图上对应的uv点,直接使用颜色信息来进行着色,over。

    接下来…

    我想现在你已经能读懂一些最简单的Shader了,接下来我推荐的是参考Unity的Surface Shader Examples多接触一些各种各样的基本Shader。在这篇教程的基础上,配合一些google的工作,完全看懂这个shader示例页面应该不成问题。如果能做到无压力看懂,那说明你已经有良好的基础可以前进到Shader的更深的层次了(也许等不到我的下一篇教程就可以自己开始动手写些效果了);如果暂时还是有困难,那也没有关系,Shader学习绝对是一个渐进的过程,因为有很多约定和常用技巧,多积累和实践自然会进步并掌握。

    在接下来的教程里,打算通过介绍一些实际例子以及从基础开始实际逐步动手实现一个复杂一点的例子,让我们能看到shader在真正使用中的威力。我希望能尽快写完这个系列,但是无奈时间确实有限,所以我也不知道什么时候能出炉…写好的时候我会更改这段内容并指向新的文章。您要是担心错过的话,也可以使用邮件订阅或者订阅本站的rss(虽然Google Reader已经关了- -)。

    展开全文
  • ShaderForge插件介绍详解

    万次阅读 2017-12-19 21:41:47
    ShaderForge简介ShaderForge是适用于Unity,基于节点的着色器编辑器 。它可让您更轻松地创建自己的着色器 ,而不需要使用代码。开始以之前我想你已经下载好了插件,如果没有的话可以从下方的链接获取。前言1.官网...
  • Shader山下(一)第一个Shader

    千次阅读 2016-10-13 13:55:09
    学习Unity3D就得学Shader,然而新手学习Shader往往不知道从何处下手,没有找对门,谈何入门。 本系列主要介绍Shader的一些基础知识,希望可以带你找对门,然后入得了门。
  • 什么是Shader

    千次阅读 2011-09-04 23:50:54
    光看字面的意思「Shader」不知道是什麼玩意兒,硬翻成中文「著色器」似乎也難以摸著頭緒!剛開始接觸圖學的我完全搞不懂它有什麼作用,然後盲目地學著OpenGL:P直到老師說:「只要你學會Shader,就可以做到別人辦不...
  • ShaderShader官方示例

    千次阅读 2018-12-20 15:42:59
    Surface Shader示例 在表面着色器 。此页面上的示例显示如何使用内置照明模型。有关如何实现自定义光照模型的示例,请参阅Surface Shader光照示例。 简单着色器 例 我们将从一个非常简单的Shader开始,并在此基础上...
  • 【一步步学OpenGL 4】-《着色器》

    万次阅读 多人点赞 2016-12-18 17:12:32
    教程4:着色器原文:http://ogldev.atspace.co.uk/www/tutorial04/tutorial04.html背景:从这篇教程开始,我们将使用shader着色器来实现每一个效果和技术点。着色器是目前做3D图形最流行的方式。在某种程度上我们...
  • 作为一个系统介绍Unity3D中Shader编写的系列文章的开篇,本文的第一部分系列文章的前言,然后第二部分介绍了这个系列文章中我们会使用的游戏场景创建方式,最后一部分讲解了如何在Unity中创建和使用Shader,为后面...
  • Unity Shader Graph初次尝试

    万次阅读 2020-02-24 09:56:37
    软件环境 Unity Version: 2018.1.2f1 边缘发光材质效果 创建工程 打开Unity并创建一个新工程 ... Package Manager打开包管理器,安装二个依赖包: ...2. Shader Graph Lightweight Render Pipeline ...
  • 本次更新放出的Shader为透明系列的3个Shader和标准的镜面高光Shader的两个Shader。由易到难,由入门级到应用级,难度梯度合理。 依然是先放出游戏场景的exe和运行截图。 本期用的模型为妙蛙草。 【可运行...
  • 从这篇文章开始, Shader系列博文将继续开始更新。且在这次重启,这个系列文章会更多专注于实际Shader的书写,力求推出更多具有特色和实用性的Shader,概念性的东西在原则上上是不会再多讲的。 作为可编程Shader...
  • 这篇文章主要讲解了如何在Unity3D中分别使用Surface Shader和Vertex & Fragment Shader实现边缘发光Shader。 一、最终实现的效果 边缘发光Shader比较直观的一个运用便是模拟宇宙中的星球效果。将本文实现的边缘...
  • 概要:本文对Unity5中全新的三种Shader模板的源码进行了解析,然后还讲解了运动模糊屏幕特效的实现方法。 Unity5和之前的书写模式有了一定的改变。Unity5时代的Shader Reference官方文档也进一步地变得丰满。主要...
  • 本文主要讲解了Unity中SurfaceShader的具体写法,以及几个常用的CG函数的用法。 在这里先说明一下,表面着色器将分为两次讲解,本文介绍表面着色器的基本概念和一些写法,用内置的兰伯特光照模式来进行Surface ...
  • 本篇文章中,我们学习了Unity Shader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照、材质与颜色的具体写法。写了6个Shader作为本文Shader讲解的实战内容,最后创建了一个逼真的暴风雪场景...
  • 本篇文章将分析如何在Unity中基于Shader实现高斯模糊屏幕后期特效。 首先放出最终的实现效果。如下几幅图,是在Unity中使用本文所实现的Shader得到的高斯模糊屏幕后期特效与原始图的效果对比图。 写实风格的...
1 2 3 4 5 ... 20
收藏数 67,383
精华内容 26,953
关键字:

shader