//Shadows VS 7.
#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;
};


// Vk3DVision (http://3dsurroundgaming.com/) - Stereo Injection
layout(set = 0, binding = 110, std140) uniform Vk3DParams
{
    vec4 stereo;
    vec4 custom_params;
} vk3d_params;

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

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

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

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;
} _615;

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

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

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

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

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 = 6) in vec4 inColor;
layout(location = 1) out vec2 outUV0;
layout(location = 4) out vec3 outPosWS;

float mf_hash(float n)
{
    return fract(sin(n) * 43758.546875);
}

float mf_noise(vec3 x)
{
    vec3 p = floor(x);
    vec3 f = fract(x);
    f = (f * f) * (vec3(3.0) - (f * 2.0));
    float n = (p.x + (p.y * 57.0)) + (113.0 * p.z);
    float param = n + 0.0;
    float param_1 = n + 1.0;
    float param_2 = n + 57.0;
    float param_3 = n + 58.0;
    float param_4 = n + 113.0;
    float param_5 = n + 114.0;
    float param_6 = n + 170.0;
    float param_7 = n + 171.0;
    return mix(mix(mix(mf_hash(param), mf_hash(param_1), f.x), mix(mf_hash(param_2), mf_hash(param_3), f.x), f.y), mix(mix(mf_hash(param_4), mf_hash(param_5), f.x), mix(mf_hash(param_6), mf_hash(param_7), f.x), f.y), f.z);
}

vec3 generateWindNoise(vec3 localPos, float time)
{
    vec3 param = (localPos * 0.001000000047497451305389404296875) + vec3(time * 0.5);
    float windNoise = (mf_noise(param) * 2.0) - 1.0;
    return vec3(windNoise, windNoise, windNoise);
}

void applyMainBending(inout vec3 vtxPosWS, vec3 windDirection, float bendScale)
{
    float fLength = length(vtxPosWS);
    float fBF = vtxPosWS.y * bendScale;
    fBF += 1.0;
    fBF *= fBF;
    fBF = (fBF * fBF) - fBF;
    vec3 vNewPos = vtxPosWS;
    vNewPos += (windDirection * fBF);
    vtxPosWS = normalize(vNewPos) * fLength;
}

vec4 triangleWave(vec4 x)
{
    return abs((fract(x + vec4(0.5)) * 2.0) - vec4(1.0));
}

vec4 smoothCurve(vec4 x)
{
    return (x * x) * (vec4(3.0) - (x * 2.0));
}

vec4 smoothTriangleWave(vec4 x)
{
    vec4 param = x;
    vec4 param_1 = triangleWave(param);
    return smoothCurve(param_1);
}

void applyDetailBending(inout vec3 vtxPosWS, vec3 vtxPos, vec3 vtxNormal, vec3 objectPosition, float leafPhase, inout float branchPhase, float time, float leafFlexibility, float branchFlexibility, float detailBendingBranchStrength, float detailBendingSpeed, float detailBendingLeafStrength)
{
    float fObjPhase = dot(objectPosition / vec3(100.0), vec3(1.0));
    branchPhase += fObjPhase;
    float phaseSum = leafPhase + branchPhase;
    float fVtxPhase = dot(vtxPos, vec3(phaseSum));
    vec2 vWavesIn = vec2(time) + vec2(fVtxPhase, branchPhase);
    vec4 vWaves = ((fract(vWavesIn.xxyy * vec4(1.97500002384185791015625, 0.7929999828338623046875, 0.375, 0.19300000369548797607421875)) * 2.0) - vec4(1.0)) * detailBendingSpeed;
    vec4 param = vWaves;
    vWaves = smoothTriangleWave(param);
    vec2 vWavesSum = vWaves.xz + vWaves.yw;
    vec2 _172 = vtxPosWS.xz + (((vWavesSum.xx * leafFlexibility) * detailBendingLeafStrength) * vtxNormal.xz);
    vtxPosWS = vec3(_172.x, vtxPosWS.y, _172.y);
    vtxPosWS.y += ((vWavesSum.y * branchFlexibility) * detailBendingBranchStrength);
}

vec3 applyVegetationAnimation(vec3 vtxPos, vec3 vtxPosWS, vec3 objPosWS, vec3 vtxNormal, vec3 vtxAnimParameters, float time, inout vec4 vegetation_animation_parameters0, vec4 vegetation_animation_parameters1)
{
    vec3 globalWindDirection = vec3(0.0);
    float windDetailBendingStrength = 0.0;
    float windNoiseStrength = 0.0;
    windDetailBendingStrength = 1.0;
    windNoiseStrength = 1.0;
    vegetation_animation_parameters0 = vegetation_animation_parameters0;
    float windTime = time * clamp(windNoiseStrength, 1.0, 3.0);
    vec3 param = objPosWS;
    float param_1 = windTime;
    vec3 windSpeed = globalWindDirection + (generateWindNoise(param, param_1) * windNoiseStrength);
    float bendScale = 0.001000000047497451305389404296875 * vegetation_animation_parameters1.x;
    float detailBendingBranchStrength = 10.0 * (vegetation_animation_parameters1.y * windDetailBendingStrength);
    float detailBendingLeafStrength = 2.0 * (vegetation_animation_parameters1.z * windDetailBendingStrength);
    float detailBendingSpeed = vegetation_animation_parameters1.w;
    vec3 vtxPosResult = vtxPosWS;
    vtxPosResult -= objPosWS;
    vec3 param_2 = vtxPosResult;
    vec3 param_3 = windSpeed;
    float param_4 = bendScale;
    applyMainBending(param_2, param_3, param_4);
    vtxPosResult = param_2;
    vtxPosResult += objPosWS;
    vec3 param_5 = vtxPosResult;
    vec3 param_6 = vtxPos;
    vec3 param_7 = vtxNormal;
    vec3 param_8 = objPosWS;
    float param_9 = 0.0;
    float param_10 = vtxAnimParameters.y;
    float param_11 = time;
    float param_12 = vtxAnimParameters.x;
    float param_13 = vtxAnimParameters.z;
    float param_14 = detailBendingBranchStrength;
    float param_15 = detailBendingSpeed;
    float param_16 = detailBendingLeafStrength;
    applyDetailBending(param_5, param_6, param_7, param_8, param_9, param_10, param_11, param_12, param_13, param_14, param_15, param_16);
    vtxPosResult = param_5;
    return vtxPosResult;
}

