//More smoke PS.
#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;
    float flow;
    vec4 dissolve;
};

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

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

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

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

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

layout(set = 2, binding = 0) uniform texture2D globalTextures[];
layout(set = 1, binding = 0) uniform sampler linearClampSampler;
layout(set = 1, binding = 1) uniform sampler linearRepeatSampler;
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 textureCube globalCubeTextures[];
layout(set = 2, binding = 0) uniform texture3D global3DTextures[];
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 = 12) in float inFlow;
layout(location = 10) in vec4 inDissolve;
layout(location = 0) out vec4 outOITAccum;
layout(location = 1) out float outOITReveal;

vec2 _315;
float _591;

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

vec2 computeFlipbookCoord(vec2 p_uv, uint p_flipbookHorizontalImages, uint p_flipbookVerticalImages, uint p_flipbookFramerate, float p_time)
{
    if ((p_flipbookHorizontalImages > 1u) || (p_flipbookVerticalImages > 1u))
    {
        uint index = uint(p_time * float(max((p_flipbookFramerate - 1u), 0u)));
        index %= (p_flipbookHorizontalImages * p_flipbookVerticalImages);
        vec2 size = vec2(1.0 / float(p_flipbookHorizontalImages), 1.0 / float(p_flipbookVerticalImages));
        uint u = index % p_flipbookHorizontalImages;
        uint v = index / p_flipbookHorizontalImages;
        vec2 offset = vec2(float(u) * size.x, float(v) * size.y);
        return (p_uv * size) + offset;
    }
    else
    {
        return p_uv;
    }
}

vec4 flrSampleBindless(sampler samplerState, vec2 uv, uint textureIdx)
{
    return texture(sampler2D(globalTextures[nonuniformEXT(textureIdx)], samplerState), uv);
}

vec4 applyDistortAndFlow(vec2 p_uv0, inout vec2 p_uv1, float p_lifetimePerc, uint p_renderingFlags, float p_flowFrequency, float p_flowStrength, float p_flowOverLifetime, float p_distortStrength, uint flowTexId, uint distortTexId, uint spriteTexId)
{
    vec4 diffuse = vec4(0.0);
    vec2 uvResult = vec2(0.0);
    if ((p_renderingFlags & 256u) > 0u)
    {
        vec2 param = p_uv0;
        uint param_1 = flowTexId;
        vec2 flowSample = (flrSampleBindless(linearClampSampler, param, param_1).wy * 2.0) - vec2(1.0);
        float l0 = length(flowSample);
        if (l0 < 0.00999999977648258209228515625)
        {
            flowSample = vec2(0.0);
        }
        float time = mod(p_lifetimePerc * p_flowFrequency, 1.0);
        vec2 flow = (flowSample * p_flowOverLifetime) * p_flowStrength;
        vec2 scale = vec2(time, mod(time + 0.5, 1.0));
        float flowLayerBlendFactor = 2.0 * abs(time - 0.5);
        vec4 flowUv = flow.xyxy * scale.xxyy;
        if ((p_renderingFlags & 64u) > 0u)
        {
            vec2 param_2 = p_uv0 + flowUv.xy;
            uint param_3 = distortTexId;
            vec2 distort0 = flrSampleBindless(linearClampSampler, param_2, param_3).wy;
            vec2 param_4 = p_uv0 + flowUv.zw;
            uint param_5 = distortTexId;
            vec2 distort1 = flrSampleBindless(linearClampSampler, param_4, param_5).wy;
            vec2 distortMapValue = (mix(distort0, distort1, vec2(flowLayerBlendFactor)) * 2.0) - vec2(1.0);
            float l1 = length(distortMapValue);
            if (l1 < 0.00999999977648258209228515625)
            {
                distortMapValue = vec2(0.0);
            }
            flowUv += (distortMapValue.xyxy * p_distortStrength);
        }
        vec2 param_6 = p_uv1 + flowUv.xy;
        uint param_7 = spriteTexId;
        vec4 diffuse0 = flrSampleBindless(linearRepeatSampler, param_6, param_7);
        vec2 param_8 = p_uv1 + flowUv.zw;
        uint param_9 = spriteTexId;
        vec4 diffuse1 = flrSampleBindless(linearRepeatSampler, param_8, param_9);
        diffuse = mix(diffuse0, diffuse1, vec4(flowLayerBlendFactor));
        uvResult += mix(flowUv.xy, flowUv.zw, vec2(flowLayerBlendFactor));
    }
    else
    {
        if ((p_renderingFlags & 64u) > 0u)
        {
            vec2 param_10 = p_uv0;
            uint param_11 = distortTexId;
            vec2 distortMapValue_1 = (flrSampleBindless(linearClampSampler, param_10, param_11).wy * 2.0) - vec2(1.0);
            float l0_1 = length(distortMapValue_1);
            if (l0_1 < 0.00999999977648258209228515625)
            {
                distortMapValue_1 = vec2(0.0);
            }
            uvResult += (distortMapValue_1 * p_distortStrength);
            vec2 param_12 = p_uv1 + uvResult;
            uint param_13 = spriteTexId;
            diffuse = flrSampleBindless(linearRepeatSampler, param_12, param_13);
        }
        else
        {
            vec2 param_14 = p_uv1 + uvResult;
            uint param_15 = spriteTexId;
            diffuse = flrSampleBindless(linearRepeatSampler, param_14, param_15);
        }
    }
    p_uv1 = uvResult;
    return diffuse;
}

