
// Vk3DVision (http://3dsurroundgaming.com/) - Original Shader
#version 450
#extension GL_EXT_nonuniform_qualifier : require

struct FlrInput
{
    vec3 position;
    vec2 uv0;
    vec3 normal;
    vec4 tangent;
    vec4 color;
    uvec4 blendIndices;
    vec4 blendWeights;
    uint instanceIndex;
    uint instancingBufferOffset;
    uint skinningBufferOffset;
};

struct FlrOutput
{
    vec4 position;
    vec2 uv0;
    vec3 posWS;
    vec3 normal;
    vec4 tangent;
    vec3 binormal;
    vec4 color;
    vec4 prevPosition;
};

struct VegetationSkinningBufferEntry
{
    mat3x4 transform;
    vec4 tint;
};

layout(set = 0, binding = 4, std430) readonly buffer SkinningBuffer
{
    mat3x4 _SkinningBuffer[];
} _37;

layout(set = 0, binding = 1, std140) uniform PerFrame
{
    vec4 frameParameters0;
    vec4 frameParameters1;
    vec4 projectionOffsets;
} _64;

layout(set = 0, binding = 0, std140) uniform PerInstance
{
    mat4 worldMatrix;
    mat4 prevWorldMatrix;
    uvec4 params0;
} _263;

layout(set = 0, binding = 3, std140) uniform PerView
{
    mat4 viewProjMatrix;
    mat4 prevViewProjMatrix;
    vec4 cameraPositionWS;
} _318;

layout(set = 0, binding = 2, std140) uniform PerMaterial
{
    uvec4 paramIntData0;
    vec4 tint;
    vec4 parameters0;
    vec4 uvTransform;
    vec4 paramData3;
    vec4 normalParams;
    vec4 paramData5;
    vec4 paramData6;
    vec4 paramData7;
    vec4 paramData8;
    vec4 paramData9;
    uvec4 paramImgIDs0;
    uvec4 paramImgIDs1;
    uvec4 paramImgIDs2;
} _455;

layout(set = 0, binding = 5, std430) readonly buffer InstancingBuffer
{
    mat3x4 _InstancingBuffer[];
} _459;

layout(set = 0, binding = 6, std430) readonly buffer VegetationSkinningBuffer
{
    VegetationSkinningBufferEntry _VegetationSkinningBuffer[];
} _464;

layout(set = 0, binding = 99, std430) buffer DebugBuffer
{
    uint debugBuffer[];
} _468;

layout(set = 2, binding = 0) uniform texture2D globalTextures[];
layout(set = 2, binding = 0) uniform textureCube globalCubeTextures[];
layout(set = 2, binding = 0) uniform texture3D global3DTextures[];
layout(set = 1, binding = 0) uniform sampler linearClampSampler;
layout(set = 1, binding = 1) uniform sampler linearRepeatSampler;
layout(set = 1, binding = 2) uniform sampler nearestClampSampler;
layout(set = 1, binding = 3) uniform sampler nearestRepeatSampler;
layout(set = 1, binding = 4) uniform sampler shadowSampler;

layout(location = 0) in vec4 inPosition;
layout(location = 1) in vec2 inUV0;
layout(location = 4) in uvec4 inBlendIndices;
layout(location = 5) in vec4 inBlendWeights;
layout(location = 2) in vec4 inNormal;
layout(location = 3) in vec4 inTangent;
layout(location = 1) out vec2 outUV0;
layout(location = 4) out vec3 outPosWS;

uint getBlendIndex(uvec4 blendIndices, uint index)
{
    return blendIndices[index];
}

mat3x4 getSkinningMatrix(uint blendIndex, uint skinningBufferOffset)
{
    return _37._SkinningBuffer[(skinningBufferOffset * 256u) + blendIndex];
}

