//Particles PS 1.
#version 450
#extension GL_EXT_nonuniform_qualifier : require

struct FlrInput
{
    vec3 coords;
    vec3 normal;
    vec3 binormal;
    vec4 tangent;
    vec3 position;
    vec3 prev_position;
    vec4 color;
    vec2 uv0;
    float lifetime_perc;
};

struct FlrOutput
{
    vec4 weighted_color;
    float alpha;
};

struct ParticleEmitterSpriteRenderingFragmentData
{
    float fade_near_distance;
    float fade_near_interval;
    float fade_far_distance;
    float fade_far_interval;
    float soft_edge_fade_distance;
    uint flipbook_horizontal_images;
    uint flipbook_vertical_images;
    uint flipbook_framerate;
    uint sprite_texture_id;
    uint dissolve_texture_id;
    uint distort_texture_id;
    uint flow_texture_id;
    float flow_frequency;
    float flow_strength;
    float distort_strength;
    float distort_chromashift_strength;
    vec4 dissolve_fade_threshold;
    float procedural_attenuation_constant;
    float procedural_attenuation_linear;
    float procedural_attenuation_quadratic;
    float padding0;
    float trail_fade_start_distance;
    float trail_fade_start_interval;
    float trail_fade_end_distance;
    float trail_fade_end_interval;
};

// 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 = 22, std140) uniform PerInstance
{
    uvec4 parameters_0;
    vec4 parameters_1;
} _234;

layout(set = 0, binding = 21, std140) uniform PerView
{
    vec4 nearFar;
    vec4 volumetricsParams2;
    vec4 dynamicResolutionParameters;
} _245;

layout(set = 0, binding = 27, std430) readonly buffer ParticleEmitterSpriteRenderingFragmentDataBuffer
{
    ParticleEmitterSpriteRenderingFragmentData _ParticleEmitterSpriteRenderingFragmentDataBuffer[];
} _277;

layout(set = 0, binding = 20, 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;
} _690;

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

layout(set = 0, binding = 23) uniform sampler2D depthBufferTex;
layout(set = 0, binding = 24) uniform sampler3D lightingTex0;
layout(set = 0, binding = 25) uniform sampler3D lightingTex1;
layout(set = 0, binding = 26) uniform sampler3D scatterTex;
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 = 6) in vec4 inPosition;
layout(location = 1) in vec2 inUV0;
layout(location = 0) in vec3 inNormal;
layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec3 inBinormal;
layout(location = 5) in vec4 inColor;
layout(location = 11) in float inLifetimePerc;
layout(location = 7) in vec4 inPrevPosition;
layout(location = 4) in vec3 inPosWS;
layout(location = 0) out vec4 outOITAccum;
layout(location = 1) out float outOITReveal;
layout(location = 10) in vec4 inDissolve;
layout(location = 12) in float inFlow;

float deviceDepthToLinear(float deviceDepth, float near, float far)
{
    return -((far * near) / ((deviceDepth * (far - near)) + near));
}

float calcNearFade(float p_fadeNearDistance, float p_fadeNearInterval, float p_depth)
{
    float fade = 0.0;
    if (p_fadeNearDistance > 9.9999999747524270787835121154785e-07)
    {
        float fadeNearEndDistance = p_fadeNearDistance + p_fadeNearInterval;
        if (p_depth < fadeNearEndDistance)
        {
            fade += clamp((fadeNearEndDistance - p_depth) / max(p_fadeNearInterval, 9.9999999747524270787835121154785e-07), 0.0, 1.0);
        }
    }
    return fade;
}

float calcFarFade(float p_fadeFarDistance, float p_fadeFarInterval, float p_depth)
{
    float fade = 0.0;
    if (p_fadeFarDistance > 9.9999999747524270787835121154785e-07)
    {
        float fadeFarStartDistance = p_fadeFarDistance - p_fadeFarInterval;
        if (p_depth > fadeFarStartDistance)
        {
            fade += clamp((p_depth - fadeFarStartDistance) / max(p_fadeFarInterval, 9.9999999747524270787835121154785e-07), 0.0, 1.0);
        }
    }
    return fade;
}

