

#define diagonal3_dh(m) vec3((m)[0].x, (m)[1].y, m[2].z)
#define projMAD_dh(m, v) (diagonal3_dh(m) * (v) + (m)[3].xyz)

vec3 toClipSpace3DH(vec3 viewSpacePosition)
{
    return projMAD_dh(dhProjection, viewSpacePosition) / -viewSpacePosition.z * 0.5 + 0.5;
}

vec3 toScreenSpaceDH(vec3 position)
{
    position = position * 2.0 - 1.0;
    position.xy = vec2(dhProjectionInverse[0].x, dhProjectionInverse[1].y) * position.xy + dhProjectionInverse[3].xy;
    return vec3(position.xy, dhProjectionInverse[3].z) /
           (dhProjectionInverse[2].w * position.z + dhProjectionInverse[3].w);
}

vec3 toClipSpace3_org(vec3 viewSpacePosition)
{
    return projMAD_dh(gbufferProjection, viewSpacePosition) / -viewSpacePosition.z * 0.5 + 0.5;
}

vec3 toScreenSpace_org(vec3 p)
{
    vec4 iProjDiag = vec4(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y, gbufferProjectionInverse[2].zw);
    vec3 p3 = p * 2. - 1.;
    vec4 fragposition = iProjDiag * p3.xyzz + gbufferProjectionInverse[3];
    return fragposition.xyz / fragposition.w;
}

vec3 toScreenSpace_alt(vec2 texcoord, float depthA, float depthB)
{
#ifdef DISTANT_HORIZONS

    if (depthA >= 1.0)
    {
        return toScreenSpaceDH(vec3(texcoord, depthB));
    }
    else
    {

        return toScreenSpace_org(vec3(texcoord, depthA));
    }
#else
    return toScreenSpace_org(vec3(texcoord, depthA));

#endif
}
vec3 toClipSpace3_alt(vec3 viewSpacePosition)
{
    return projMAD_dh(gbufferProjection, viewSpacePosition) / -viewSpacePosition.z * 0.5 + 0.5;
}
