教程链接:Overwatch Shield
项目链接:OverwatchShieldTemplate
Pipeline & Shader:Built-in,Unlit
本文是对 Overwatch Shield 学习过程的记录和总结,不是完全的翻译,更多的细节和图文建议跳转原博
效果分析
使用守望先锋中Reinhardt的护盾作为参考
整体观察
可以看出护盾是半透明的,带有一层基色,可以微微照亮周边区域
绕着护盾走可以发现,护盾的背面也可以显示(关闭Cull),并且有明显的厚度
蜂窝纹理
蜂窝会从中心沿x轴方向搏动,仔细观察还可以发现蜂窝并不是同时搏动的
蜂窝状电流
电流沿着蜂窝状边缘向外扩散,不能难发现扩散的形状一个菱形
所以这个效果其实是一个从护盾中心,从点变大的菱形框点亮蜂窝边缘的过程
固定边缘
仔细看就会发现边缘效果由两部分组成:固定边缘、相交边缘
相交边缘
相交边缘的效果基本和固定边缘一样
效果总结
- 基础效果:整体透明,带有基色,Cull Off
- 蜂窝纹理:蜂窝纹理从护盾中心沿x轴搏动,带有一定先后顺序
- 电流脉冲:蜂窝电流从护盾中心按菱形扩散
- 固定边缘:越边缘颜色越实
- 相交边缘:与其他物体交叉处有高亮
- 自发光:护盾可以微微照亮周边
项目设置
场景方面,模拟了视频(图片)中的物体:
护盾与地面相交,有物体穿过护盾,方便测试效果
另外项目的色彩空间使用了线性空间,因为线性空间的精度更高
更多关于颜色空间的内容,可以查看GAMMA AND LINEAR SPACE - WHAT THEY ARE AND HOW THEY DIFFER和Unity User Manual Color space
Shader编写
基础效果
目标效果:整体透明,带有基色,Cull Off
没啥东西,改 Tag,关 Cull,设置 Blend,完事
Pass
{
Tags {
"RenderType" = "Transparent" "Queue" = "Transparent"}
Cull off
Blend SrcAlpha one
HLSLPROGRAM
// ...
fixed4 frag (v2f i) : SV_Target
{
return _Color;
}
ENDHLSL
}
基础效果图
蜂窝搏动
目标效果:蜂窝纹理从护盾中心沿x轴搏动,带有一定先后顺序
效果拆分:
- 蜂窝纹理 + 整体呼吸效果
- 打乱呼吸顺序
- 呼吸效果沿x轴扩散
1.蜂窝纹理 + 整体呼吸效果
fixed4 frag (v2f i) : SV_Target
{
// 蜂窝图案
fixed4 pulseTex = tex2D(_PulseTex, i.uv);
fixed4 pulseTerm = pulseTex * _Color * _PulseIntensity;
// 呼吸效果
pulseTerm *= abs(sin(_Time.y * _PulseTimeScale));
return fixed4(_Color.rgb + pulseTerm.rgb, _Color.a);
}
2.打乱呼吸顺序
打乱顺序的方法有很多,因为这里使用的蜂窝纹理刚好有深浅变化,可以直接用来作为决定呼吸顺序的因子
这里的代码会让 r 通道越大的地方亮的越早
fixed4 frag (v2f i) : SV_Target
{
// 蜂窝图案
fixed4 pulseTex = tex2D(_PulseTex, i.uv);
fixed4 pulseTerm = pulseTex * _Color * _PulseIntensity;
float breath = _Time.y * _PulseTimeScale;
float pulseOffset = pulseTex.r * _PulseTexOffsetScale;
// 随机呼吸效果
pulseTerm *= abs(sin(breath + pulseOffset));
return fixed4(_Color.rgb + pulseTerm.rgb, _Color.a);
}
为了防止 sin() 的负值导致奇怪的结果出现,需要滤去负值
同时也不希望负值直接被处理为常数导致图案无变化,使用了 abs()
3.呼吸效果沿x轴扩散
由于制作模型时,将模型的中心点设置在了正中心(默认是底部中心),可以直接取模型空间的x坐标来确定顶点与中心轴的距离
fixed4 frag (v2f i) : SV_Target
{
// 蜂窝图案
fixed4 pulseTex = tex2D(_PulseTex, i.uv);
fixed4 pulseTerm = pulseTex * _Color * _PulseIntensity;
float breath = _Time.y * _PulseTimeScale;
float pulseOffset = pulseTex.r * _PulseTexOffsetScale;
float horizontalDist = abs(i.posOS.x);
float xOffset = horizontalDist * _PulsePosScale;
// 沿x轴扩散的随机呼吸效果
pulseTerm *= abs(sin(breath + pulseOffset - xOffset));
return fixed4(_Color.rgb + pulseTerm.rgb, _Color.a);
}
电流脉冲
目标效果:蜂窝电流从护盾中心按菱形扩散
大体上思路和蜂窝搏动效果有很多相似的地方
效果拆分:
- 蜂窝电流 + 整体呼吸效果
- 蜂窝电流以菱形从护盾中心扩散
1.蜂窝电流 + 整体呼吸效果
fixed4 frag (v2f i) : SV_Target
{
// 蜂窝搏动
// ...
// 蜂窝电流
fixed4 hexEdgeTex = tex2D(_HexEdgeTex, i.uv);
fixed4 hexEdgeTerm = hexEdgeTex * _HexEdgeColor * _HexEdgeIntensity;
// 呼吸
float edgeBreath = _Time.y * _HexEdgeTimeScale;
hexEdgeTerm *= saturate(sin(edgeBreath));
// 只看电流