#ifndef ENABLE_DEPTH
  #define ENABLE_DEPTH 0
#endif

#ifndef ENABLE_HEIGHT
  #define ENABLE_HEIGHT 0
#endif

#ifndef ENABLE_VIEWER_FOR_REFLECTIONS
  #define ENABLE_VIEWER_FOR_REFLECTIONS 0
#endif

#if ENABLE_DEPTH || ENABLE_HEIGHT
  #define ENABLE_PARALLAX 1
#else
  #define ENABLE_PARALLAX 0
#endif

uniform vec3 ScreenFrontDirection;
uniform vec3 ScreenUpDirection;
uniform vec3 ScreenRightDirection;

uniform vec2 FOV;

#if ENABLE_PARALLAX || ENABLE_VIEWER_FOR_REFLECTIONS
  uniform vec3 Viewer;
#endif

uniform vec2 UVScale;

attribute vec4 Position;

varying vec2 UV;

#if !ENABLE_VIEWER_FOR_REFLECTIONS
  varying vec3 FOVNormal;
#endif

#if ENABLE_PARALLAX || ENABLE_VIEWER_FOR_REFLECTIONS
  varying vec3 ViewerDirection; // From surface to viewer, requires normalization
#endif

void main()
{
    vec2 fov_offset = FOV * Position.xy;

#if !ENABLE_VIEWER_FOR_REFLECTIONS
    FOVNormal = ScreenFrontDirection
              + fov_offset.x * ScreenRightDirection
              + fov_offset.y * ScreenUpDirection;
#endif

#if ENABLE_PARALLAX || ENABLE_VIEWER_FOR_REFLECTIONS
    ViewerDirection = vec3(Viewer.xy - fov_offset, Viewer.z);
#endif

    UV = (vec2(Position.x, -Position.y) * UVScale + vec2(1, 1)) * 0.5;
    gl_Position = Position;
}