void flrMain(FlrInput flrInput, inout FlrOutput flrOutput)
{
    flrOutput.color = vec4(1.0);
    uint currFrameID = floatBitsToUint(_425.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 skinningBufferOffset = (_443.params0.y * 3u) + (230400u * currFrameID);
    uint skinningBufferOffsetPrev = (_443.params0.y * 3u) + (230400u * prevFrameID);
    uint _476 = ((flrInput.instanceIndex * 3u) + 0u) + skinningBufferOffset;
    VegetationSkinningBufferEntry skinningBufferEntries[3];
    skinningBufferEntries[0].transform = _469._VegetationSkinningBuffer[_476].transform;
    skinningBufferEntries[0].tint = _469._VegetationSkinningBuffer[_476].tint;
    uint _494 = ((flrInput.instanceIndex * 3u) + 0u) + skinningBufferOffsetPrev;
    VegetationSkinningBufferEntry skinningBufferEntriesPrev[3];
    skinningBufferEntriesPrev[0].transform = _469._VegetationSkinningBuffer[_494].transform;
    skinningBufferEntriesPrev[0].tint = _469._VegetationSkinningBuffer[_494].tint;
    localPos = vec4(flrInput.position, 1.0) * skinningBufferEntries[0].transform;
    prevLocalPos = vec4(flrInput.position, 1.0) * skinningBufferEntriesPrev[0].transform;
    localNormal = vec4(flrInput.normal, 0.0) * skinningBufferEntries[0].transform;
    localTangent = vec4(flrInput.tangent.xyz, 0.0) * skinningBufferEntries[0].transform;
    prevLocalPos = localPos;
    vec3 _547 = flrOutput.color.xyz * skinningBufferEntries[0].tint.xyz;
    flrOutput.color = vec4(_547.x, _547.y, _547.z, flrOutput.color.w);
    flrOutput.color.w = 1.0;
    vec3 objectPositionWS = vec3(0.0);
    objectPositionWS = (_443.worldMatrix * vec4(objectPositionWS, 1.0)).xyz;
    vec3 normalWS = normalize((_443.worldMatrix * vec4(localNormal, 0.0)).xyz);
    vec3 posWS = (_443.worldMatrix * vec4(localPos, 1.0)).xyz;
    vec3 prevPosWS = (_443.prevWorldMatrix * vec4(prevLocalPos, 1.0)).xyz;
    vec3 prevNormalWS = normalize((_443.prevWorldMatrix * vec4(localNormal, 0.0)).xyz);
    vec3 normalVeg = trunc(normalWS * 100.0) / vec3(100.0);
    vec3 param = localPos;
    vec3 param_1 = posWS;
    vec3 param_2 = objectPositionWS;
    vec3 param_3 = normalVeg;
    vec3 param_4 = flrInput.color.zyx;
    float param_5 = _425.frameParameters0.x;
    vec4 param_6 = vec4(0.0);
    vec4 param_7 = _615.paramData3;
    vec3 _636 = applyVegetationAnimation(param, param_1, param_2, param_3, param_4, param_5, param_6, param_7);
    posWS = _636;
    vec3 prevNormalVeg = trunc(prevNormalWS * 100.0) / vec3(100.0);
    vec3 param_8 = prevLocalPos;
    vec3 param_9 = prevPosWS;
    vec3 param_10 = objectPositionWS;
    vec3 param_11 = normalVeg;
    vec3 param_12 = flrInput.color.zyx;
    float param_13 = _425.frameParameters0.y;
    vec4 param_14 = vec4(0.0);
    vec4 param_15 = _615.paramData3;
    vec3 _662 = applyVegetationAnimation(param_8, param_9, param_10, param_11, param_12, param_13, param_14, param_15);
    prevPosWS = _662;
    flrOutput.position = _665.viewProjMatrix * vec4(posWS, 1.0);
    flrOutput.normal = normalWS;
    vec3 _686 = normalize((_443.worldMatrix * vec4(localTangent, 0.0)).xyz);
    flrOutput.tangent = vec4(_686.x, _686.y, _686.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 = _665.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 = inColor;
    flrInput.skinningBufferOffset = _443.params0.x;
    flrInput.instancingBufferOffset = _443.params0.y;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    
// Vk3DVision (http://3dsurroundgaming.com/) - Stereo Injection
//flrOutput.position.x += vk3d_params.stereo.x * (flrOutput.position.w - vk3d_params.stereo.y);
gl_Position = flrOutput.position;
    outUV0 = flrOutput.uv0;
    outPosWS = flrOutput.posWS;
}


