//Lighting PS 2. Volumetric lighting.
#version 450
#extension GL_EXT_nonuniform_qualifier : require

struct FlrInput
{
    vec2 uv0;
    mat4 invProjMatrix;
    vec4 volumetricsParams2;
    vec4 nearFar;
};

struct FlrOutput
{
    vec4 hdrColor;
};

// 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 = 0, std140) uniform PerView
{
    mat4 invProjMatrix;
    vec4 volumetricsParams2;
    vec4 nearFar;
    vec4 dynamicResolutionParameters;
} _108;

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

layout(set = 0, binding = 1) uniform sampler2D lightingBufferTex;
layout(set = 0, binding = 2) uniform sampler2D depthBufferTex;
layout(set = 0, binding = 3) 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 = 0) in vec2 inUV0;
layout(location = 0) out vec4 outHdrColor;

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

//Custom.
float linearDepthToDevice(float depthLinear, float near, float far)
{
    return -(((depthLinear + far) * near) / (depthLinear * (far - near)));
}
float volumeZToNativeDepth(float z, float depthExp, float depthRange, vec2 nearFar)
{
    float depthLinear = -((pow(abs(z), depthExp) * depthRange) + nearFar.x);
    float param = depthLinear;
    float param_1 = nearFar.x;
    float param_2 = nearFar.y;
    return linearDepthToDevice(param, param_1, param_2);
}


void flrMain(FlrInput flrInput, inout FlrOutput flrOutput)
{
    vec2 sampleUv = flrInput.uv0;
    sampleUv *= _108.dynamicResolutionParameters.xy;
    vec3 lighting = texture(lightingBufferTex, sampleUv).xyz;
    flrOutput.hdrColor = vec4(lighting, 1.0);
    float depth = texture(depthBufferTex, sampleUv).x;
    
    vec3 parama = vec3(flrInput.uv0, depth);
    float param_1a = flrInput.volumetricsParams2.y;
    float param_2a = flrInput.volumetricsParams2.z;
    vec2 param_3a = flrInput.nearFar.xy;
    
    parama.z = volumeZToNativeDepth(parama.z, param_1a, param_2a, param_3a);
    
    flrInput.uv0.x -= vk3d_params.stereo.x *0.5;
    
    vec3 param = vec3(flrInput.uv0, depth);
    float param_1 = flrInput.volumetricsParams2.y;
    float param_2 = flrInput.volumetricsParams2.z;
    vec2 param_3 = flrInput.nearFar.xy;
    vec3 _157 = cellCenterSSToUVW(param, param_1, param_2, param_3);
    vec3 scatteringUVW = _157;
    vec4 volSample = textureLod(scatterBufferTex, scatteringUVW, 0.0);
    float weight = (1.0 - volSample.w) * flrInput.volumetricsParams2.w;
    vec3 _181 = mix(flrOutput.hdrColor.xyz, volSample.xyz, vec3(weight));
    flrOutput.hdrColor = vec4(_181.x, _181.y, _181.z, flrOutput.hdrColor.w);
}

void main()
{
    FlrInput flrInput;
    flrInput.uv0 = inUV0;
    flrInput.invProjMatrix = _108.invProjMatrix;
    flrInput.volumetricsParams2 = _108.volumetricsParams2;
    flrInput.nearFar = _108.nearFar;
    FlrInput param = flrInput;
    FlrOutput param_1;
    flrMain(param, param_1);
    FlrOutput flrOutput = param_1;
    outHdrColor = flrOutput.hdrColor;
}








