// Armature shader (preserve volume skinning) - Optimized Version
struct VertexAttributes {
    float3 position;
    float3 normal;
    float4 tangent; // 原代码未使用，保留兼容
};
struct BlendAttributes {
    float4 weights;
    int4 indicies;
};
struct PoseAttributes {
    float3 S;    // 缩放
    float3 T;    // 偏移
    float4 QR;   // 旋转四元数（实部w在最后）
    float4 QD;   // 对偶四元数
};

// 寄存器绑定保持不变（兼容原有管线）
RWStructuredBuffer<VertexAttributes> rw_buffer : register(u5);
StructuredBuffer<VertexAttributes> base : register(t50);
StructuredBuffer<BlendAttributes> blend : register(t51);
StructuredBuffer<PoseAttributes> pose : register(t52);
Texture1D<float4> IniParams : register(t120);

// 宏定义保持不变（兼容原有参数传递）
#define TIME IniParams[88].x
#define VG_COUNT IniParams[89].x

// 声明仅保留使用到的函数（移除未使用的m_scale）
int i8toi32(uint src);
uint i32toi8(int src);

[numthreads(64, 1, 1)]
void main(uint3 threadID : SV_DispatchThreadID)
{
    uint i = threadID.x;
    BlendAttributes b = blend[i]; // 仅读取1次blend数据，减少内存访问
    VertexAttributes v = base[i]; // 仅读取1次base数据，减少内存访问

    // 1. 坐标系统转换 + 类型转换（合并赋值，减少临时变量）
    float4 pos = float4(-v.position.x, v.position.z, -v.position.y, 1.0f); // 直接转换轴系，避免二次赋值
    float4 normal = float4(v.normal.x, v.normal.y, v.normal.z, 0.0f);

    // 2. 帧插值参数（提前计算，避免重复floor）
    int frame = (int)TIME;
    float inter = frac(TIME); // 替代TIME - floor(TIME)，指令更精简
    float inter_prev = 1.0f - inter;
    int vg_count = (int)VG_COUNT;

    // 3. 计算混合索引（合并计算，减少临时变量）
    int4 idx_prev = frame * vg_count + b.indicies;
    int4 idx_next = (frame + 1) * vg_count + b.indicies;

    // 4. 读取所有需要的pose数据（一次性读取，减少内存访问延迟）
    PoseAttributes p0_prev = pose[idx_prev.x];
    PoseAttributes p1_prev = pose[idx_prev.y];
    PoseAttributes p2_prev = pose[idx_prev.z];
    PoseAttributes p3_prev = pose[idx_prev.w];
    PoseAttributes p0_next = pose[idx_next.x];
    PoseAttributes p1_next = pose[idx_next.y];
    PoseAttributes p2_next = pose[idx_next.z];
    PoseAttributes p3_next = pose[idx_next.w];

    // 5. 线性混合皮肤（LBS）计算 - 缩放+偏移（向量化运算，减少指令数）
    float4 weights = b.weights;
    float3 scale = (p0_prev.S * weights.x + p1_prev.S * weights.y + p2_prev.S * weights.z + p3_prev.S * weights.w) * inter_prev
                 + (p0_next.S * weights.x + p1_next.S * weights.y + p2_next.S * weights.z + p3_next.S * weights.w) * inter;
    float3 bias = (p0_prev.T * weights.x + p1_prev.T * weights.y + p2_prev.T * weights.z + p3_prev.T * weights.w) * inter_prev
                + (p0_next.T * weights.x + p1_next.T * weights.y + p2_next.T * weights.z + p3_next.T * weights.w) * inter;
    pos.xyz = pos.xyz * scale + bias;

    // 6. 对偶四元数混合（DLB）- 移除分支，向量化计算
    float4 qr = p0_prev.QR * weights.x * inter_prev;
    float4 qd = p0_prev.QD * weights.x * inter_prev;

    // 四元数符号修正：用dot结果的符号替代if-else（sign函数返回±1，避免分支）
    float sign1 = sign(dot(p0_prev.QR, p1_prev.QR));
    float sign2 = sign(dot(p0_prev.QR, p2_prev.QR));
    float sign3 = sign(dot(p0_prev.QR, p3_prev.QR));
    float sign0_next = sign(dot(p0_prev.QR, p0_next.QR));
    float sign1_next = sign(dot(p0_prev.QR, p1_next.QR));
    float sign2_next = sign(dot(p0_prev.QR, p2_next.QR));
    float sign3_next = sign(dot(p0_prev.QR, p3_next.QR));

    // 混合所有四元数（向量运算，无分支）
    qr += p1_prev.QR * weights.y * inter_prev * sign1;
    qd += p1_prev.QD * weights.y * inter_prev * sign1;
    qr += p2_prev.QR * weights.z * inter_prev * sign2;
    qd += p2_prev.QD * weights.z * inter_prev * sign2;
    qr += p3_prev.QR * weights.w * inter_prev * sign3;
    qd += p3_prev.QD * weights.w * inter_prev * sign3;
    qr += p0_next.QR * weights.x * inter * sign0_next;
    qd += p0_next.QD * weights.x * inter * sign0_next;
    qr += p1_next.QR * weights.y * inter * sign1_next;
    qd += p1_next.QD * weights.y * inter * sign1_next;
    qr += p2_next.QR * weights.z * inter * sign2_next;
    qd += p2_next.QD * weights.z * inter * sign2_next;
    qr += p3_next.QR * weights.w * inter * sign3_next;
    qd += p3_next.QD * weights.w * inter * sign3_next;

    // 7. 四元数归一化（优化顺序：先算长度，避免重复除法）
    float qr_len = length(qr);
    if (qr_len < 1e-6f) qr_len = 1e-6f; // 避免除零
    qr /= qr_len;
    qd /= qr_len;

    // 8. 构建旋转矩阵（合并计算，减少临时变量trans）
    float qx = qr.x, qy = qr.y, qz = qr.z, qw = qr.w;
    float qdx = qd.x, qdy = qd.y, qdz = qd.z, qdw = qd.w;

    // 旋转矩阵第一列 + 平移分量（对偶四元数展开）
    float m00 = 1.0f - 2.0f*qy*qy - 2.0f*qz*qz;
    float m10 = 2.0f*(qx*qy + qw*qz);
    float m20 = 2.0f*(qx*qz - qw*qy);
    float t0 = 2.0f*(-qdw*qx + qdx*qw - qdy*qz + qdz*qy);

    // 旋转矩阵第二列 + 平移分量
    float m01 = 2.0f*(qx*qy - qw*qz);
    float m11 = 1.0f - 2.0f*qx*qx - 2.0f*qz*qz;
    float m21 = 2.0f*(qy*qz + qw*qx);
    float t1 = 2.0f*(-qdw*qy + qdx*qz + qdy*qw - qdz*qx);

    // 旋转矩阵第三列 + 平移分量
    float m02 = 2.0f*(qx*qz + qw*qy);
    float m12 = 2.0f*(qy*qz - qw*qx);
    float m22 = 1.0f - 2.0f*qx*qx - 2.0f*qy*qy;
    float t2 = 2.0f*(-qdw*qz - qdx*qy + qdy*qx + qdz*qw);

    // 9. 应用变换（直接计算，避免临时float4 trans）
    float4 pos_result;
    pos_result.x = m00*pos.x + m01*pos.y + m02*pos.z + t0*pos.w;
    pos_result.y = m10*pos.x + m11*pos.y + m12*pos.z + t1*pos.w;
    pos_result.z = m20*pos.x + m21*pos.y + m22*pos.z + t2*pos.w;
    pos_result.w = 1.0f;

    float4 normal_result;
    normal_result.x = m00*normal.x + m01*normal.y + m02*normal.z;
    normal_result.y = m10*normal.x + m11*normal.y + m12*normal.z;
    normal_result.z = m20*normal.x + m21*normal.y + m22*normal.z;
    normal_result.w = 0.0f;

    // 10. 边界裁剪（保持原有逻辑，优化条件判断顺序）
    // if (abs(pos_result.x) > 3.0f || abs(pos_result.y) > 3.0f || abs(pos_result.z) > 3.0f) {
    //     pos_result = float4(0.0f, 0.0f, 0.0f, 1.0f);
    //     normal_result = float4(0.0f, 0.0f, 0.0f, 0.0f);
    // }

    // 11. 还原轴系 + 写入结果（直接赋值，减少临时变量）
    rw_buffer[i].position = float3(-pos_result.x, -pos_result.z, pos_result.y);
    rw_buffer[i].normal = normalize(float3(normal_result.x, normal_result.y, normal_result.z)); // 归一化法线，提升渲染质量
}

// 保留原有辅助函数（未使用但保持兼容）
int i8toi32(uint src) {
    return (src & 0x80) ? (src | 0xffffff80) : (src & 0x7f);
}

uint i32toi8(int src) {
    src = clamp(src, -128, 127); // 替代双if，指令更精简
    return (uint)src & 0xff;
}