Files
ichni_Official/Packages/NB_FX/XuanXuanRenderUtility/Shader/HLSL/TyflowVAT.hlsl
SoulliesOfficial 40fa80cd70 NB_FX
2026-07-17 17:46:16 -04:00

586 lines
17 KiB
HLSL

#ifndef TYFLOW_VAT_INCLUDED
#define TYFLOW_VAT_INCLUDED
#define TYFLOW_VAT_SKIN_MAX_BONES 7
#if defined(_VAT) && defined(_VAT_TYFLOW) && \
!defined(_TYFLOW_VAT_ABSOLUTE) && \
!defined(_TYFLOW_VAT_RELATIVE) && \
!defined(_TYFLOW_VAT_SKIN_R) && \
!defined(_TYFLOW_VAT_SKIN_PR) && \
!defined(_TYFLOW_VAT_SKIN_PRSAVE) && \
!defined(_TYFLOW_VAT_SKIN_PRSXYZ)
#define _TYFLOW_VAT_ABSOLUTE
#endif
#if defined(_TYFLOW_VAT_SKIN_R) || \
defined(_TYFLOW_VAT_SKIN_PR) || \
defined(_TYFLOW_VAT_SKIN_PRSAVE) || \
defined(_TYFLOW_VAT_SKIN_PRSXYZ)
#define TYFLOW_VAT_SKIN_MODE
#endif
struct TyflowVatMatrix3
{
float3 row0;
float3 row1;
float3 row2;
float3 row3;
};
struct TyflowVatTMParts
{
float3 pos;
float4 rot;
float3 scale;
};
inline int TyflowVatUnpackIntRGBA(int4 bytes)
{
return ((bytes.x << 24) + (bytes.y << 16) + (bytes.z << 8) + (bytes.w << 0));
}
inline float TyflowVatUnpackFloatRGBA(int4 bytes)
{
int sign = (bytes.r & 128) > 0 ? -1 : 1;
int expR = (bytes.r & 127) << 1;
int expG = bytes.g >> 7;
int exponent = expR + expG;
int signifG = (bytes.g & 127) << 16;
int signifB = bytes.b << 8;
float significand = (signifG + signifB + bytes.a) / pow(2, 23);
significand += 1;
return sign * significand * pow(2, exponent - 127);
}
inline half TyflowVatUnpackHalfRGBA(int2 bytes)
{
uint value = (bytes.x << 8) | bytes.y;
uint sign = (value & 0x8000) > 0;
int exponent = (value & 0x7C00) >> 10;
uint mantissa = (value & 0x03FF);
if ((value & 0x7FFF) == 0)
{
return sign ? -0 : 0;
}
if (exponent == 0x001F)
{
if (mantissa == 0)
{
return sign ? -1e+28 : 1e+28;
}
return 1e+28;
}
if (exponent > 0)
{
float result = pow(2.0, exponent - 15) * (1 + mantissa * (1 / 1024.0f));
return sign ? -result : result;
}
float subnormal = pow(2.0, -24) * mantissa;
return sign ? -subnormal : subnormal;
}
float4 TyflowVatSampleTexel(uint x, uint y)
{
float2 uv = float2(
((float)x + 0.5f) * _VATTex_TexelSize.x,
1.0f - (((float)y + 0.5f) * _VATTex_TexelSize.y));
return SAMPLE_TEXTURE2D_LOD(_VATTex, sampler_point_clamp, uv, 0);
}
float4 TyflowVatSampleEncodedTexel(uint x, uint y)
{
float4 sample = TyflowVatSampleTexel(x, y);
if (_LinearToGamma > 0.5f)
{
sample.r = LinearToGammaSpaceExact(sample.r);
sample.g = LinearToGammaSpaceExact(sample.g);
sample.b = LinearToGammaSpaceExact(sample.b);
}
return sample;
}
int TyflowVatTex2DInt(int arrInx)
{
uint width = (uint)_VATTex_TexelSize.z;
uint x = (uint)arrInx % width;
uint y = (uint)arrInx / width;
float4 bytes = TyflowVatSampleEncodedTexel(x, y);
int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255));
return TyflowVatUnpackIntRGBA(byteInts.wzyx);
}
float TyflowVatTex2DFloat(int arrInx)
{
uint width = (uint)_VATTex_TexelSize.z;
uint x = (uint)arrInx % width;
uint y = (uint)arrInx / width;
float4 bytes = TyflowVatSampleEncodedTexel(x, y);
int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255));
return TyflowVatUnpackFloatRGBA(byteInts.wzyx);
}
half TyflowVatTex2DHalf(float arrInxF)
{
uint arrInx = (uint)floor(arrInxF + 0.1f);
uint width = (uint)_VATTex_TexelSize.z;
uint x = arrInx % width;
uint y = arrInx / width;
float4 bytes = TyflowVatSampleEncodedTexel(x, y);
int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255));
if (abs(arrInxF - round(arrInxF)) > 0.25f)
{
return TyflowVatUnpackHalfRGBA(byteInts.wz);
}
return TyflowVatUnpackHalfRGBA(byteInts.yx);
}
half2 TyflowVatTex2DHalfs2(float arrInxF)
{
uint arrInx = (uint)floor(arrInxF + 0.1f);
uint width = (uint)_VATTex_TexelSize.z;
uint x = arrInx % width;
uint y = arrInx / width;
float4 bytes = TyflowVatSampleEncodedTexel(x, y);
int4 byteInts = int4(round(bytes.x * 255), round(bytes.y * 255), round(bytes.z * 255), round(bytes.w * 255));
return half2(TyflowVatUnpackHalfRGBA(byteInts.yx), TyflowVatUnpackHalfRGBA(byteInts.wz));
}
float3 TyflowVatMultiplyPosition(TyflowVatMatrix3 matrixValue, float3 pos)
{
return float3(
pos.x * matrixValue.row0[0] + pos.y * matrixValue.row1[0] + pos.z * matrixValue.row2[0] + matrixValue.row3[0],
pos.x * matrixValue.row0[1] + pos.y * matrixValue.row1[1] + pos.z * matrixValue.row2[1] + matrixValue.row3[1],
pos.x * matrixValue.row0[2] + pos.y * matrixValue.row1[2] + pos.z * matrixValue.row2[2] + matrixValue.row3[2]);
}
TyflowVatMatrix3 TyflowVatQuaternionToTM(float4 quat)
{
TyflowVatMatrix3 matrixValue;
float x = quat.x;
float y = quat.y;
float z = quat.z;
float w = quat.w;
matrixValue.row0[0] = 1 - 2 * (y * y + z * z);
matrixValue.row0[1] = 2 * (x * y + z * w);
matrixValue.row0[2] = 2 * (x * z - y * w);
matrixValue.row1[0] = 2 * (x * y - z * w);
matrixValue.row1[1] = 1 - 2 * (x * x + z * z);
matrixValue.row1[2] = 2 * (y * z + x * w);
matrixValue.row2[0] = 2 * (x * z + y * w);
matrixValue.row2[1] = 2 * (y * z - x * w);
matrixValue.row2[2] = 1 - 2 * (x * x + y * y);
matrixValue.row3 = float3(0, 0, 0);
return matrixValue;
}
TyflowVatMatrix3 TyflowVatScaleTM(TyflowVatMatrix3 matrixValue, float3 scale)
{
matrixValue.row0 *= scale.x;
matrixValue.row1 *= scale.y;
matrixValue.row2 *= scale.z;
return matrixValue;
}
TyflowVatMatrix3 TyflowVatTranslateTM(TyflowVatMatrix3 matrixValue, float3 translation)
{
matrixValue.row3 = translation;
return matrixValue;
}
float4 TyflowVatQlerp(float4 a, float4 b, float blend)
{
float s1 = 1.0f - blend;
float s2 = dot(a, b) < 0.0f ? -blend : blend;
return normalize(float4(
s1 * a.x + s2 * b.x,
s1 * a.y + s2 * b.y,
s1 * a.z + s2 * b.z,
s1 * a.w + s2 * b.w));
}
int TyflowVatGetMetaDataSize()
{
#if defined(_TYFLOW_VAT_SKIN_PRSXYZ)
return 12;
#else
if (_DeformingSkin > 0.5f)
{
return 12;
}
return 3;
#endif
}
float3 TyflowVatGetTMPos(float startIndex)
{
float3 result;
for (int i = 0; i < 3; i++)
{
result[i] = TyflowVatTex2DFloat(startIndex + i);
}
return result;
}
float4 TyflowVatGetTMRot(float startIndex)
{
half2 rotHalfs1 = TyflowVatTex2DHalfs2(startIndex);
half2 rotHalfs2 = TyflowVatTex2DHalfs2(startIndex + 1);
return float4(-rotHalfs1.x, -rotHalfs1.y, -rotHalfs2.x, rotHalfs2.y);
}
float3 TyflowVatGetTMScaleXYZ(float startIndex)
{
half2 scaleHalfs1 = TyflowVatTex2DHalfs2(startIndex);
half2 scaleHalfs2 = TyflowVatTex2DHalfs2(startIndex + 1);
return float3(scaleHalfs1.x, scaleHalfs1.y, scaleHalfs2.x);
}
float3 TyflowVatGetTMScaleAve(float startIndex)
{
half scaleHalf = TyflowVatTex2DHalf(startIndex);
return float3(scaleHalf, scaleHalf, scaleHalf);
}
TyflowVatMatrix3 TyflowVatTMFromParts(TyflowVatTMParts parts)
{
TyflowVatMatrix3 matrixValue = TyflowVatQuaternionToTM(parts.rot);
matrixValue = TyflowVatScaleTM(matrixValue, parts.scale);
matrixValue = TyflowVatTranslateTM(matrixValue, parts.pos);
return matrixValue;
}
TyflowVatMatrix3 TyflowVatGetVertexInvTM(int tmInx)
{
TyflowVatMatrix3 matrixValue;
int pixelsPerTM = TyflowVatGetMetaDataSize();
float tmRowInx = 2 + (pixelsPerTM * tmInx);
matrixValue.row0 = TyflowVatGetTMPos(tmRowInx);
tmRowInx += 3;
matrixValue.row1 = TyflowVatGetTMPos(tmRowInx);
tmRowInx += 3;
matrixValue.row2 = TyflowVatGetTMPos(tmRowInx);
tmRowInx += 3;
matrixValue.row3 = TyflowVatGetTMPos(tmRowInx);
return matrixValue;
}
TyflowVatTMParts TyflowVatGetVertexTMPartsAtFrame(int tmInx, int frame, int numTMs)
{
float4 rot = float4(0, 0, 0, 1);
float3 pos = float3(0, 0, 0);
float3 scale = float3(1, 1, 1);
float pixelsPerTM = 0;
#if defined(_TYFLOW_VAT_SKIN_R)
pixelsPerTM = 2;
#elif defined(_TYFLOW_VAT_SKIN_PR)
pixelsPerTM = 5;
#elif defined(_TYFLOW_VAT_SKIN_PRSXYZ)
pixelsPerTM = 7;
#elif defined(_TYFLOW_VAT_SKIN_PRSAVE)
pixelsPerTM = 6;
#endif
float frameTMInx = (2 + numTMs * TyflowVatGetMetaDataSize()) + (frame * numTMs * pixelsPerTM) + (pixelsPerTM * tmInx);
#if defined(_TYFLOW_VAT_SKIN_R)
pos = TyflowVatGetTMPos(2 + tmInx * TyflowVatGetMetaDataSize());
rot = TyflowVatGetTMRot(frameTMInx);
#elif defined(_TYFLOW_VAT_SKIN_PR)
pos = TyflowVatGetTMPos(frameTMInx);
frameTMInx += 3;
rot = TyflowVatGetTMRot(frameTMInx);
#elif defined(_TYFLOW_VAT_SKIN_PRSXYZ)
pos = TyflowVatGetTMPos(frameTMInx);
frameTMInx += 3;
rot = TyflowVatGetTMRot(frameTMInx);
frameTMInx += 2;
scale = TyflowVatGetTMScaleXYZ(frameTMInx);
#elif defined(_TYFLOW_VAT_SKIN_PRSAVE)
pos = TyflowVatGetTMPos(frameTMInx);
frameTMInx += 3;
rot = TyflowVatGetTMRot(frameTMInx);
frameTMInx += 2;
scale = TyflowVatGetTMScaleAve(frameTMInx);
#endif
TyflowVatTMParts parts;
parts.pos = pos;
parts.rot = rot;
parts.scale = scale;
return parts;
}
float4 TyflowVatGetVertexValueAtFrame(uint vertexIndex, int vertexCount, int frame, int frameOffset)
{
float4 result = float4(0, 0, 0, 0);
vertexIndex += (vertexCount * frame) + (vertexCount * frameOffset);
if (_RGBAEncoded > 0.5f)
{
if (_RGBAHalf > 0.5f)
{
vertexIndex *= 3;
for (int i = 0; i < 3; i++)
{
float arrInxF = (vertexIndex + i) * 0.5f;
result[i] = TyflowVatTex2DHalf(arrInxF);
}
}
else
{
vertexIndex *= 3;
for (int i = 0; i < 3; i++)
{
result[i] = TyflowVatTex2DFloat(vertexIndex + i);
}
}
}
else
{
uint width = (uint)_VATTex_TexelSize.z;
uint x = vertexIndex % width;
uint y = vertexIndex / width;
result = TyflowVatSampleTexel(x, y);
}
return result;
}
float3 TyflowVatGetLocalVertexPosFromTM(float3 pos, TyflowVatMatrix3 invTM)
{
float3 localPos = ((pos / _ImportScale) * float3(-1, 1, 1));
return TyflowVatMultiplyPosition(invTM, localPos);
}
float3 TyflowVatGetLocalVertexPosFromPos(float3 pos, float boneInx)
{
int tmInx = 2 + (int)round(boneInx) * TyflowVatGetMetaDataSize();
float3 tmPos = float3(0, 0, 0);
for (int i = 0; i < 3; i++)
{
tmPos[i] = TyflowVatTex2DFloat(tmInx + i);
}
return ((pos / _ImportScale) * float3(-1, 1, 1)) - tmPos;
}
float2 TyflowVatGetSkinTexcoord(AttributesParticle input, int index)
{
if (index == 0) return input.Custom1.xy;
if (index == 1) return input.Custom2.xy;
#if !defined(_FLIPBOOKBLENDING_ON)
if (index == 2) return input.vatTexcoord4;
#endif
if (index == 3) return input.vatTexcoord5;
if (index == 4) return input.vatTexcoord6;
if (index == 5) return input.vatTexcoord7;
if (index == 6) return input.vatTexcoord8;
return float2(0, 0);
}
void ApplyTyflowVAT(AttributesParticle input, inout float4 positionOS, inout float3 normalOS)
{
#if defined(SHADOWS_DEPTH)
if (_AffectsShadows < 0.5f)
{
return;
}
#endif
float frameBase = _Frame;
float frameCustomData = GetCustomData(NB_CUSTOM_DATA_FLAG_2, FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, -1.0f, input.Custom1, input.Custom2);
if (frameCustomData >= 0.0f)
{
frameBase = saturate(frameCustomData) * max(_Frames - 1.0f, 0.0f);
}
float frame = abs(frameBase + ((_Autoplay > 0.5f) ? (time * 30.0f * _AutoplaySpeed) : 0.0f));
frame = (_Loop > 0.5f) ? fmod(frame, _Frames) : min(frame, _Frames - 1.0f);
if ((_Loop > 0.5f) && (_InterpolateLoop < 0.5f) && (frame >= _Frames - 1.0f))
{
frame = _Frames - 1.0f;
}
uint frame0 = (uint)floor(frame);
uint frame1 = (uint)ceil(frame) % (uint)_Frames;
float frameInterp = frame - frame0;
#if defined(TYFLOW_VAT_SKIN_MODE)
if (CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM))
{
return;
}
else
{
int numTMs = TyflowVatTex2DInt(1);
float3 combinedPos = float3(0, 0, 0);
float3 combinedNormal = float3(0, 0, 0);
int loopCount = (_DeformingSkin > 0.5f) ? (int)_SkinBoneCount : 1;
[unroll]
for (int i = 0; i < TYFLOW_VAT_SKIN_MAX_BONES; i++)
{
if (i >= loopCount)
{
break;
}
float weight = 1.0f;
float tmInx = round(input.Custom1.y);
if (_DeformingSkin > 0.5f)
{
float2 texcoord = TyflowVatGetSkinTexcoord(input, i);
tmInx = round(texcoord.x);
weight = texcoord.y;
}
TyflowVatTMParts tmParts0 = TyflowVatGetVertexTMPartsAtFrame((int)tmInx, frame0, numTMs);
if (_FrameInterpolation > 0.5f)
{
TyflowVatTMParts tmParts1 = TyflowVatGetVertexTMPartsAtFrame((int)tmInx, frame1, numTMs);
tmParts0.pos = lerp(tmParts0.pos, tmParts1.pos, frameInterp);
tmParts0.rot = TyflowVatQlerp(tmParts0.rot, tmParts1.rot, frameInterp);
tmParts0.scale = lerp(tmParts0.scale, tmParts1.scale, frameInterp);
}
TyflowVatMatrix3 tm = TyflowVatTMFromParts(tmParts0);
TyflowVatMatrix3 invStartTM;
#if defined(_TYFLOW_VAT_SKIN_PRSXYZ)
bool useInvStartTM = true;
#else
bool useInvStartTM = _DeformingSkin > 0.5f;
#endif
if (useInvStartTM)
{
invStartTM = TyflowVatGetVertexInvTM((int)tmInx);
}
else
{
invStartTM.row0 = float3(0, 0, 0);
invStartTM.row1 = float3(0, 0, 0);
invStartTM.row2 = float3(0, 0, 0);
invStartTM.row3 = float3(0, 0, 0);
}
float3 localPos;
if (useInvStartTM)
{
localPos = TyflowVatGetLocalVertexPosFromTM(positionOS.xyz, invStartTM);
}
else
{
localPos = TyflowVatGetLocalVertexPosFromPos(positionOS.xyz, tmInx);
}
float3 pos = TyflowVatMultiplyPosition(tm, localPos) * float3(-1, 1, 1);
combinedPos += (pos * _ImportScale) * weight;
#if !defined(SHADOWS_DEPTH)
{
float3 animatedNormal = normalOS;
tm.row3 = float3(0, 0, 0);
if (useInvStartTM)
{
invStartTM.row3 = float3(0, 0, 0);
float3 localNormal = TyflowVatGetLocalVertexPosFromTM(animatedNormal, invStartTM);
animatedNormal = normalize(TyflowVatMultiplyPosition(tm, localNormal)) * float3(-1, 1, 1);
}
else
{
tm = TyflowVatTranslateTM(tm, float3(0, 0, 0));
animatedNormal = normalize(TyflowVatMultiplyPosition(tm, animatedNormal * float3(-1, 1, 1))) * float3(-1, 1, 1);
}
combinedNormal += animatedNormal * weight;
}
#endif
}
positionOS.xyz = combinedPos;
normalOS = combinedNormal;
}
#elif defined(_TYFLOW_VAT_ABSOLUTE) || defined(_TYFLOW_VAT_RELATIVE)
{
float2 tyflowVatIndexData = CheckLocalFlags1(FLAG_BIT_PARTICLE_1_IS_PARTICLE_SYSTEM)
? input.texcoords.zw
: input.Custom1.xy;
uint vertexIndex = (uint)round(tyflowVatIndexData.x);
uint vertexCount = (uint)round(tyflowVatIndexData.y);
float4 vertexOffset0 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame0, 0);
float4 vertexOffset = vertexOffset0;
if (_FrameInterpolation > 0.5f)
{
float4 vertexOffset1 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame1, 0);
vertexOffset = lerp(vertexOffset0, vertexOffset1, frameInterp);
}
#if defined(_TYFLOW_VAT_RELATIVE)
positionOS.xyz += (vertexOffset * float4(-1, 1, 1, 1) * _ImportScale).xyz;
#else
positionOS.xyz = (vertexOffset * float4(-1, 1, 1, 1) * _ImportScale).xyz;
#endif
#if !defined(SHADOWS_DEPTH)
if (_VATIncludesNormals > 0.5f)
{
float4 normal0 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame0, (int)_Frames);
float4 animatedNormal = normal0;
if (_FrameInterpolation > 0.5f)
{
float4 normal1 = TyflowVatGetVertexValueAtFrame(vertexIndex, vertexCount, frame1, (int)_Frames);
animatedNormal = lerp(normal0, normal1, frameInterp) * float4(-1, 1, 1, 1);
}
normalOS = normalize(animatedNormal.xyz);
}
#endif
}
#endif
}
#endif