float applyDissolve(uint p_renderingFlags, vec2 p_uv0, vec4 p_dissolveFadeThreshold, vec4 p_dissolveOverTime, uint dissolveTexId)
{
    if ((p_renderingFlags & 128u) > 0u)
    {
        vec2 param = p_uv0;
        uint param_1 = dissolveTexId;
        vec4 diff = flrSampleBindless(linearRepeatSampler, param, param_1) - p_dissolveOverTime;
        vec4 dissolveFadeThresholdClamped = max(p_dissolveFadeThreshold, vec4(9.9999999747524270787835121154785e-07));
        vec4 alphaMod = vec4(1.0 - (max((dissolveFadeThresholdClamped.x - diff.x) - dissolveFadeThresholdClamped.x, 0.0) / dissolveFadeThresholdClamped.x), 1.0 - (max((dissolveFadeThresholdClamped.y - diff.y) - dissolveFadeThresholdClamped.y, 0.0) / dissolveFadeThresholdClamped.y), 1.0 - (max((dissolveFadeThresholdClamped.z - diff.z) - dissolveFadeThresholdClamped.z, 0.0) / dissolveFadeThresholdClamped.z), 1.0 - (max((dissolveFadeThresholdClamped.w - diff.w) - dissolveFadeThresholdClamped.w, 0.0) / dissolveFadeThresholdClamped.w));
        return clamp(((alphaMod.x * alphaMod.y) * alphaMod.z) * alphaMod.w, 9.9999999747524270787835121154785e-07, 1.0);
    }
    else
    {
        return 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 ((_601.parameters_0.x & 2048u) > 0u)
    {
        scaledUV *= _612.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 = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].fade_near_distance;
    ped.fade_near_interval = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].fade_near_interval;
    ped.fade_far_distance = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].fade_far_distance;
    ped.fade_far_interval = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].fade_far_interval;
    ped.soft_edge_fade_distance = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].soft_edge_fade_distance;
    ped.flipbook_horizontal_images = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flipbook_horizontal_images;
    ped.flipbook_vertical_images = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flipbook_vertical_images;
    ped.flipbook_framerate = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flipbook_framerate;
    ped.sprite_texture_id = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].sprite_texture_id;
    ped.dissolve_texture_id = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].dissolve_texture_id;
    ped.distort_texture_id = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].distort_texture_id;
    ped.flow_texture_id = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flow_texture_id;
    ped.flow_frequency = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flow_frequency;
    ped.flow_strength = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].flow_strength;
    ped.distort_strength = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].distort_strength;
    ped.distort_chromashift_strength = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].distort_chromashift_strength;
    ped.dissolve_fade_threshold = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].dissolve_fade_threshold;
    ped.procedural_attenuation_constant = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].procedural_attenuation_constant;
    ped.procedural_attenuation_linear = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].procedural_attenuation_linear;
    ped.procedural_attenuation_quadratic = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].procedural_attenuation_quadratic;
    ped.padding0 = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].padding0;
    ped.trail_fade_start_distance = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].trail_fade_start_distance;
    ped.trail_fade_start_interval = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].trail_fade_start_interval;
    ped.trail_fade_end_distance = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].trail_fade_end_distance;
    ped.trail_fade_end_interval = _642._ParticleEmitterSpriteRenderingFragmentDataBuffer[_601.parameters_0.z].trail_fade_end_interval;
    float param = flrInput.coords.z;
    float param_1 = _612.nearFar.x;
    float param_2 = _612.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 = _612.nearFar.x;
    float param_11 = _612.nearFar.y;
    float linDepth = -deviceDepthToLinear(param_9, param_10, param_11);
    uint param_12 = _601.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;
    vec2 param_16 = flrInput.uv0;
    uint param_17 = ped.flipbook_horizontal_images;
    uint param_18 = ped.flipbook_vertical_images;
    uint param_19 = ped.flipbook_framerate;
    float param_20 = flrInput.lifetime_perc;
    vec2 uv1 = computeFlipbookCoord(param_16, param_17, param_18, param_19, param_20);
    vec2 param_21 = flrInput.uv0;
    vec2 param_22 = uv1;
    float param_23 = flrInput.lifetime_perc;
    uint param_24 = _601.parameters_0.x;
    float param_25 = ped.flow_frequency;
    float param_26 = ped.flow_strength;
    float param_27 = flrInput.flow;
    float param_28 = ped.distort_strength;
    uint param_29 = ped.flow_texture_id;
    uint param_30 = ped.distort_texture_id;
    uint param_31 = ped.sprite_texture_id;
    vec4 _844 = applyDistortAndFlow(param_21, param_22, param_23, param_24, param_25, param_26, param_27, param_28, param_29, param_30, param_31);
    uv1 = param_22;
    vec4 diffuse = _844;
    vec2 dissolveUv = flrInput.uv0;
    if ((_601.parameters_0.x & 4096u) > 0u)
    {
        dissolveUv += uv1;
    }
    uint param_32 = _601.parameters_0.x;
    vec2 param_33 = dissolveUv;
    vec4 param_34 = ped.dissolve_fade_threshold;
    vec4 param_35 = flrInput.dissolve;
    uint param_36 = ped.dissolve_texture_id;
    float alphaMod = applyDissolve(param_32, param_33, param_34, param_35, param_36);
    color *= (diffuse * alphaMod);
    if ((_601.parameters_0.x & 512u) > 0u)
    {
        float param_37 = ped.trail_fade_start_distance;
        float param_38 = ped.trail_fade_start_interval;
        float param_39 = length(flrInput.position - flrInput.prev_position);
        float param_40 = ped.trail_fade_end_distance;
        float param_41 = ped.trail_fade_end_interval;
        float param_42 = length(_601.parameters_1.xyz - flrInput.position);
        color *= (1.0 - clamp(calcNearFade(param_37, param_38, param_39) + calcNearFade(param_40, param_41, param_42), 0.0, 1.0));
    }
    if (color.w < 0.001000000047497451305389404296875)
    {
        discard;
    }
    vec3 param_43 = flrInput.coords;
    float param_44 = _612.volumetricsParams2.y;
    float param_45 = _612.volumetricsParams2.z;
    vec2 param_46 = _612.nearFar.xy;
    
    //Fix here.
    param_43.x -= vk3d_params.stereo.x *(1-vk3d_params.stereo.y*param_43.z*0.0)*0.5;
    
    vec3 _941 = cellCenterSSToUVW(param_43, param_44, param_45, param_46);
    vec3 scatteringUVW = _941;
    if ((_601.parameters_0.x & 2u) == 0u)
    {
        vec4 volSample = vec4(1.0);
        if (_601.parameters_0.y == 0u)
        {
            volSample = textureLod(lightingTex0, scatteringUVW, 0.0);
        }
        else
        {
            volSample = textureLod(lightingTex1, scatteringUVW, 0.0);
        }
        vec3 _971 = color.xyz * volSample.xyz;
        color = vec4(_971.x, _971.y, _971.z, color.w);
    }
    vec4 volSample_1 = textureLod(scatterTex, scatteringUVW, 0.0);
    float weight = (1.0 - volSample_1.w) * _612.volumetricsParams2.w;
    vec3 _992 = mix(color.xyz, volSample_1.xyz, vec3(weight));
    color = vec4(_992.x, _992.y, _992.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 _1042 = (flrInput.coords.xy * 0.5) + vec2(0.5);
    flrInput.coords = vec3(_1042.x, _1042.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.flow = inFlow;
    flrInput.dissolve = inDissolve;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    outOITAccum = flrOutput.weighted_color;
    outOITReveal = flrOutput.alpha;
}


