uniform mat4 gbufferModelView;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferProjection;
uniform mat4 gbufferProjectionInverse;

uniform vec3 cameraPosition;

vec3 screenToView(vec2 texcoord, float depth)
{
    vec3 ndcPos = vec3(texcoord, depth)*2.0-1.0;

    return (ndcPos*vec3(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y, gbufferProjectionInverse[2].z) + gbufferProjectionInverse[3].xyz) / (ndcPos.z * gbufferProjectionInverse[2].w + gbufferProjectionInverse[3].w);
}

vec3 screenToView(vec3 pos)
{
    vec3 ndcPos = pos*2.0-1.0;

    return (ndcPos*vec3(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y, gbufferProjectionInverse[2].z) + gbufferProjectionInverse[3].xyz) / (ndcPos.z * gbufferProjectionInverse[2].w + gbufferProjectionInverse[3].w);
}

vec3 viewToScreen(vec3 viewPos)
{
    return ((viewPos*vec3(gbufferProjection[0].x,gbufferProjection[1].y,gbufferProjection[2].z) + gbufferProjection[3].xyz) / (viewPos.z * gbufferProjection[2].w + gbufferProjection[3].w)) * 0.5 + 0.5;
}

vec3 screenToFeet(vec2 texcoord, float depth)
{
    vec3 viewPos = screenToView(texcoord, depth);

    return mat3(gbufferModelViewInverse) * viewPos + gbufferModelViewInverse[3].xyz;
}


vec3 screenToFeet(vec3 coord)
{
    vec3 viewPos = screenToView(coord);

    return mat3(gbufferModelViewInverse) * viewPos + gbufferModelViewInverse[3].xyz;
}


vec3 viewToFeet(vec3 viewPos)
{
    return mat3(gbufferModelViewInverse) * viewPos + gbufferModelViewInverse[3].xyz;
}

vec3 screenToEye(vec2 texcoord, float depth)
{
    vec3 viewPos = screenToView(texcoord, depth);

    return mat3(gbufferModelViewInverse) * viewPos;
}

vec3 screenToEye(vec3 screenPos)
{
    vec3 viewPos = screenToView(screenPos);

    return mat3(gbufferModelViewInverse) * viewPos;
}


vec3 viewToEye(vec3 viewPos)
{
    return mat3(gbufferModelViewInverse) * viewPos;
}

vec3 feetToWorld(vec3 feetPos)
{
    return feetPos + cameraPosition;
}

vec3 screenToWorld(vec2 texcoord, float depth)
{
    return screenToFeet(texcoord, depth) + cameraPosition;
}

vec3 screenToWorld(vec3 coord)
{
    return screenToFeet(coord) + cameraPosition;
}