float calculateSoftEdgeFade(uint p_renderingFlags, float p_fadeDistance, float p_particleDepth, float p_depth)
{
    float fade = 1.0;
    if (((p_renderingFlags & 4u) > 0u) && (p_fadeDistance > 9.9999999747524270787835121154785e-07))
    {
        float fadeDistanceSquared = max(p_fadeDistance * p_fadeDistance, 9.9999999747524270787835121154785e-07);
        float partDepthDist = abs(p_depth - p_particleDepth);
        if (partDepthDist < fadeDistanceSquared)
        {
            fade = clamp(partDepthDist / fadeDistanceSquared, 0.0, 1.0);
        }
    }
    return fade;
}

float getAttenuationFromConstantLinearQuadratic(float p_distance, float p_constantAttenuation, float p_linearAttenuation, float p_quadraticAttenuation)
{
    return clamp((p_constantAttenuation + (p_linearAttenuation * p_distance)) + ((p_quadraticAttenuation * p_distance) * p_distance), 0.0, 1.0);
}

float nativeDepthToVolumeZ(float depth, float invDepthExp, float depthRange, vec2 nearFar)
{
    float param = depth;
    float param_1 = nearFar.x;
    float param_2 = nearFar.y;
    float depthLinear = -deviceDepthToLinear(param, param_1, param_2);
    return pow(clamp((depthLinear - nearFar.x) / depthRange, 0.0, 1.0) + 9.9999999392252902907785028219223e-09, invDepthExp);
}

vec3 cellCenterSSToUVW(inout vec3 cellCenter, float invDepthExp, float depthRange, vec2 nearFar)
{
    float param = cellCenter.z;
    float param_1 = invDepthExp;
    float param_2 = depthRange;
    vec2 param_3 = nearFar;
    cellCenter.z = nativeDepthToVolumeZ(param, param_1, param_2, param_3);
    return cellCenter;
}

