//Hologram lighting PS.
#version 450
#extension GL_EXT_nonuniform_qualifier : require

struct FlrInput
{
    vec2 uv0;
    vec4 pos;
};

struct FlrOutput
{
    vec4 emissive;
    vec4 distortVector;
    vec4 postFXMask;
    vec2 motionVector;
};

struct SH9Compressed
{
    uvec4 data0[2];
    uvec4 data1;
};

// 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 = 31, std140) uniform PerMaterial
{
    uvec4 paramIntData0;
    vec4 paramData0;
    vec4 paramData1;
    vec4 paramData2;
    vec4 paramData3;
    vec4 paramData4;
    vec4 paramData5;
    vec4 paramData6;
    vec4 paramData7;
    vec4 paramData8;
    vec4 paramData9;
    uvec4 paramImgIDs0;
    uvec4 paramImgIDs1;
    uvec4 paramImgIDs2;
} _276;

layout(set = 0, binding = 32, std140) uniform PerView
{
    mat4 invViewProjMatrix;
    mat4 invProjMatrix;
    vec4 nearFar;
    vec4 nearFarWidthHeight;
    vec4 cameraPositionWS;
    vec4 dirLightDirWS;
    vec4 dirLightColorAndIntens;
    uvec4 dirLightProjectorParams;
    vec4 dirLightProjectorTransform;
    mat4 dirLightProjectorViewProjMatrix;
    SH9Compressed skyModelSH;
    SH9Compressed globalBackgroundSH;
    mat4 pssmViewProjMatrices[5];
    mat4 localLightViewProjMatrices[16];
    vec4 shadowParameters0;
    vec4 playerWorldPosition;
    vec4 lightingWeights0;
    vec4 lightingWeights1;
    vec4 dynamicResolutionParameters;
    vec4 frameParameters0;
    vec4 frameParameters1;
    vec4 projectionOffsets;
    vec4 irradianceGridWorldPosition;
    vec4 irradianceGridHalfExtents;
    uvec4 irradianceGridResolution;
    mat4 viewMatrix;
    vec4 volumetricsParams2;
} _312;

layout(set = 0, binding = 30, std140) uniform PerInstance
{
    uvec4 params0;
    vec4 materialParams0;
    vec4 materialParams1;
    vec4 materialParams2;
    vec4 materialParams3;
} _522;

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

layout(set = 0, binding = 25) uniform sampler2D flowTex;
layout(set = 0, binding = 20) uniform sampler2D emissiveTex;
layout(set = 0, binding = 22) uniform sampler2D distortTex;
layout(set = 0, binding = 24) uniform sampler2D postFXMaskTex;
layout(set = 0, binding = 23) uniform sampler2D distortMaskTex;
layout(set = 0, binding = 21) uniform sampler2D emissiveMaskTex;
layout(set = 0, binding = 26) uniform sampler3D scatterBufferTex;
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 = 1) in vec2 inUV0;
layout(location = 6) in vec4 inPosition;
layout(location = 0) out vec4 outEmissive;
layout(location = 1) out vec4 outDistortVector;
layout(location = 2) out vec4 postFXMask;
layout(location = 3) out vec4 outMotionVector;
layout(location = 0) in vec3 inNormal;
layout(location = 2) in vec4 inTangent;
layout(location = 3) in vec3 inBinormal;

vec4 computeFlowData(inout vec2 flowSample, float time, float flowSpeed, float flowStrength)
{
    float l0 = length(flowSample);
    if (l0 < 0.00999999977648258209228515625)
    {
        flowSample = vec2(0.0);
    }
    vec2 flow = flowSample * flowStrength;
    vec2 scale = fract(vec2((time * flowSpeed) - 0.5, time * flowSpeed));
    return vec4(flow, scale);
}

vec4 computeFlowData(sampler2D _flowMap, vec2 _flowMapUV, float time, float flowSpeed, float flowStrength)
{
    vec2 flowSample = (texture(_flowMap, _flowMapUV).wy * 2.0) - vec2(1.0);
    vec2 param = flowSample;
    float param_1 = time;
    float param_2 = flowSpeed;
    float param_3 = flowStrength;
    vec4 _145 = computeFlowData(param, param_1, param_2, param_3);
    return _145;
}

