Unity Shader案例03-------自发光效果

 

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
Shader "CLF/SetLightting"
{
    Properties
    {
        _MainColor("MainColor", Color) = (0,0,0,1) //模型主颜色
 
        _InSideRimColor("InSideRimColor", Color) = (1,1,1,1)//内边缘光颜色
        _InSideRimPower("InSideRimPower", Range(0.0,5)) = 0 //边缘光强度  ,这个值可以控制菲涅尔影响范围的大小,这个值越大,效果上越边缘化
        _InSideRimIntensity("InSideRimIntensity", Range(0.0, 10)) = 0  //边缘光强度系数 这个值是反射的强度, 值越大,返回的强度越大,导致边缘的颜色不那么明显 
 
        _OutSideRimColor("OutSideRimColor", Color) = (1,1,1,1)//外边缘光颜色
        _OutSideRimSize("OutSideRimSize", Float) = 0 //因为外边缘光,需要把模型外扩,这是外扩大小
        _OutSideRimPower("OutSideRimPower", Range(0.0,5)) = 0 //边缘光强度  ,这个值可以控制菲涅尔影响范围的大小,这个值越大,效果上越边缘化
        _OutSideRimIntensity("OutSideRimIntensity", Range(0.0, 10)) = 0  //边缘光强度系数 这个值是反射的强度, 值越大,返回的强度越大,导致边缘的颜色不那么明显 
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100
        Pass  //内边缘光pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
            uniform float4 _MainColor;
            uniform float4 _InSideRimColor;
            uniform float  _InSideRimPower;
            uniform float _InSideRimIntensity;
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
 
            };
 
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float3 normal : TEXCOORD1;
                float4 vertex : SV_POSITION;
                float4 vertexWorld : TEXCOORD2;
 
            };
            v2f vert(appdata v)
            {
                v2f o;
                o.normal = mul(unity_ObjectToWorld, float4(v.normal,0)).xyz;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vertexWorld = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }
 
            fixed4 frag(v2f i) : SV_Target
            {
                i.normal = normalize(i.normal);//下面计算方式套用菲涅尔计算
                float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - i.vertexWorld.xyz);//获取单位视角方向   相机世界空间位置减去顶点世界空间位置
                half NdotV = max(0, dot(i.normal, worldViewDir));//计算法线方向和视角方向点积,约靠近边缘夹角越大,值约小,那就是会越在圆球中间约亮,越边缘约暗
                NdotV = 1.0 - NdotV;//这里需求是越边缘约亮,所以需要反一下,这里用1 减下
                float fresnel = pow(NdotV,_InSideRimPower) * _InSideRimIntensity;//使用上面的属性参数,这里不多说
                float3  Emissive = _InSideRimColor.rgb * fresnel; //配置上属性里面的内边缘光颜色
                return _MainColor + float4(Emissive,1);//最后加在本体主颜色就即可
            }
            ENDCG
        }
 
        Pass  //外边缘光pass
        {
            Cull Front   //需要正面剔除,否则模型主pass渲染会看不到
            Blend SrcAlpha One // 需要设置成透明叠加
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
 
             uniform float4 _OutSideRimColor;
             uniform float  _OutSideRimSize;
             uniform float  _OutSideRimPower;
             uniform float  _OutSideRimIntensity;
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
 
                float4 tangent : TANGENT;
 
            };
 
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float3 normal : TEXCOORD1;
                float4 vertex : SV_POSITION;
                float4 vertexWorld : TEXCOORD2;
 
            };
            v2f vert(appdata v)
            {
                v2f o;
                o.normal = mul(unity_ObjectToWorld, float4(v.normal,0)).xyz;
                v.vertex.xyz += v.normal * _OutSideRimSize;  //顶点进行外扩
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.vertexWorld = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }
 
            fixed4 frag(v2f i) : SV_Target
            {
                i.normal = normalize(i.normal);//**下面计算方式套用菲涅尔计算区别在下面2点**
                //float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - i.vertexWorld.xyz);
                float3 worldViewDir = normalize(i.vertexWorld.xyz - _WorldSpaceCameraPos.xyz);//**区别1**:因为顶点外扩,法线不变, 这里需要反过来,顶点世界空间位置减去相机世界空间位置
                half NdotV = dot(i.normal, worldViewDir);
                //NdotV = 1.0-NdotV;//**区别2**:因为需求是发光内强外弱,在模型外扩之后,这里就不需要反了
                float fresnel = pow(saturate(NdotV),_OutSideRimPower) * _OutSideRimIntensity;//配置上属性里面的外边缘光颜色
                return float4(_OutSideRimColor.rgb,fresnel);//这里最终计算的值,只需要用来处理返回颜色的Alpha透明度
            }
            ENDCG
        }
    }
}

  

posted @   打工仔-也想飞  阅读(560)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界
点击右上角即可分享
微信分享提示