void flrMain(FlrInput flrInput, inout FlrOutput flrOutput)
{
    vec2 scaledUV = flrInput.coords.xy;
    if ((_234.parameters_0.x & 2048u) > 0u)
    {
        scaledUV *= _245.dynamicResolutionParameters.xy;
    }
    float depth = textureLod(depthBufferTex, scaledUV, 0.0).x;
    if ((flrInput.coords.z - depth) < 9.9999999747524270787835121154785e-07)
    {
        discard;
    }
    ParticleEmitterSpriteRenderingFragmentData ped;
    ped.fade_near_distance = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].fade_near_distance;
    ped.fade_near_interval = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].fade_near_interval;
    ped.fade_far_distance = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].fade_far_distance;
    ped.fade_far_interval = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].fade_far_interval;
    ped.soft_edge_fade_distance = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].soft_edge_fade_distance;
    ped.flipbook_horizontal_images = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flipbook_horizontal_images;
    ped.flipbook_vertical_images = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flipbook_vertical_images;
    ped.flipbook_framerate = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flipbook_framerate;
    ped.sprite_texture_id = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].sprite_texture_id;
    ped.dissolve_texture_id = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].dissolve_texture_id;
    ped.distort_texture_id = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].distort_texture_id;
    ped.flow_texture_id = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flow_texture_id;
    ped.flow_frequency = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flow_frequency;
    ped.flow_strength = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].flow_strength;
    ped.distort_strength = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].distort_strength;
    ped.distort_chromashift_strength = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].distort_chromashift_strength;
    ped.dissolve_fade_threshold = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].dissolve_fade_threshold;
    ped.procedural_attenuation_constant = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].procedural_attenuation_constant;
    ped.procedural_attenuation_linear = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].procedural_attenuation_linear;
    ped.procedural_attenuation_quadratic = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].procedural_attenuation_quadratic;
    ped.padding0 = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].padding0;
    ped.trail_fade_start_distance = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].trail_fade_start_distance;
    ped.trail_fade_start_interval = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].trail_fade_start_interval;
    ped.trail_fade_end_distance = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].trail_fade_end_distance;
    ped.trail_fade_end_interval = _277._ParticleEmitterSpriteRenderingFragmentDataBuffer[_234.parameters_0.z].trail_fade_end_interval;
    float param = flrInput.coords.z;
    float param_1 = _245.nearFar.x;
    float param_2 = _245.nearFar.y;
    float linDepthParticle = -deviceDepthToLinear(param, param_1, param_2);
    float param_3 = ped.fade_near_distance;
    float param_4 = ped.fade_near_interval;
    float param_5 = linDepthParticle;
    float param_6 = ped.fade_far_distance;
    float param_7 = ped.fade_far_interval;
    float param_8 = linDepthParticle;
    float nearFarFade = 1.0 - clamp(calcNearFade(param_3, param_4, param_5) + calcFarFade(param_6, param_7, param_8), 0.0, 1.0);
    if (nearFarFade < 0.001000000047497451305389404296875)
    {
        discard;
    }
    float param_9 = depth;
    float param_10 = _245.nearFar.x;
    float param_11 = _245.nearFar.y;
    float linDepth = -deviceDepthToLinear(param_9, param_10, param_11);
    uint param_12 = _234.parameters_0.x;
    float param_13 = ped.soft_edge_fade_distance;
    float param_14 = linDepthParticle;
    float param_15 = linDepth;
    float softEdgeFade = clamp(calculateSoftEdgeFade(param_12, param_13, param_14, param_15), 0.0, 1.0);
    vec4 color = (flrInput.color.zyxw * nearFarFade) * softEdgeFade;
    if ((_234.parameters_0.x & 512u) == 0u)
    {
        float param_16 = clamp(1.0 - length((flrInput.uv0 * 2.0) - vec2(1.0)), 0.0, 1.0);
        float param_17 = ped.procedural_attenuation_constant;
        float param_18 = ped.procedural_attenuation_linear;
        float param_19 = ped.procedural_attenuation_quadratic;
        float fade = getAttenuationFromConstantLinearQuadratic(param_16, param_17, param_18, param_19);
        color *= fade;
    }
    if ((_234.parameters_0.x & 512u) > 0u)
    {
        float param_20 = ped.trail_fade_start_distance;
        float param_21 = ped.trail_fade_start_interval;
        float param_22 = length(flrInput.position - flrInput.prev_position);
        float param_23 = ped.trail_fade_end_distance;
        float param_24 = ped.trail_fade_end_interval;
        float param_25 = length(_234.parameters_1.xyz - flrInput.position);
        color *= (1.0 - clamp(calcNearFade(param_20, param_21, param_22) + calcNearFade(param_23, param_24, param_25), 0.0, 1.0));
    }
    if (color.w < 0.001000000047497451305389404296875)
    {
        discard;
    }
    vec3 param_26 = flrInput.coords;
    float param_27 = _245.volumetricsParams2.y;
    float param_28 = _245.volumetricsParams2.z;
    vec2 param_29 = _245.nearFar.xy;
    
    //Fix here.
    param_26.x -= vk3d_params.stereo.x * (1-vk3d_params.stereo.y*param_26.z*0.0) * 0.5;
    
    vec3 _522 = cellCenterSSToUVW(param_26, param_27, param_28, param_29);
    vec3 scatteringUVW = _522;
    if ((_234.parameters_0.x & 2u) == 0u)
    {
        vec4 volSample = vec4(1.0);
        if (_234.parameters_0.y == 0u)
        {
            volSample = textureLod(lightingTex0, scatteringUVW, 0.0);
        }
        else
        {
            volSample = textureLod(lightingTex1, scatteringUVW, 0.0);
        }
        vec3 _552 = color.xyz * volSample.xyz;
        color = vec4(_552.x, _552.y, _552.z, color.w);
    }
    vec4 volSample_1 = textureLod(scatterTex, scatteringUVW, 0.0);
    float weight = (1.0 - volSample_1.w) * _245.volumetricsParams2.w;
    vec3 _573 = mix(color.xyz, volSample_1.xyz, vec3(weight));
    color = vec4(_573.x, _573.y, _573.z, color.w);
    float oitWeight = clamp(0.02999999932944774627685546875 / (9.9999997473787516355514526367188e-06 + pow((1.0 - flrInput.coords.z) / 200.0, 4.0)), 9.9999997473787516355514526367188e-06, 100000.0);
    flrOutput.weighted_color = vec4(color.xyz * color.w, color.w) * oitWeight;
    flrOutput.alpha = color.w;
}

void main()
{
    FlrInput flrInput;
    flrInput.coords = inPosition.xyz / vec3(inPosition.w);
    vec2 _624 = (flrInput.coords.xy * 0.5) + vec2(0.5);
    flrInput.coords = vec3(_624.x, _624.y, flrInput.coords.z);
    flrInput.uv0 = inUV0;
    flrInput.normal = inNormal;
    flrInput.tangent = inTangent;
    flrInput.binormal = inBinormal;
    flrInput.color = inColor;
    flrInput.lifetime_perc = inLifetimePerc;
    flrInput.prev_position = inPrevPosition.xyz;
    flrInput.position = inPosWS;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    outOITAccum = flrOutput.weighted_color;
    outOITReveal = flrOutput.alpha;
}


