贴图漫反射(MainTex)+高光反射+边缘光
Shader "My/Light/RimLight" { Properties { _MainTex("Main Tex", 2D) = "white" {} _Color("Diffuse Color", Color) = (1, 1, 1, 1) //类似之前的Diffuse _Specular("Specular", Color) = (1, 1, 1, 1) //高光反射颜色 _Gloss("Gloss", Range(8.0, 256)) = 20 //高光区域大小 _RimColor("Rim Color", Color) = (1, 1, 1, 1) //边缘光颜色 _RimPower("Rim Power", Range(0.7, 9)) = 4 //边缘光强度 } SubShader { Pass { Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" sampler2D _MainTex; float4 _MainTex_ST; fixed4 _Color; fixed4 _Specular; float _Gloss; fixed4 _RimColor; float _RimPower; struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; //顶点法线 float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 worldNormal : TEXCOORD1; float3 worldPos: TEXCOORD2; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { fixed3 worldNormal = normalize(i.worldNormal); fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); //指向光源向量(世界空间) fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb; //取贴图颜色作为漫反射颜色 fixed3 ambientColor = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo; //环境光,这里需要*albedo吗? fixed lambert = max(0, dot(worldNormal, worldLightDir)); //表面法线和光线方向夹角的cos值成正比 fixed3 diffuseColor = _LightColor0.rgb * albedo * lambert; //漫反射计算公式 fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)); //视线方向(顶点到相机) //fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal)); //fixed3 specularColor = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, worldViewDir)), _Gloss); //phong模型高光反射计算公式 fixed3 halfDir = normalize(worldLightDir + worldViewDir); // blinn模型引入的h向量 fixed3 specularColor = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss); // blinn模型高光反射计算公式(更亮, 高光区域更大) float rim = 1 - abs(dot(worldNormal, worldViewDir)); //正对视线时边缘光最弱(0), 垂直视线时最强(1) rim = pow(rim, _RimPower); //_RimPower>1时, 正对附近缓慢变大, 快到垂直了快速变大; fixed4 c = fixed4(ambientColor + diffuseColor + specularColor, 1); c.rgb = c.rgb * (1-rim) + _RimColor.rgb * rim; return c; } ENDCG } } Fallback "Specular" }
对rim因子增加一个power是为了让其可以非线性变化
a) >1时
b) <1时
不足
a) 边缘存在锯齿
b) 背面也有边缘光,且和前面是一样的
参考
Shader学习——边缘光 - 简书 (jianshu.com)
【玉兔 | 图形学与游戏开发】游戏中的人物边缘发光效果是如何实现的?码农小姐姐手把手教你写Shader | 2022开工啦,快来学习!_哔哩哔哩_bilibili
标签:MainTex,Color,fixed3,边缘,rgb,Specular,worldNormal,简单 From: https://www.cnblogs.com/sailJs/p/17121726.html