// --- START OF FILE shapekey_anim_packed_delta_v5_merged.hlsl ---
//
// **** ADDITIVE ANIMATION SHADER - V5 MERGED PACKED POSITION DELTA ****
// Contributors: Zlevir, Assistant
// Version: 5.0
// Description:
//   - Merge all slot packed delta buffers into one data buffer.
//   - Merge all slot index maps into one flattened index buffer.
//   - Optional optimized FREQ lookup stays as a separate buffer.

#define NO_FREQ_INDEX 255

struct VertexAttributes {
    float3 position;
    uint normal;
};

RWStructuredBuffer<VertexAttributes> rw_buffer : register(u5);
StructuredBuffer<float3> merged_shapekey_pos_deltas : register(t51);
StructuredBuffer<int> merged_shapekey_indices : register(t52);
StructuredBuffer<uint> vertex_freq_indices : register(t53);

Texture1D<float4> IniParams : register(t120);

// --- [PYTHON-MANAGED BLOCK START] ---
// --- Shared Animation Intensity (per Shape Key Name) ---
// From index 100 onwards
#define FREQ1 IniParams[100].x // Vag2↓
#define FREQ2 IniParams[101].x // 假阳具
#define FREQ3 IniParams[102].x // 肛塞
#define FREQ4 IniParams[103].x // Vag_intra↓
#define FREQ5 IniParams[104].x // Anal↓
// --- [PYTHON-MANAGED BLOCK END] ---

[numthreads(16, 1, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
    uint i = threadID.x;
    uint vertex_count = rw_buffer.Length;
    if (i >= vertex_count)
    {
        return;
    }

    VertexAttributes output = rw_buffer[i];
    float3 total_diff_position = float3(0.0, 0.0, 0.0);

    // --- [PYTHON-MANAGED LOGIC START] ---
    // V5 merged mode: all slot buffers are packed into a single data buffer and a single index buffer
    uint num_slots = 3;
    // --- Slot 0 (merged) ---
    uint packed_idx_slot0 = i * num_slots + 0;
    uint freq_idx_slot0 = vertex_freq_indices[packed_idx_slot0];
    if (freq_idx_slot0 != 255)
    {
        float anim_weight_slot0 = IniParams[100 + freq_idx_slot0].x;
        int packed_index = merged_shapekey_indices[packed_idx_slot0];
        if (packed_index != -1)
        {
            total_diff_position += merged_shapekey_pos_deltas[packed_index] * anim_weight_slot0;
        }
    }

    // --- Slot 1 (merged) ---
    uint packed_idx_slot1 = i * num_slots + 1;
    uint freq_idx_slot1 = vertex_freq_indices[packed_idx_slot1];
    if (freq_idx_slot1 != 255)
    {
        float anim_weight_slot1 = IniParams[100 + freq_idx_slot1].x;
        int packed_index = merged_shapekey_indices[packed_idx_slot1];
        if (packed_index != -1)
        {
            total_diff_position += merged_shapekey_pos_deltas[packed_index] * anim_weight_slot1;
        }
    }

    // --- Slot 2 (merged) ---
    uint packed_idx_slot2 = i * num_slots + 2;
    uint freq_idx_slot2 = vertex_freq_indices[packed_idx_slot2];
    if (freq_idx_slot2 != 255)
    {
        float anim_weight_slot2 = IniParams[100 + freq_idx_slot2].x;
        int packed_index = merged_shapekey_indices[packed_idx_slot2];
        if (packed_index != -1)
        {
            total_diff_position += merged_shapekey_pos_deltas[packed_index] * anim_weight_slot2;
        }
    }
    // --- [PYTHON-MANAGED LOGIC END] ---

    output.position += total_diff_position;
    rw_buffer[i] = output;
}
// --- END OF FILE shapekey_anim_packed_delta_v5_merged.hlsl ---
