#ifndef MATCAP
    #define MATCAP
    
    UNITY_DECLARE_TEX2D_NOSAMPLER(_Matcap);
    POI_TEXTURE_NOSAMPLER(_MatcapMask);
    float _MatcapBorder;
    float4 _MatcapColor;
    float _MatcapIntensity;
    float _MatcapReplace;
    float _MatcapMultiply;
    float _MatcapAdd;
    float _MatcapEnable;
    float _MatcapLightMask;
    float _MatcapEmissionStrength;
    uint _MatcapNormal;
    
    UNITY_DECLARE_TEX2D_NOSAMPLER(_Matcap2);
    POI_TEXTURE_NOSAMPLER(_Matcap2Mask);
    float _Matcap2Border;
    float4 _Matcap2Color;
    float _Matcap2Intensity;
    float _Matcap2Replace;
    float _Matcap2Multiply;
    float _Matcap2Add;
    float _Matcap2Enable;
    float _Matcap2LightMask;
    float _Matcap2EmissionStrength;
    uint _Matcap2Normal;
    
    // globals
    float4 matcap;
    float matcapMask;
    float4 matcap2;
    float matcap2Mask;
    
    
    void calculateMatcap()
    {
        // Both matcaps use the same coordinates
        half3 worldViewUp = normalize(half3(0, 1, 0) - poiCam.viewDir * dot(poiCam.viewDir, half3(0, 1, 0)));
        half3 worldViewRight = normalize(cross(poiCam.viewDir, worldViewUp));
        
        // Matcap 1
        half2 matcapUV = half2(dot(worldViewRight, poiMesh.normals[_MatcapNormal]), dot(worldViewUp, poiMesh.normals[_MatcapNormal])) * _MatcapBorder + 0.5;
        matcap = UNITY_SAMPLE_TEX2D_SAMPLER(_Matcap, _MainTex, matcapUV) * _MatcapColor;
        matcap.rgb *= _MatcapIntensity;
        matcapMask = POI2D_SAMPLER_PAN(_MatcapMask, _MainTex, poiMesh.uv[_MatcapMaskUV], _MatcapMaskPan);
        #ifdef POI_LIGHTING
            if (_MatcapLightMask)
            {
                matcapMask *= lerp(1, poiLight.rampedLightMap, _MatcapLightMask);
            }
        #endif
        
        // Matcap 2
        UNITY_BRANCH
        if (_Matcap2Enable)
        {
            half2 matcapUV2 = half2(dot(worldViewRight, poiMesh.normals[_Matcap2Normal]), dot(worldViewUp, poiMesh.normals[_Matcap2Normal])) * _Matcap2Border + 0.5;
            matcap2 = UNITY_SAMPLE_TEX2D_SAMPLER(_Matcap2, _MainTex, matcapUV2) * _Matcap2Color;
            matcap2 *= _Matcap2Intensity;
            matcap2Mask = POI2D_SAMPLER_PAN(_Matcap2Mask, _MainTex, poiMesh.uv[_Matcap2MaskUV], _Matcap2MaskPan);
            #ifdef POI_LIGHTING
                if(_Matcap2LightMask)
                {
                    matcap2Mask *= lerp(1, poiLight.rampedLightMap, _Matcap2LightMask);
                }
            #endif
        }
    }
    
    void applyMatcap(inout float4 finalColor)
    {
        finalColor.rgb = lerp(finalColor.rgb, matcap.rgb, _MatcapReplace * matcapMask * matcap.a);
        finalColor.rgb *= lerp(1, matcap.rgb, _MatcapMultiply * matcapMask * matcap.a);
        finalColor.rgb += matcap.rgb * _MatcapAdd * matcapMask * matcap.a;
        
        UNITY_BRANCH
        if(_Matcap2Enable)
        {
            finalColor.rgb = lerp(finalColor.rgb, matcap2.rgb, _Matcap2Replace * matcap2Mask * matcap2.a);
            finalColor.rgb *= lerp(1, matcap2.rgb, _Matcap2Multiply * matcap2Mask * matcap2.a);
            finalColor.rgb += matcap2.rgb * _Matcap2Add * matcap2Mask * matcap2.a;
        }
    }
    
    void applyMatcapEmission(inout float3 finalEmission)
    {
        finalEmission += matcap.rgb * _MatcapEmissionStrength * matcapMask * matcap.a;
        
        if(_Matcap2Enable)
        {
            finalEmission += matcap2.rgb * _Matcap2EmissionStrength * matcap2Mask * matcap2.a;
        }
    }
#endif