vec4 computeFlowmapColor(sampler2D _inputTex, vec2 _inputUV, vec4 _flowData)
{
    vec2 scale = _flowData.zw;
    float flowLayerBlendFactor = abs((0.5 - scale.x) / 0.5);
    vec4 flowUV = _flowData.xyxy * scale.xxyy;
    vec4 val0 = texture(_inputTex, _inputUV + flowUV.xy);
    vec4 val1 = texture(_inputTex, _inputUV + flowUV.zw);
    return mix(val0, val1, vec4(flowLayerBlendFactor));
}

float nrand(float x, float y)
{
    return fract(sin(dot(vec2(x, y), vec2(12.98980045318603515625, 78.233001708984375))) * 43758.546875);
}

vec4 decodeRGBA8uint(uint colorU)
{
    return vec4(float((colorU & 4278190080u) >> uint(24)) * 0.003921560011804103851318359375, float((colorU & 16711680u) >> uint(16)) * 0.003921560011804103851318359375, float((colorU & 65280u) >> uint(8)) * 0.003921560011804103851318359375, float(colorU & 255u) * 0.003921560011804103851318359375);
}

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

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 uv = (flrInput.uv0 * _276.paramData0.zw) + _276.paramData0.xy;
    if ((_276.paramIntData0.x & 1u) > 0u)
    {
        uv = (flrInput.uv0 * _276.paramData0.zw) + (_276.paramData0.xy * _312.frameParameters0.x);
    }
    vec4 emissive = vec4(0.0);
    vec4 postFXMask_1 = vec4(1.0);
    vec2 distortVector = vec2(0.0);
    if ((_276.paramIntData0.x & 2u) > 0u)
    {
        vec2 param = flrInput.uv0;
        float param_1 = _312.frameParameters0.x;
        float param_2 = _276.paramData2.z;
        float param_3 = _276.paramData2.w;
        vec4 flowData = computeFlowData(flowTex, param, param_1, param_2, param_3);
        emissive = texture(emissiveTex, uv);
        vec2 param_4 = uv;
        vec4 param_5 = flowData;
        distortVector = computeFlowmapColor(distortTex, param_4, param_5).wy;
    }
    else
    {
        emissive = texture(emissiveTex, uv);
        distortVector = texture(distortTex, uv).wy;
        postFXMask_1 = texture(postFXMaskTex, uv);
    }
    postFXMask_1 *= _276.paramData6;
    if ((_276.paramIntData0.x & 8u) > 0u)
    {
        distortVector = (distortVector - vec2(0.5)) * 2.0;
    }
    float additionalChromaShift = 0.0;
    vec2 glitchVector = vec2(0.0);
    if ((_276.paramIntData0.x & 4u) > 0u)
    {
        vec2 glitchUV = ((flrInput.pos.xy * vec2(0.0005208333604969084262847900390625, 0.000925925909541547298431396484375)) + vec2(1.0)) * 0.5;
        float time = _312.frameParameters0.x;
        vec2 glitchAmount = _276.paramData5.xy;
        vec2 glitchStrength = _276.paramData4.xy;
        vec2 glitchBlockSize = vec2(1.0) - _276.paramData4.zw;
        float shakeStrength = 0.00999999977648258209228515625;
        float verticalJumpAmount = 1.0;
        float verticalJumpOffset = 1.0;
        float param_6 = glitchUV.x * glitchBlockSize.x;
        float param_7 = time;
        vec2 jitter;
        jitter.x = nrand(param_6, param_7);
        float param_8 = (glitchUV.y * glitchBlockSize.y) * 0.5625;
        float param_9 = time;
        jitter.y = nrand(param_8, param_9);
        glitchUV = (glitchUV + vec2(1.0)) * 0.5;
        float linkedGlitch = abs(jitter.x * jitter.y);
        vec2 glitchStep = vec2(linkedGlitch, linkedGlitch);
        jitter *= (step(vec2(1.0) - clamp(glitchAmount, vec2(0.0), vec2(1.0)), glitchStep) * glitchStrength);
        float jump = mix(glitchUV.y, fract(glitchUV.y + verticalJumpOffset), verticalJumpAmount);
        float param_10 = time;
        float param_11 = 2.0;
        float shake = (nrand(param_10, param_11) - 0.5) * shakeStrength;
        jitter = (jitter + vec2(1.0)) * 0.5;
        glitchVector = fract(vec2(jitter.x, jitter.y));
        glitchVector = (glitchVector * 2.0) - vec2(1.0);
        distortVector += glitchVector;
    }
    vec4 distortMask = texture(distortMaskTex, flrInput.uv0);
    flrOutput.motionVector = ((distortVector * _522.materialParams1.z) * distortMask.xx) * _276.paramData3.z;
    flrOutput.postFXMask = postFXMask_1;
    vec2 _546 = ((distortVector * _522.materialParams1.z) * distortMask.x) * _276.paramData3.x;
    flrOutput.distortVector = vec4(_546.x, _546.y, flrOutput.distortVector.z, flrOutput.distortVector.w);
    flrOutput.distortVector.z = ((((length(distortVector) * length(flrOutput.distortVector.xy)) + additionalChromaShift) + length(flrOutput.motionVector)) * _276.paramData3.y) * distortMask.y;
    flrOutput.distortVector.w = _522.materialParams0.x;
    vec4 emissiveMask = texture(emissiveMaskTex, flrInput.uv0);
    vec3 _590 = ((emissive.xyz * emissiveMask.xyz) * _276.paramData1.xyz) * _276.paramData2.x;
    flrOutput.emissive = vec4(_590.x, _590.y, _590.z, flrOutput.emissive.w);
    flrOutput.emissive.w = emissive.w * _276.paramData2.y;
    uint param_12 = floatBitsToUint(_522.materialParams0.w);
    vec3 perInstanceEmissiveTint = decodeRGBA8uint(param_12).xyz;
    vec3 _614 = flrOutput.emissive.xyz * (perInstanceEmissiveTint * _522.materialParams0.y);
    flrOutput.emissive = vec4(_614.x, _614.y, _614.z, flrOutput.emissive.w);
    flrOutput.emissive.w *= _522.materialParams0.x;
    vec3 screenUV = flrInput.pos.xyz / vec3(flrInput.pos.w);
    vec2 _636 = (screenUV.xy * 0.5) + vec2(0.5);
    screenUV = vec3(_636.x, _636.y, screenUV.z);
    vec3 param_13 = screenUV;
    float param_14 = _312.volumetricsParams2.y;
    float param_15 = _312.volumetricsParams2.z;
    vec2 param_16 = _312.nearFar.xy;
    
    //Fix here.
    param_13.x -= vk3d_params.stereo.x *(1-vk3d_params.stereo.y*param_13.z*0.0)*0.5;
    
    vec3 _653 = cellCenterSSToUVW(param_13, param_14, param_15, param_16);
    vec3 scatteringUVW = _653;
    vec4 volSample = textureLod(scatterBufferTex, scatteringUVW, 0.0);
    float weight = (1.0 - volSample.w) * _312.volumetricsParams2.w;
    vec3 _676 = mix(flrOutput.emissive.xyz, volSample.xyz, vec3(weight));
    flrOutput.emissive = vec4(_676.x, _676.y, _676.z, flrOutput.emissive.w);
}

void main()
{
    FlrInput flrInput;
    flrInput.uv0 = inUV0;
    flrInput.pos = inPosition;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    outEmissive = flrOutput.emissive;
    outDistortVector = flrOutput.distortVector;
    postFXMask = flrOutput.postFXMask;
    outMotionVector = vec4(flrOutput.motionVector.x, flrOutput.motionVector.y, outMotionVector.z, outMotionVector.w);
    outMotionVector = vec4(outMotionVector.x, outMotionVector.y, vec2(1.0).x, vec2(1.0).y);
}


