https://assetstore.unity.com/packages/vfx/shaders/energy-shield-effect-with-transition-and-hit-response-100109
因为想做个护盾从Unity Asset Store找到了这个资源包,学习了一下参数配置。
调整效果总不满意就打开Shader源文件看了一看,收获颇多。
- Rim Shader 边缘发光效果
- Shader中获取法线和点到视角向量的方式
- smoothstep与Lerp的不同
- 固定坐标值的含义(视角坐标系
Rim的含义
本质就是边缘发光,参考边缘发光Shader等用法,在光滑面上效果是挺好的。
但我好死不死主要用在平面上,从上方的图片可以看到俯视脚下正面看不到水平护盾,斜面的护盾又亮得过分。再不知道rim为何物的情况下调参数许久都没找到切入点。
获取法线和点到视角向量
知道rim是边缘发光后根据现有知识知道渲染面的法线和视角向量做点积可以轻松算出cos夹角来做是否发光的判断。
struct v2f
{
float2 uv : TEXCOORD0; // texture coordinate
float4 pos : SV_POSITION; // clip space position
half3 rimN : TEXCOORD1;
half3 rimV : TEXCOORD2;
float4 objectSpacePos : TEXCOORD3;
};
一开始很很疑惑i.rimN取了一个TEXCOORD1,这怎么算法线?难道语法里有后门让每张贴图的参数代表不同信息?
后继续阅读代码法线如下内容,其实就是先声明一个然后用正式数据替换掉。
o.rimN = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
float3 p = UnityObjectToViewPos(v.vertex);
o.rimV = normalize(-p);
smoothstep与Lerp的不同
float colorRim = smoothstep(_ColorRimMin, _ColorRimMax, vdn)
public static float Lerp(float a, float b, float t);
Lerp种第3个参数是控制器,根据0到1按先行比例返回从a到b中的一个值。
smoothstep则类似他的反函数,根据第一第二参数的对比返回0到1的值。
我的需求只要让夹角小时发亮高一些,并且不随角度变化最开始的问题就能解决。但我发现默认的RimMax配置居然超过了1,最大为4。
超过1的色彩输出有意义吗?滤清各种误解后意识到至少有两点:
- smoothstep是和Lerp相反的计算方式,RimMax值越大返回的值越小。
- 另外colorRim会与贴图颜色相乘输出最终颜色,超过1的时候对于任何原本不足1的值都可以起放大作用。比如(0.25,0.25,1)的颜色乘以4最终就成了白色。
固定向量 x 法线向量
代码中有一段
dot(_ShieldDirection.xyz, i.rimN)
其中_ShieldDirection的定义是固定值
_ShieldDirection("ShieldDirection", Vector) = (1,0,0,0)
用平面测了半天后没搞懂换了个球体上来就很清晰了,图中是_ShieldDirection取值(0,1,0)时的表现。
- 理解为视角坐标系正上
- X轴正向为视角坐标系正右
- Z轴正向为视角坐标系正后