105 lines
3.5 KiB
Plaintext
105 lines
3.5 KiB
Plaintext
/*
|
|
Created by jiadong chen
|
|
https://jiadong-chen.medium.com/
|
|
*/
|
|
|
|
// Atlas VAT shader.
|
|
// 支持 1 张大图存多个 clip,clip 段沿 Y 轴堆叠。
|
|
// 通过 MaterialPropertyBlock 设置 _AnimYStart / _AnimYSpan / _AnimLen / _AnimTimeOffset 可切换 clip,
|
|
// 无需切换 material → 不破坏 SRP Batcher / GPU Instancing。
|
|
// 单 clip 模式向后兼容: _AnimYStart=0, _AnimYSpan=1, 行为与原 shader 一致。
|
|
Shader "chenjd/BuiltIn/AnimMapShader"
|
|
{
|
|
Properties
|
|
{
|
|
_MainTex ("Texture", 2D) = "white" {}
|
|
_AnimMap ("AnimMap", 2D) ="white" {}
|
|
_AnimLen("Anim Length", Float) = 1
|
|
_AnimYStart("Anim Y Start [0,1]", Float) = 0
|
|
_AnimYSpan ("Anim Y Span [0,1]", Float) = 1
|
|
_AnimTimeOffset("Anim Time Offset", Float) = 0
|
|
[Toggle] _AnimLoop("Loop Anim", Float) = 1
|
|
}
|
|
|
|
SubShader
|
|
{
|
|
Tags { "RenderType" = "Opaque" }
|
|
Cull off
|
|
LOD 100
|
|
|
|
Pass
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
//开启gpu instancing
|
|
#pragma multi_compile_instancing
|
|
|
|
#include "UnityCG.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float4 pos : POSITION;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float2 uv : TEXCOORD0;
|
|
float4 vertex : SV_POSITION;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
|
|
sampler2D _AnimMap;
|
|
float4 _AnimMap_TexelSize; // x == 1/width, y == 1/height
|
|
|
|
// Per-instance friendly props (set via MaterialPropertyBlock to keep SRP Batcher / instancing)
|
|
UNITY_INSTANCING_BUFFER_START(Props)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _AnimLen)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _AnimYStart)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _AnimYSpan)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _AnimTimeOffset)
|
|
UNITY_DEFINE_INSTANCED_PROP(float, _AnimLoop)
|
|
UNITY_INSTANCING_BUFFER_END(Props)
|
|
|
|
v2f vert (appdata v, uint vid : SV_VertexID)
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
|
|
|
float animLen = UNITY_ACCESS_INSTANCED_PROP(Props, _AnimLen);
|
|
float yStart = UNITY_ACCESS_INSTANCED_PROP(Props, _AnimYStart);
|
|
float ySpan = UNITY_ACCESS_INSTANCED_PROP(Props, _AnimYSpan);
|
|
float timeOff = UNITY_ACCESS_INSTANCED_PROP(Props, _AnimTimeOffset);
|
|
float loopFlag = UNITY_ACCESS_INSTANCED_PROP(Props, _AnimLoop);
|
|
|
|
// 时间 → 段内归一化 t [0,1]
|
|
float playTime = _Time.y - timeOff;
|
|
float t = playTime / max(animLen, 0.0001);
|
|
// 循环 or 停在最后一帧
|
|
t = lerp(saturate(t), frac(t), step(0.5, loopFlag));
|
|
|
|
float animMap_x = (vid + 0.5) * _AnimMap_TexelSize.x;
|
|
float animMap_y = yStart + t * ySpan;
|
|
|
|
float4 pos = tex2Dlod(_AnimMap, float4(animMap_x, animMap_y, 0, 0));
|
|
|
|
v2f o;
|
|
o.vertex = UnityObjectToClipPos(pos);
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag (v2f i) : SV_Target
|
|
{
|
|
fixed4 col = tex2D(_MainTex, i.uv);
|
|
return col;
|
|
}
|
|
ENDCG
|
|
}
|
|
}
|
|
}
|