//Motion blur CS.
#version 450
#extension GL_EXT_nonuniform_qualifier : require
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

// 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 = 10, std140) uniform PerInstance
{
    vec4 motionblur_parameters;
    vec4 ouput_dims;
} _355;

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

layout(set = 0, binding = 1) uniform sampler2D sceneSampler;
layout(set = 0, binding = 2) uniform sampler2D randomSampler;
layout(set = 0, binding = 3) uniform sampler2D neighborMaxSampler;
layout(set = 0, binding = 4) uniform sampler2D encodedVelocitySampler;
layout(set = 0, binding = 0, rgba16f) uniform writeonly image2D outputTex;
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;

vec3 getVelocityAndLength(vec2 velocity, float halfExposureXFramerate)
{
    vec2 _71 = velocity * halfExposureXFramerate;
    vec3 velAndLen;
    velAndLen = vec3(_71.x, _71.y, velAndLen.z);
    float invLen = inversesqrt(dot(velAndLen.xy, velAndLen.xy) + 9.9999999747524270787835121154785e-07);
    vec2 _91 = velAndLen.xy * clamp(0.014999999664723873138427734375 * invLen, 0.0, 1.0);
    velAndLen = vec3(_91.x, _91.y, velAndLen.z);
    velAndLen.z = sqrt(length(velAndLen.xy) * 32.0);
    return velAndLen;
}

vec4 decodeMotionData(vec4 encodedMotionData)
{
    vec4 motionData = encodedMotionData;
    vec2 _55 = (encodedMotionData.xy - vec2(0.4980392158031463623046875)) * 2.0;
    motionData = vec4(_55.x, _55.y, motionData.z, motionData.w);
    motionData.w *= 255.0;
    return motionData;
}

vec2 softDepthCompare(vec2 z0, vec2 z1, vec2 softZ)
{
    return clamp((vec2(1.0) + (z0 * softZ)) - (z1 * softZ), vec2(0.0), vec2(1.0));
}

vec4 velocityCmp(float lenStep, vec2 lenVel)
{
    return clamp(vec4((vec4(1.0) - (vec4(lenStep) * (vec4(1.0) / lenVel.xyxy))) + vec4(0.0, 0.0, 0.949999988079071044921875, 0.949999988079071044921875)), vec4(0.0), vec4(1.0));
}

vec4 getMotionBlur(sampler2D sceneSampler_1, sampler2D randomSampler_1, sampler2D neighborMaxSampler_1, sampler2D encodedVelocitySampler_1, vec2 screenUV, vec3 position, float halfExposureXFramerate)
{
    vec2 velMax = textureLod(neighborMaxSampler_1, screenUV, 0.0).xy;
    vec2 param = velMax;
    float param_1 = halfExposureXFramerate;
    velMax = getVelocityAndLength(param, param_1).xy;
    vec4 colorCenter = textureLod(sceneSampler_1, screenUV, 0.0);
    
    
    
    vec2 startUV = screenUV - velMax;
    
    
    
    vec2 stepUV = (velMax * 0.0909090936183929443359375) * 2.0;
    vec4 param_2 = textureLod(encodedVelocitySampler_1, screenUV, 0.0);
    
    //param_2.x= vk3d_params.stereo.x;
    
    vec4 motionDataX = decodeMotionData(param_2);
    
    
    
    float depthX = motionDataX.w;
    float velLenX = (motionDataX.z * motionDataX.z) * 0.03125;
    float startLen = -length(velMax);
    float stepLen = (abs(startLen) * 0.0909090936183929443359375) * 2.0;
    float weightCenter = 0.375 * (1.0 / max(velLenX * halfExposureXFramerate, 1.0));
    float samplingDither = ((texelFetch(randomSampler_1, ivec2(position.xy) & ivec2(255), 0).x - 0.5) * 2.0) - 1.0;
    float weight = weightCenter;
    vec3 color = vec3(0.0);
    for (int stepIdx = 0; stepIdx < 12; stepIdx++)
    {
        vec2 sampleUV = startUV + (stepUV * (float(stepIdx) + samplingDither));
        vec4 param_3 = textureLod(encodedVelocitySampler_1, sampleUV, 0.0);
        vec4 motionDataY = decodeMotionData(param_3);
        float depthY = motionDataY.w;
        float velLenY = (motionDataY.z * motionDataY.z) / 32.0;
        float velLenStep = abs(startLen + (stepLen * (float(stepIdx) + samplingDither)));
        vec2 cmp0 = softDepthCompare(vec2(depthX, depthY), vec2(depthY, depthX), vec2(1.0));
        vec4 cmp1 = velocityCmp(velLenStep, max(vec2(9.9999997473787516355514526367188e-06), vec2(velLenY, velLenX)));
        float sampleWeight = dot(cmp0, cmp1.xy) + ((cmp1.z * cmp1.w) * 2.0);
        color += (textureLod(sceneSampler_1, sampleUV, 0.0).xyz * sampleWeight);
        weight += sampleWeight;
    }
    if (weightCenter > 0.0)
    {
        color += (colorCenter.xyz * weightCenter);
    }
    float motionBlurMask = (dot(velMax, velMax) * (weight / 12.0)) * 20000.0;
    vec4 finalColor = vec4(color / vec3(weight), motionBlurMask);
    return finalColor;
}

void main()
{
    uvec3 cellCoord = gl_GlobalInvocationID;
    vec3 cellCenter = vec3(cellCoord) + vec3(0.5);
    vec2 uv = cellCenter.xy / vec2(_355.ouput_dims.xy);
    vec2 param = uv;
    vec3 param_1 = vec3(cellCoord);
    float param_2 = _355.motionblur_parameters.y;
    vec4 color = getMotionBlur(sceneSampler, randomSampler, neighborMaxSampler, encodedVelocitySampler, param, param_1, param_2);
    imageStore(outputTex, ivec2(cellCoord.xy), vec4(color));
}


