#if defined(SPHERE_MAP) || defined(EQUIRECT_MAP)
#define ENVMAP sampler2D
#define TEXENV texture2D
#else
#define ENVMAP samplerCube
#define TEXENV textureCube
#endif

// converts a normalized direction vector
// into a texture coordinate for fetching
// texel from a sphere map
vec2 Optics_SphereCoord(in vec3 dir){
    float dzplus1 = dir.z + 1.0;

    // compute 1/2p
    // NOTE: this simplification only works if dir is normalized.
    float inv_two_p = 1.414 * sqrt(dzplus1);
    //float inv_two_p = sqrt(dir.x * dir.x + dir.y * dir.y + dzplus1 * dzplus1);
    inv_two_p *= 2.0;
    inv_two_p = 1.0 / inv_two_p;

    // compute texcoord
    return (dir.xy * vec2(inv_two_p)) + vec2(0.5);
}

#ifndef PI
    #define PI 3.14159265358979323846264
#endif
//should be vec2(1.0 / (PI * 2.0), 1.0 / PI) but it's precomputed.
const vec2 Optics_Glsllib_Rads = vec2(0.159154943091895, 0.318309886183790);
vec2 Optics_LonLatCoords(in ENVMAP envMap, in vec3 dir){
 float lon = atan(dir.z, dir.x)+ PI;
 float lat = acos(dir.y); 
 return vec2(lon, lat) * Optics_Glsllib_Rads; 
}

vec4 Optics_GetEnvColor(in ENVMAP envMap, in vec3 dir){
    #ifdef SPHERE_MAP
    return texture2D(envMap, Optics_SphereCoord(dir));
    #else
        #ifdef EQUIRECT_MAP
            return texture2D(envMap, Optics_LonLatCoords(envMap,dir));            
        #else
            return textureCube(envMap, dir);
        #endif
    #endif
}
