// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

    #ifndef UNITY_SHADER_UTILITIES_INCLUDED
    #define UNITY_SHADER_UTILITIES_INCLUDED
    
    // This file is always included in all unity shaders.
    
    #include "UnityShaderVariables.cginc"
    
    float3 ODSOffset(float3 worldPos, float ipd)
    {
        //based on google's omni-directional stereo rendering thread
        const float EPSILON = 2.4414e-4;
        float3 worldUp = float3(0.0, 1.0, 0.0);
        float3 camOffset = worldPos.xyz - _WorldSpaceCameraPos.xyz;
        float4 direction = float4(camOffset.xyz, dot(camOffset.xyz, camOffset.xyz));
        direction.w = max(EPSILON, direction.w);
        direction *= rsqrt(direction.w);
    
        float3 tangent = cross(direction.xyz, worldUp.xyz);
        if (dot(tangent, tangent) < EPSILON)
            return float3(0, 0, 0);
        tangent = normalize(tangent);
    
        float directionMinusIPD = max(EPSILON, direction.w*direction.w - ipd*ipd);
        float a = ipd * ipd / direction.w;
        float b = ipd / direction.w * sqrt(directionMinusIPD);
        float3 offset = -a*direction + b*tangent;
        return offset;
    }
    
    inline float4 UnityObjectToClipPosODS(float3 inPos)
    {
        float4 clipPos;
        float3 posWorld = mul(unity_ObjectToWorld, float4(inPos, 1.0)).xyz;
    #if defined(STEREO_CUBEMAP_RENDER_ON)
        float3 offset = ODSOffset(posWorld, unity_HalfStereoSeparation.x);
        clipPos = mul(UNITY_MATRIX_VP, float4(posWorld + offset, 1.0));
    #else
        clipPos = mul(UNITY_MATRIX_VP, float4(posWorld, 1.0));
    #endif
        return clipPos;
    }
    
    // Tranforms position from object to homogenous space
    inline float4 UnityObjectToClipPos(in float3 pos)
    {
    #if defined(STEREO_CUBEMAP_RENDER_ON)
        return UnityObjectToClipPosODS(pos);
    #else
        // More efficient than computing M*VP matrix product
        return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
    #endif
    }
    inline float4 UnityObjectToClipPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
    {
        return UnityObjectToClipPos(pos.xyz);
    }
    
    #endif