Unity-shader学习记录

文章目录

  • [1. Shader](#1. Shader)
    • [1.1 基本格式](#1.1 基本格式)
      • [1.1.1 SubShader](#1.1.1 SubShader)
      • [1.1.2 Pass](#1.1.2 Pass)
      • [1.1.3 CG语言](#1.1.3 CG语言)
      • [1.1.4 语义](#1.1.4 语义)
      • [1.1.5 引入](#1.1.5 引入)
    • [1.2 着色](#1.2 着色)
      • [1.2.1 顶点着色器](#1.2.1 顶点着色器)
      • [1.2.2 片元着色器](#1.2.2 片元着色器)
    • [1.3 物体着色流程](#1.3 物体着色流程)
      • [1.3.1 新建Shader](#1.3.1 新建Shader)
      • [1.3.2 新建材质](#1.3.2 新建材质)
      • [1.3.3 挂载材质](#1.3.3 挂载材质)
  • [2. 结构体](#2. 结构体)
    • [2.1 编写结构体](#2.1 编写结构体)
      • [2.1.1 简单结构体](#2.1.1 简单结构体)
      • [2.1.2 引入结构体后的Shader代码](#2.1.2 引入结构体后的Shader代码)
    • [2.2 unity封装的结构体](#2.2 unity封装的结构体)
      • [2.2.1 查看unity结构体](#2.2.1 查看unity结构体)
      • [2.2.2 常用的结构体](#2.2.2 常用的结构体)
      • [2.2.3 应用unity结构体](#2.2.3 应用unity结构体)
    • [2.3 案例1-小彩球](#2.3 案例1-小彩球)
      • [2.3.1 顶点着色器](#2.3.1 顶点着色器)
      • [2.3.2 片元着色器](#2.3.2 片元着色器)
      • [2.3.3 完整脚本](#2.3.3 完整脚本)
  • [3. Properties](#3. Properties)
    • [3.1 常用外部资产](#3.1 常用外部资产)
    • [3.2 外部着色](#3.2 外部着色)
      • [3.2.1 _Color](#3.2.1 _Color)
      • [3.2.2 完整脚本](#3.2.2 完整脚本)
    • [3.3 贴图](#3.3 贴图)
      • [3.3.1 _MainTex](#3.3.1 _MainTex)
      • [3.3.2 完整脚本](#3.3.2 完整脚本)
    • [3.4 案例2-图片与外部颜色叠加显示](#3.4 案例2-图片与外部颜色叠加显示)
  • [4. 漫反射](#4. 漫反射)
    • [4.1 基本储备](#4.1 基本储备)
      • [4.1.1 appdata_full](#4.1.1 appdata_full)
      • [4.1.2 相关代码](#4.1.2 相关代码)
    • [4.2 兰伯特算法](#4.2 兰伯特算法)
      • [4.2.1 公式](#4.2.1 公式)
      • [4.2.2 逐顶点脚本](#4.2.2 逐顶点脚本)
      • [4.2.3 逐像素脚本](#4.2.3 逐像素脚本)
    • [4.4 半兰伯特算法-案例3-漫反射材质球](#4.4 半兰伯特算法-案例3-漫反射材质球)
      • [4.4.1 公式](#4.4.1 公式)
      • [4.4.2 完整脚本](#4.4.2 完整脚本)
  • [5. 表面着色器](#5. 表面着色器)
    • [5.1 使用格式](#5.1 使用格式)
    • [5.2 viewDir](#5.2 viewDir)
      • [5.2.1 viewDir](#5.2.1 viewDir)
      • [5.2.2 完整脚本](#5.2.2 完整脚本)
    • [5.3 案例4-渐变发光小球](#5.3 案例4-渐变发光小球)

1. Shader

1.1 基本格式

1.1.1 SubShader

001是Shader的文件名

Shader有很多影响其行为的块SubShader

csharp 复制代码
Shader "Custom/001"
{
SubShader{    }	//干预着色器
}

在unity上方工具栏点击扩展,选择管理扩展,搜索ShaderlabVS,下载安装后编辑代码时会提示是否有误

1.1.2 Pass

同一个物体有很多状态

csharp 复制代码
Shader "Custom/001"
{
SubShader
    {
        //假如这里写水的渲染
        pass{    }	//通道
        //假如这里写石头的渲染
        pass{    }
    }
}

1.1.3 CG语言

直接和着色器对接的部分CG语言

csharp 复制代码
Shader "Custom/001"
{
    SubShader
    {
        pass
        {
            CGPROGRAM    //开始 CG 语言了
 
            ENDCG        // CG 语言结束了
        }
    }
}

1.1.4 语义

shader规定了一些词汇,获得一些信息,也可以去传递一些信息,这些词汇就叫做语义,用法就是

:语义词汇

CG语言:在CG语言里,Vector2的表达是float2,Vector3的表达是float3,Vector4的表达是float4

csharp 复制代码
//声明变量float4  //变量名称v  //POSITION就是语义,你只要:POSITION就能获取到模型的顶点
float4 v:POSITION

常用语义

:POSITION 获取到模型的顶点坐标

:NORMAL 法线坐标

:TEXCOORD0 第一套纹理坐标 //纹理坐标就UV坐标

:SV_POSITION 输出给像素着色器的屏幕坐标

:SV_TARGET 输出值直接用于渲染了

1.1.5 引入

shader引入后需要给引入的内容起个名字

csharp 复制代码
#pragma vertex vert      //引用顶点着色器
#pragma fragment frag    //引用片元着色器

1.2 着色

1.2.1 顶点着色器

1)坐标转换

模型的顶点位置是世界坐标下的,屏幕不一定能显示全面,shader只需要管屏幕看得到的东西就够了

世界坐标转屏幕坐标代码如下:

csharp 复制代码
//最后会得到,模型的屏幕坐标
UnityObjectToClipPos(这里输入模型的顶点世界坐标)

2)指定着色的点

shader里是不好随便去声明数据的,传入数据时,用的是括号传入

1.2.2 片元着色器

csharp 复制代码
//引入fragment //起名叫frag
#pragma fragment frag

//片元着色器方法  //直接输出渲染
float4 frag():SV_TARGET
{
    //输出白色
   return float4(1,1,1,1);
}

1.3 物体着色流程

1.3.1 新建Shader

新建一个Shader,这几个Shader任选一个,并将其重命名为001

点开Shader,脚本如下

csharp 复制代码
Shader "Custom/001"
{
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
			float4 vert(float4 v :POSITION):SV_POSITION
            {
            if (v.x <= 0)
	            {
	            	v.x = 0;	//x负方向的点不着色
	            }
            return UnityObjectToClipPos(v);
            }
 
            float4 frag():SV_TARGET
            {
            return float4(1,1,1,1);
            }
 
            ENDCG
        }
    }
}

1.3.2 新建材质

新建一个材质

在材质的shader处找到前面新建的001

1.3.3 挂载材质

选中需要着色的物体,在对象的材质处挂载刚刚新建的材质

2. 结构体

当需要继承很多数据时,一个括号就不方便管理,于是引入新语法,结构体

2.1 编写结构体

2.1.1 简单结构体

csharp 复制代码
 //这里结构体的名字是可以自己起的
 struct a2v
 {
 float4 vertex:POSITION;
 float3 normal:NORMAL;
 float4 texcoord:TEXCOORD0;
 }

2.1.2 引入结构体后的Shader代码

修改前面1.3.1里的shader脚本,引入结构体后如下:

csharp 复制代码
Shader "Custom/001"
{
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            //这里结构体的名字是可以自己起的
            struct a2v
            {
            float4 vertex:POSITION;
            float3 normal:NORMAL;
            float4 texcoord:TEXCOORD0;
            };
 
                    //传入并声明结构体
            float4 vert(a2v v):SV_POSITION
            {
             if (v.vertex.x <= 0)
	            {
	            	v.vertex.x = 0;	//x负方向的点不着色
	            }
                                   //调用结构体的vertex
            return UnityObjectToClipPos(v.vertex);
            }
 
            float4 frag():SV_TARGET
            {
            return float4(1,1,1,1);
            }
 
            ENDCG
        }
    }
}

2.2 unity封装的结构体

2.2.1 查看unity结构体

进入unity网站,在下载unity的界面处,选择对应的版本,在Win 处选择Bulit in shaders

下载完后解压,找到UnityCG.cginc文件,该文件里就可以看见unity已有的结构体

2.2.2 常用的结构体

csharp 复制代码
struct appdata_base {
    float4 vertex : POSITION;//顶点坐标
    float3 normal : NORMAL;//法线
    float4 texcoord : TEXCOORD0;//第一纹理坐标
    UNITY_VERTEX_INPUT_INSTANCE_ID    //ID信息
};
 
struct appdata_tan {
    float4 vertex : POSITION;//顶点坐标
    float4 tangent : TANGENT;//切线
    float3 normal : NORMAL;//法线
    float4 texcoord : TEXCOORD0;//第一纹理坐标
    UNITY_VERTEX_INPUT_INSTANCE_ID    //ID信息
};
 
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;        //顶点颜色
    UNITY_VERTEX_INPUT_INSTANCE_ID    //ID信息
};

2.2.3 应用unity结构体

引用结构体

#include"UnityCG.cginc"

csharp 复制代码
Shader "Custom/001"
{
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include"UnityCG.cginc"
 
                    //传入上述结构体
            float4 vert(appdata_base v):SV_POSITION
            {
                                    //调用结构体的vertex
            return UnityObjectToClipPos(v.vertex);
            }
 
            float4 frag():SV_TARGET
            {
            return float4(1,1,1,1);
            }
 
            ENDCG
        }
    }
}

2.3 案例1-小彩球

之前是最后传了一个颜色,不管哪个点,都显示一个颜色,这次是每个顶点需要不同的颜色

2.3.1 顶点着色器

声明了这个结构体,这个结构体会自带值,这个值就是后面的语义里所带的值

如果我们改变了这个结构体,在把它return出去,改变的值就会自己输出到后面的语义里,进行下一轮计算

csharp 复制代码
appdata_base vert(appdata_base v)
            {
            //我们在这里把顶点坐标改成了屏幕坐标,传回了appdata_base里
            v.vertex =UnityObjectToClipPos(v.vertex);
 
            //因为最后return了,所以v.vertex会被语义POSITION接收
            return v;
            }

2.3.2 片元着色器

1)在顶点着色器里修改的值,实际上是储存在语义里了,再次声明也是从语义里接收数据,所以只需要再次声明appdata_base,就可以接收到顶点着色器中修改过的数据

2)每一个顶点,对应着一个法线,每一个法线值,会映射成不同的【0,1】之间的值

csharp 复制代码
 float4 frag(appdata_base v):SV_TARGET
            {
            //-1,1	→	0,1
            //因为你是一组数,不是一个数,所以不能直接加0.5,让颜色随顶点坐标的法向量变化而变化
            float3 n = v.normal/2+float3(0.5,0.5,0.5);
            
            //n是float3,但返回的是float4,所以后面补一个1
            return float4(n,1);
            }

2.3.3 完整脚本

csharp 复制代码
Shader "Custom/001"
{
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include"UnityCG.cginc"
 
            appdata_base vert(appdata_base v)
            {
            v.vertex =UnityObjectToClipPos(v.vertex);
            return v;
            }
 
            float4 frag(appdata_base v):SV_TARGET
            {
                                    //因为你是一组数,不是一个数,所以不能直接加0.5
            float3 n = v.normal/2+float3(0.5,0.5,0.5);
 
            return float4(n,1);
            }
 
            ENDCG
        }
    }
}

3. Properties

3.1 常用外部资产

代码格式:

内部名称 外部名称 数据类型 赋值

csharp 复制代码
    Properties
    {
       //颜色
        _Color("颜色", Color) = (1,1,1,1)
 
        //图片
        _Tex("2D图片",2D) = "white"{}
        _Tex3("3D图片",3D) = "white"{}
        _Cube("Cube图片",CUBE)=""{}
 
        //数字
        _Float("Float数字",Float) = 0.5
        _Int("Int数字",Int) = 1
        _Range("范围",Range(0,100))=1
        _Vector("坐标",Vector)=(1,1,1,1)
    }

后面的数字设置也是,如果是没打钩 =0,打钩了就 =1

csharp 复制代码
    Properties
    {
        [Toggle] _MyToggle("MyToggle",float) =0
    }

引入内部,完整脚本

csharp 复制代码
Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        //颜色
        _Color ("颜色", Color) = (1,1,1,1)
 
        //图片
        _Tex("2D图片",2D) = "white"{}
        _Tex3("3D图片",3D) = "white"{}
        _Cube("Cube图片",CUBE)=""{}
 
        //数字
        _Float("Float数字",Float) = 0.5
        _Int("Int数字",Int) = 1
        _Range("范围",Range(0,100))=1
        _Vector("坐标",Vector)=(1,1,1,1)
    }
    SubShader
    {
        //这里是CG语言
        CGPROGRAM
 
        //****************************
        //这里就是把格式重写一遍,注意看,名称和上面是一样的
        //四个数字代表颜色
        fixed4 _Color;
 
        //普通图片
        sampler2D _Tex;
        //3D图片
        sampler3D _Tex3;
        //Cube图片
        samplerCUBE _Cube;
 
        //一个数字
        float _Float;
        int _Int;
        //这里是不需要很大的小数
        half _Range;
        float4 _Vector;
        //********************************
 
        ENDCG
    }
}

3.2 外部着色

3.2.1 _Color

_Color是脚本里使用的名称

"Color"是外部使用的名称

Color是声明的数据类型

csharp 复制代码
Properties
     {
     //内部使用的名称  //外部使用的名称	//声明的数据类型	//赋值(1,1,1,1)
    _Color("Color",Color)=(1,1,1,1)           
     }

3.2.2 完整脚本

用的时候在SubShader中还是要重新声明一下

csharp 复制代码
Shader "Custom/001"
{
Properties
     {
     //内部使用的名称  //声明的数据类型
    _Color("Color",Color)=(1,1,1,1)
         //外部使用的名称   //赋值(1,1,1,1)
     }
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include"UnityCG.cginc"
 
            //重新声明_Color
            float4 _Color ;
 
            appdata_base vert(appdata_base v)
            {
            v.vertex =UnityObjectToClipPos(v.vertex);
            return v;
            }
 
            float4 frag():SV_TARGET
            {
            //直接将接到的数据输出
            return _Color;
            }
            ENDCG
        }
    }
}

3.3 贴图

3.3.1 _MainTex

2D 2D图片资源

"white" {} 这个是unity之前准备好的图片资源,就是一个白图

备注:因为shader是一直运行的,不能加空的进去,会出问题,所以先加个白图

1)编辑脚本

csharp 复制代码
Properties
     {
    _Color("Color",Color)=(1,1,1,1)
 
    //本节新增
    _MainTex("MainTex",2D) = "white" {}
     }

2)挂载图片

将图片拖拽至Shader的MainTex

3.3.2 完整脚本

csharp 复制代码
Shader "Custom/001"
{
Properties
     {
    _MainTex("MainTex",2D) = "white"{}  
     }
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include"UnityCG.cginc"
  
            //承接2D图片在CG语言里是sampler2D    //起名为MainTex
            sampler2D _MainTex;
 
            appdata_base vert(appdata_base v)
            {
            v.vertex =UnityObjectToClipPos(v.vertex);
            return v;
            }
 
            float4 frag(appdata_base v):SV_TARGET
            {
            //转换贴图数据    //appdata_base中的贴图数据,取出xy轴数据(这里也可以理解为uv数据)
            float4 c =tex2D(_MainTex,v.texcoord.xy);
            return c;
            }
            ENDCG
        }
    }
}

3.4 案例2-图片与外部颜色叠加显示

csharp 复制代码
 float4 c =tex2D(_MainTex,v.texcoord.xy)*_Color;

颜色和颜色的叠加一般相乘即可

完整的代码如下:

csharp 复制代码
Shader "Custom/001"
{
Properties
     {
    _Color("Color",Color)=(1,1,1,1)
    _MainTex("MainTex",2D) = "white"{}
    
     }
SubShader
    {
        pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include"UnityCG.cginc"
 
            float4 _Color ;
 
            sampler2D _MainTex;
 
            appdata_base vert(appdata_base v)
            {
            v.vertex =UnityObjectToClipPos(v.vertex);
            return v;
            }
 
            float4 frag(appdata_base v):SV_TARGET
            {
            float4 c =tex2D(_MainTex,v.texcoord.xy)*_Color;
            return c;
            }
            ENDCG
        }
    }
}

4. 漫反射

4.1 基本储备

4.1.1 appdata_full

所需结构体

csharp 复制代码
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;        //顶点颜色
    UNITY_VERTEX_INPUT_INSTANCE_ID    //ID信息
};

4.1.2 相关代码

引入光

csharp 复制代码
#include "Lighting.cginc"

所用算法

csharp 复制代码
UnityObjectToWorldNormal()     //把物体的法线坐标,换算到世界坐标下
normalize()                    //把任何一个向量变成单位向量
dot()                          //点乘
max()                          //上文讲过
 
//以下要引用#include "Lighting.cginc"才能找到
 
_WorldSpaceLightPos0           //世界坐标下的光线坐标
_LightColor0                   //光线的颜色

4.2 兰伯特算法

4.2.1 公式

屏幕上对应点的颜色 = (光的颜色*物体的颜色)max(0,该点的法向量该点的光照方向)

4.2.2 逐顶点脚本

白色和黑色交界处有些方块块的感觉、照不到的地方全黑

csharp 复制代码
Shader "Custom/001"
{
 SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
            
            //新的引用
            #include "Lighting.cginc"
 
            //返回结构体        //引用结构体
            appdata_full vert (appdata_full v)
            {    
                //模型顶点坐标转屏幕坐标
                v.vertex = UnityObjectToClipPos(v.vertex);
                
                //获取法线坐标并转换成世界坐标下的法线坐标
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
 
                 //世界坐标下的光线坐标  //单位化坐标   //获取世界坐标下的光线坐标
                float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                
                 //上面的公式
                float3 diffuse =_LightColor0.rgb * v.color.rgb * max(0,dot(worldNormal,worldLight));
 
                //算出的值给颜色
                v.color = float4(diffuse,1);
                
                return v;
            }
 
 
            float4 frag (appdata_full v) : SV_Target
            {    
                //输出颜色    
                return float4(v.color) ;
            }
            ENDCG
        }
    }
}

4.2.3 逐像素脚本

白色和黑色交界处平滑过渡、照不到的地方全黑

顶点算法是在顶点着色器中写的,像素算法是在片元着色器中写的

顶点是初始值,经过一系列计算后,数据就会和想要的有些偏差

像素着色器离最后的显示比较近,所以出来的结果和想要的更一致

csharp 复制代码
Shader "Unlit/001"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            appdata_full vert (appdata_full v)
            {   
                v.vertex = UnityObjectToClipPos(v.vertex);
                return v;
            }
 
            float4 frag (appdata_full v) : SV_Target
            {
                //法线世界坐标
                float3 worldNormal = v.normal;
                //光线世界坐标
                float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                //计算颜色
                float3 diffuse =_LightColor0.rgb * v.color.rgb * max(0,dot(worldNormal,worldLight));
                
                //把颜色传进去
                return float4(diffuse,1) ;
            }
            ENDCG
        }
    }
}

4.4 半兰伯特算法-案例3-漫反射材质球

白色和黑色交界处平滑过渡、照不到的地方不是全黑

在光照不到的地方也能看见,只是比较暗,而不是全黑

4.4.1 公式

最终颜色 = 环境光+Cdiffuse

4.4.2 完整脚本

csharp 复制代码
Shader "Unlit/001"
{
     SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            appdata_full vert (appdata_full v)
            {
                v.vertex = UnityObjectToClipPos(v.vertex);
                return v;
            }
 
            float4 frag (appdata_full v) : SV_Target
            {
                float3 worldNormal = v.normal;
                float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
 
                //本节变动
                //获取环境光
                float3 anbient = UNITY_LIGHTMODEL_AMBIENT.xyz;
 
                //计算范围
                float halfLamient = dot(worldNormal,worldLight)*0.5+0.5;
 
                //计算反射强度
                float3 diffuse =_LightColor0.rgb * v.color.rgb *halfLamient;
 
                //反射光加光照强度
                float3 c = anbient + diffuse;
 
                return float4(c,1) ;
            }
            ENDCG
        }
    }
}

5. 表面着色器

5.1 使用格式

csharp 复制代码
    SubShader
    {
        CGPROGRAM
        #pragma surface surf Standard
        //给表面着色器配的输入结构体
        struct Input
        {
 
        }; 
        //表面着色器
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
 
        }
        ENDCG
    }

表面着色器的结构体

csharp 复制代码
        struct Input
        {
            float3 viewDir      //包含视图方向,用于计算视差效果、边缘光照等等。
            具有 COLOR 语义的 float4 - 包含插值的每顶点颜色。
            float4 screenPos    //包含反射或屏幕空间效果的屏幕空间位置。请注意,这不适合 GrabPass;您需要使用 ComputeGrabScreenPos 函数自己计算自定义 UV。
            float3 worldPos     //包含世界空间位置。
            float3 worldRefl    //在_表面着色器不写入 o.Normal_ 的情况下,包含世界反射矢量。有关示例,请参阅反光漫射 (Reflect-Diffuse) 着色器。
            float3 worldNormal  // 在_表面着色器不写入 o.Normal_ 的情况下,包含世界法线矢量。
            float3 worldRefl;   // INTERNAL_DATA - 在_表面着色器写入 o.Normal_ 的情况下,包含世界反射矢量。要获得基于每像素法线贴图的反射矢量,请使用 WorldReflectionVector (IN, o.Normal)。有关示例,请参阅反光凹凸 (Reflect-Bumped) 着色器。
            float3 worldNormal; // INTERNAL_DATA - 在_表面着色器写入 o.Normal_ 的情况下,包含世界法线矢量。要获得基于每像素法线贴图的法线矢量,请使用 WorldNormalVector (IN, o.Normal)。
        };

5.2 viewDir

5.2.1 viewDir

viewDir是一个向量,当它和法线向量点乘时:

答案>0 在该点的正对面

答案=0 和该点成90度

答案<0 和该点大于90度(在这个情况下,一般就是看不见了)

5.2.2 完整脚本

csharp 复制代码
Shader "Custom/001"
{
    Properties
    {
    //放图片进入
    _MainTex("MainTex",2D)="white"{} 
    }
 
    SubShader
    {
 
    CGPROGRAM
    #pragma surface surf Lambert
 
    sampler2D _MainTex;
 
    struct Input
    {
        float2 uv_MainTex;
        //直接获取viewDir
        float3 viewDir;
    };
 
    void surf(Input IN,inout SurfaceOutput o)
    {
                    //点乘在shader里的写法
        half dotp =dot(IN.viewDir,o.Normal);
                                               //如果大于0才会显示颜色,否则是黑色
        o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb*dotp;
    }
 
    ENDCG
    }
}

5.3 案例4-渐变发光小球

csharp 复制代码
Shader "Custom/001"
{
     Properties
    {
    _MainTex("MainTex",2D)="white"{} 
    _Color("Color",Color)=(0,0.5,0.5,0)
    //边缘光范围参数
    _Power("Power",Range(0.8,8)) = 3
    }
 
    SubShader
    {
    CGPROGRAM
    #pragma surface surf Lambert
 
    sampler2D _MainTex;
    float4 _Color;
    //接入参数
    float _Power;
 
    struct Input
    {
        float2 uv_MainTex;
        float3 viewDir;
    };
 
    void surf(Input IN,inout SurfaceOutput o)
    {
        o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb;         
        half dotp =dot(IN.viewDir,o.Normal);
 
                             //重新设置范围变化曲线
        o.Emission =_Color.rgb*pow((1-dotp),_Power);
    }
    ENDCG
    }
}

参考专栏

Unity中写shader

参考视频

Unity Shader基础详细讲解

相关推荐
Mister西泽2 小时前
线性代数-学习日记
学习
WMX10122 小时前
Hololens 2 上部署 Unity+MRTK 项目_模型着色
unity·游戏引擎·hololens
游乐码2 小时前
unity基础(八)协程
游戏·unity·c#·游戏引擎
sakiko_2 小时前
Swift学习笔记35-本地化
笔记·学习·swift
星幻元宇VR2 小时前
VR心理骑行设备:心理健康教育的新型互动体验
科技·学习·安全·vr
是一个Bug10 小时前
Agent(智能体)应用 的入门学习路径
学习·机器学习
2301_8090511410 小时前
Linux 网络编程 学习笔记
linux·网络·学习
eggcode11 小时前
【Qt学习】Linux(ARM架构)在线安装Qt6.x
linux·qt·学习·arm
_李小白12 小时前
【android opencv学习笔记】Day 26: 滤波算法之低通滤波与图像缩放插值
android·opencv·学习