广告牌+序列帧的Shader效果
首先清点自己需要什么资源,序列帧动画需要的是序列帧的图片
序列帧 - 免费 免费下载 - 爱给网
对于图片使用时黑边的问题
AlphaTest Greater 0.5
的意思是:
只有当片元(Fragment)的 Alpha 值 > 0.5 时,才通过 Alpha 测试,才会写入颜色缓冲。
AlphaTest
是 Unity 内置渲染管线(Built-in RP) 中的一个固定功能(Fixed Function Pipeline),但是在直接使用上,没有discard好用
更现代的做法:if (alpha <= 0.5) discard;
这和 AlphaTest Greater 0.5 是逻辑等价的,但更灵活且适用于 URP/HDRP/SRP 等。
广告牌,是通过修改vertex的位置,让frag接受到变化后的三角面片覆盖区域,需要的是修改vert 中的o.pos = UnityObjectToClipPos(*****);
构建 视角方向为normal,向上为固定轴,点乘出第三向量,然后通过第三向量和normal点乘得到真正的三个基向量(局部坐标变换矩阵),
// Suppose the center in object space is fixed
float3 center = float3(0, 0, 0);
float3 viewer = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos, 1));
这里的000,使用的时候,没有规定坐标系,而当它与model坐标系的vertexPos相计算 的时候
这个000就会被 归到model坐标系下,,这是无坐标系点的吸附(为了达成广告牌,逻辑层面上的一种解释)
这三个基向量构成的矩阵,如果乘以(0,0,0)到model坐标系下的一个xyz点 的向量,
会对xyz的数值进行Transform,而这个Transform,实际上是把在model坐标系下的向量表示值,换成了在新local坐标系下的向量表示值,
宏观上来讲,向量的方向没有发生变化,只是在新的坐标系里,xyz都变了,
这个新的坐标系称为local,
而重点是,如果此时用local里的xyz值再回到model坐标系里,此时xyz都是local坐标系的表示方法,如果强行用model坐标系表示,就产生了旋转差异
序列帧逻辑
VertexOutput o = (VertexOutput)0;
//v.vertex.xyz += v.normal * 0.03; // 顶点位置法向挤出,,原本是庄懂用了两张图片叠加的原因
//o.pos = UnityObjectToClipPos(v.vertex); // 顶点位置 OS>CS
o.uv = TRANSFORM_TEX(v.uv, _Sequence); // 前置UV ST操作
float id = floor(_Time.z * _Speed); // 计算序列id
float idV = floor(id / _ColCount); // 计算V轴id
float idU = id - idV * _ColCount; // 计算U轴id
float stepU = 1.0 / _ColCount; // 计算U轴步幅
float stepV = 1.0 / _RowCount; // 计算V轴步幅
float2 initUV = o.uv * float2(stepU, stepV) + float2(0.0, stepV * (_RowCount - 1.0)); // 计算初始UV
o.uv = initUV + float2(idU * stepU, -idV * stepV); // 计算序列帧UV
广告牌的逻辑
float3 normalDir = viewer - center;
// If _VerticalBillboarding equals 1, we use the desired view dir as the normal dir
// Which means the normal dir is fixed
// Or if _VerticalBillboarding equals 0, the y of normal is 0
// Which means the up dir is fixed
normalDir.y = normalDir.y * _VerticalBillboarding;
normalDir = normalize(normalDir);
// Get the approximate up dir
// If normal dir is already towards up, then the up dir is towards front
float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
float3 rightDir = normalize(cross(upDir, normalDir));
upDir = normalize(cross(normalDir, rightDir));
// Use the three vectors to rotate the quad
float3 centerOffs = v.vertex.xyz - center;
float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;
o.pos = UnityObjectToClipPos(float4(localPos, 1));
return o;
透明区域黑,和不显示
一直没有显示出来原因是cull off没有写,可能是旋转坐标系反向了,我看到的一直是背面?
half4 frag(VertexOutput i) : SV_Target
{
half4 var_Sequence = tex2D(_Sequence, i.uv); // 采样贴图 RGB颜色 A透贴
if (var_Sequence.a < 0.2) discard; // 透明度裁剪
half3 finalRGB = var_Sequence.rgb * _Color.rgb; // 颜色混合
half opacity = var_Sequence.a * _Opacity;
//return opacity; // 返回值
return half4(finalRGB * opacity, opacity); // 返回值
}
无论mesh的形状,添加了广告牌,里面会造成这样的结果
但是加上序列帧之后,又cube有特殊了,算了,先做
unity store找一下third person controller
用于制作游戏的优质资源 | Unity Asset Store
Third Person Controller - Basic Locomotion FREE | Game Toolkits | Unity Asset Store