I edited 2 lines in the PseudoVolumeTexture function and it seemed to resolve the problem
float4 PseudoVolumeTexture(Texture2D Tex, SamplerState TexSampler, float3 inPos, float2 xysize, float numframes,
uint mipmode = 0, float miplevel = 0, float2 InDDX = 0, float2 InDDY = 0)
{
// float zframe = ceil(inPos.z * numframes);
// [EDIT] the first z frames were appearing after the last ones
float zframe = floor(inPos.z * numframes);
float zphase = frac(inPos.z * numframes);
float2 uv = frac(inPos.xy) / xysize;
float2 curframe = Tile1Dto2D(xysize.x, zframe) / xysize;
float2 nextframe = Tile1Dto2D(xysize.x, min(zframe + 1, numframes) )/ xysize;
float4 sampleA = 0, sampleB = 0;
switch (mipmode)
{
case 0: // Mip level
sampleA = Tex.SampleLevel(TexSampler, uv + curframe, miplevel);
//sampleB = Tex.SampleLevel(TexSampler, uv + nextframe, miplevel);
// [EDIT] Without this it seems there is a interpolation between the last and first frame
sampleB = Tex.SampleLevel(TexSampler, float2(saturate(uv.x + nextframe.x), saturate(uv.y + nextframe.y)), miplevel);
break;
case 1: // Gradients automatic from UV
sampleA = Texture2DSample(Tex, TexSampler, uv + curframe);
sampleB = Texture2DSample(Tex, TexSampler, uv + nextframe);
break;
case 2: // Deriviatives provided
sampleA = Tex.SampleGrad(TexSampler, uv + curframe, InDDX, InDDY);
sampleB = Tex.SampleGrad(TexSampler, uv + nextframe, InDDX, InDDY);
break;
default:
break;
}
return lerp(sampleA, sampleB, zphase);
}
[EDIT] Following @NilsonLima 's comment
Here is the result

Since I’m working with other people, how can I embbed this code on my material (instead of directly changing the engine shader) without just copying this code on everyplace the function is called?