庄懂的TA笔记(十四)<特效:流动 + 扰动>
效果展示:
正文:
大纲:
一、增广:
1、排序问题:
造成这个问题的原因是,他在取背景前,小人的胳膊不算是透明的,所以在编译过程中他就是被忽略的透明。
透贴问题 Detach Attach Zwrite Off 解决。(如何使用呢?这里暂时没讲)
判断 前方物体,是否遮挡了后方物体。并判断前方物体是否透明,Z深度像素点,是否更靠前,更近。
2、Alpha 通道预乘问题:
两种图片类型:
左图为,没预乘图。
右图为,预乘贴图。
什么是预乘呢?
就是吧颜色,RGB图片 和 透贴 乘一下,然后放在放到RGB里面。
需要注意什么呢?
在写,AB时(预乘时), 可以用 One OneMinusSrcAlpha的混合方式。
在写,AD时(不预乘时),可以用 SrcAlpha OneMinusSrcAlpha或 在shader里做乘法的混合方式。
3、AB AD 代码改进:
这里,实际上和上一篇的 笔记 记录的一致,AB,和AD 的区别 就在于:
Blend One One 和 Blend One OneMinusSrcAlpha .
二、UV流动效果实现:
1、演示· Ghost Flow
控制参数 设计:(定义材质面板)
1、添加噪波纹理 _NoiseTex
2、控制噪波强度 _NoiseInt
3、控制Flow速度 _FlowSpeed
知识点:
整体表现是 有亮,有暗(既对背景做提亮,也会对背景压暗),如果为这种直观感受,一般这种就算是AB。
如果是对所有背景做一个提亮,那一半就是AD。
2、代码 · GhostFlow
3、代码 · GhostFlow;
frac(取余,就是取小数点的意思,否则只取整数观感上是没有变化的).原因是部分低配机的情况下,不取余会花掉,在深入下,花掉的原因是 Time是从开了unity后,就一直无限增长的容易溢出,取余后,就不会了。
例图:
顶点shader:
让UV1(噪波UV)流动:
1、TRANSFORM_TEX支持贴图缩放
2、对V轴 加上 随时间变化的 偏移量,实现流动。_Time.(X,Y,Z)分3级,从慢到快,递增2倍速。
像素shader:
1、采样噪波图,只取单通道,R。
2、获得FinalRGB.
3、计算 opacity 透贴。
Remap噪波图(从0~1映射到0~2),以 1 为 中间值。lerp(1,var_NoiseTex * 2 , _NoiseInt*2);
截去噪波负值
计算opacity = 透贴 * 总不透明度 * 噪声图;
返回输出:float4 (FinalRGB,opacity);
代码示例:
Shader "Unlit/Sc014Flow01"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_NoiseTex ("_NoiseTex", 2D) = "gray" {}
_NoiseInt ("噪波强度",Range(0,5))=1
_FlowSpeed("流动速度",Range(-10,10))=5
_Cutout("透贴",Range(0,1))=0.5
}
SubShader
{
Tags {
"Queue"="Transparent"
"RenderType"="Transparent"
"ForceNoShadowCasting"="True" // 关闭阴影投射
"IgnoreProjector"="True" // 不响应投射器
}
LOD 100
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Blend One OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
UNITY_INSTANCING_BUFFER_START( Props )
// UNITY_DEFINE_INSTANCED_PROP( float4, _Color)
UNITY_INSTANCING_BUFFER_END( Props )
uniform sampler2D _MainTex;//uniform float4 _MainTex_ST;
uniform sampler2D _NoiseTex;uniform float4 _NoiseTex_ST;
uniform float _Cutout;
uniform float _NoiseInt;
uniform float _FlowSpeed;
//输入结构
struct VertexInput
{
float4 vertex : POSITION;
float2 uv0 : TEXCOORD0;
};
//顶点输出结构
struct VertexOutput
{
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0; //采样主贴图
float2 uv1 : TEXCOORD1; //采样噪波图
};
//输出结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v)
{
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv0 = v.uv0;
o.uv1 = TRANSFORM_TEX(v.uv0,_NoiseTex);
o.uv1.y = o.uv1.y + frac(_Time.x) * _FlowSpeed;
return o ;
}
//色彩输出结构
float4 frag(VertexOutput i) : COLOR
{
float4 var_mainTex = tex2D(_MainTex,i.uv0);
float var_noiseTex = tex2D(_NoiseTex,i.uv1).r;
float noise = lerp(1,var_noiseTex * 2,_NoiseInt); // var_noiseTex * 2 == 将 noise 的值域 扩大到 0 - 2 . 并用lerp,加以控制。
noise = max(0,noise); // 赋值截断,取消负值,就没有花花绿绿的东西了。
float3 finalRGB = var_mainTex;
float opacity = var_mainTex.a * _Cutout * noise;
return float4(finalRGB*opacity,opacity);//这里注意,最后FinalRGB乘了一个 透贴,是因为开始没有预乘,这里做了预乘。(预乘:指 吧透贴和色彩都放在RGB中)
//return noise;//输出噪波图
//return opacity;//输出透明噪波图
}
ENDCG
}
}
}
三、UV扰动效果实现:
1、演示 · Ghost Warp :
1、扰动,在Flow代码段基础上增加了一个 扭曲图,噪波图是单通道的,而 扭曲图是三通道的。
2、扭曲的是什么,是UV,UV有几个分量,有两个分量,对不同的分量,要有不同的方向。所以,扭曲图是有两个通道,控制扭曲方向的.(这里为了减少贴图采样的计算量,将噪波图合并入 扭曲图)
RG =扭曲图
B = 噪波图
3、追加 扭曲强度
2、准备Warp Tex : 如何做扭曲图
3、代码 · GhostWarp:
在这里,遇到了一个问题,就是在Gamma 和 Liner 两个色彩空间下,扰动效果不一样,如图。
解决方法有2
方法1:切换为Gamma色彩空间。
方法2:保持Liner 色彩空间,选中 用到的图片,取消勾选sRGB 。
这里问了群友为什么,为什么,gamma 和 liner 不同色彩空间下,会有不同UV偏移?
群友一位大佬提供了一个解释链接:
Gamma校正 - LearnOpenGL CN
大概意思为 引擎中,与 显示器 中,因硬件算法原因,会有Pow2.2的色彩亮度差别,这个pow2.2是弥补掉那个线性差,从而达到合理的观察效果。(没读完,理解可能相差甚远)