void flrMain(FlrInput flrInput, inout FlrOutput flrOutput)
{
    flrOutput.color = flrInput.color;
    uint currFrameID = floatBitsToUint(_64.frameParameters0.w);
    uint prevFrameID = (currFrameID + 1u) % 2u;
    vec3 localPos = vec3(0.0);
    vec3 localNormal = vec3(0.0);
    vec3 localTangent = vec3(0.0);
    vec3 prevLocalPos = vec3(0.0);
    uint currMatrixOffset = flrInput.skinningBufferOffset + (8192u * currFrameID);
    uint prevMatrixOffset = flrInput.skinningBufferOffset + (8192u * prevFrameID);
    float accWeight = 0.0;
    for (uint boneIdx = 0u; boneIdx < 3u; boneIdx++)
    {
        float weight = flrInput.blendWeights[boneIdx];
        uvec4 param = flrInput.blendIndices;
        uint param_1 = boneIdx;
        uint blendIdx = getBlendIndex(param, param_1);
        uint param_2 = blendIdx;
        uint param_3 = currMatrixOffset;
        mat3x4 skinningMat = getSkinningMatrix(param_2, param_3);
        localPos += ((vec4(flrInput.position, 1.0) * skinningMat) * weight);
        localNormal += ((vec4(flrInput.normal, 0.0) * skinningMat) * weight);
        localTangent += ((vec4(flrInput.tangent.xyz, 0.0) * skinningMat) * weight);
        uint param_4 = blendIdx;
        uint param_5 = prevMatrixOffset;
        mat3x4 prevSkinningMat = getSkinningMatrix(param_4, param_5);
        prevLocalPos += ((vec4(flrInput.position, 1.0) * prevSkinningMat) * weight);
        accWeight += weight;
    }
    uint param_6 = flrInput.blendIndices.w;
    uint param_7 = currMatrixOffset;
    mat3x4 skinningMat_1 = getSkinningMatrix(param_6, param_7);
    localPos += ((vec4(flrInput.position, 1.0) * skinningMat_1) * (1.0 - accWeight));
    localNormal += ((vec4(flrInput.normal, 0.0) * skinningMat_1) * (1.0 - accWeight));
    localTangent += ((vec4(flrInput.tangent.xyz, 0.0) * skinningMat_1) * (1.0 - accWeight));
    uint param_8 = flrInput.blendIndices.w;
    uint param_9 = prevMatrixOffset;
    mat3x4 prevSkinningMat_1 = getSkinningMatrix(param_8, param_9);
    prevLocalPos += ((vec4(flrInput.position, 1.0) * prevSkinningMat_1) * (1.0 - accWeight));
    vec3 objectPositionWS = vec3(0.0);
    objectPositionWS = (_263.worldMatrix * vec4(objectPositionWS, 1.0)).xyz;
    vec3 normalWS = normalize((_263.worldMatrix * vec4(localNormal, 0.0)).xyz);
    vec3 posWS = (_263.worldMatrix * vec4(localPos, 1.0)).xyz;
    vec3 prevPosWS = (_263.prevWorldMatrix * vec4(prevLocalPos, 1.0)).xyz;
    vec3 prevNormalWS = normalize((_263.prevWorldMatrix * vec4(localNormal, 0.0)).xyz);
    flrOutput.position = _318.viewProjMatrix * vec4(posWS, 1.0);
    flrOutput.normal = normalWS;
    vec3 _339 = normalize((_263.worldMatrix * vec4(localTangent, 0.0)).xyz);
    flrOutput.tangent = vec4(_339.x, _339.y, _339.z, flrOutput.tangent.w);
    flrOutput.tangent.w = flrInput.tangent.w;
    flrOutput.binormal = cross(flrOutput.normal, flrOutput.tangent.xyz) * flrInput.tangent.w;
    flrOutput.prevPosition = vec4(0.0);
    flrOutput.posWS = posWS;
    flrOutput.uv0 = flrInput.uv0;
    flrOutput.prevPosition = _318.prevViewProjMatrix * vec4(prevPosWS, 1.0);
}

void main()
{
    FlrInput flrInput;
    flrInput.instanceIndex = uint(gl_InstanceIndex);
    flrInput.position = inPosition.xyz;
    flrInput.uv0 = inUV0;
    flrInput.blendIndices = inBlendIndices;
    flrInput.blendWeights = inBlendWeights;
    flrInput.normal = inNormal.xyz;
    flrInput.tangent = inTangent;
    flrInput.color = vec4(1.0);
    flrInput.skinningBufferOffset = _263.params0.x;
    flrInput.instancingBufferOffset = _263.params0.y;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    gl_Position = flrOutput.position;
    outUV0 = flrOutput.uv0;
    outPosWS = flrOutput.posWS;
}

