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基础详细讲解

相关推荐
狂人开飞机4 分钟前
11、UI系统
游戏引擎·godot
zr想努力16 分钟前
GAS学习(UE5自用)
学习·ue5
她说..23 分钟前
MySQL JSON 处理学习文档
学习·mysql·json
真鬼12327 分钟前
【Unity AI】Untiy链接cursor与MCP
unity·游戏引擎
资讯综合42 分钟前
一年级数学机构怎么选?与学习阶段相匹配的线上思维课程与线下机构差异分析
学习
M78佐菲1 小时前
51单片机学习笔记(2)
linux·笔记·嵌入式硬件·学习·51单片机
子不语1801 小时前
LabVIEW和PLC通过OPC通信
学习·自动化·plc
萧行之1 小时前
Observable Plot 源码深度解析——4 核心抽象逐项学习
前端·学习·数据可视化
浔溺1 小时前
al+大数据每日学习笔记37
大数据·笔记·学习