
#ifdef PROPERTY_SAMPLER_TYPE

#else
#error PROPERTY_SAMPLER_TYPE is undefined.
#endif


#if (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_INT)

layout(binding = 1)
  uniform isamplerBuffer cellData;

#elif (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_UINT)

layout(binding = 1)
  uniform usamplerBuffer cellData;

#elif (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_FLOAT || PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_BOOL)

layout(binding = 1)
  uniform samplerBuffer cellData;

#else
#error PROPERTY_SAMPLER_TYPE is defined to unknown value.
#endif


layout(binding = 2)
  uniform sampler1D transferFunctionData;

uniform float rOffset;
uniform float rScale;
uniform float rPropertyNoValueFloat;


/////////////////////////////////////////////////////////////////////////////
// IsInvisible
//

bool
IsInvisible(ivec3 iMin, ivec3 iMax)
{

#if (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_BOOL)
  int
    nCells = 8 * textureSize(cellData);
#else
  int
    nCells = textureSize(cellData);
#endif

  bool
    isNoValueColorVisible = (nIsNoValueColorVisible > 0);

  for (int z_in = iMin.z; z_in < iMax.z; z_in++)
  {
    for (int y_in = iMin.y; y_in < iMax.y; y_in++)
    {
      for (int x_in = iMin.x; x_in < iMax.x ; x_in++)
      {
        bool
          isVoxelNoValue = false;

#if (VOXEL_TYPE == VOXEL_TYPE_FLOAT)

		float
          vRed = GetVoxelFloat(x_in, y_in, z_in, isVoxelNoValue);

        int
          iRed = int (floor(vRed));

#elif (VOXEL_TYPE == VOXEL_TYPE_INTEGER)

        int
          iRed = GetVoxelInteger(x_in, y_in, z_in, isVoxelNoValue);

#else
#error VOXEL_TYPE unknown or undefined.
#endif
        
        if (isVoxelNoValue)
        {
          if (isNoValueColorVisible)
          {
            return false;
          }
          else
          {
            continue;
          }
        }
          
        int
          nCellID = iRed;

        float
          rPropertyValue;
          
        if (nCellID < 0 || nCellID >= nCells)
        {

#if (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_BOOL)
          
          rPropertyValue = 0.f;
#else
          rPropertyValue = rPropertyNoValueFloat;
#endif
        }          
        else
        {

#if (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_BOOL)

          int
            nCellIDBytePosition = nCellID / 8;

          uint
            uCellIDBit =  uint( nCellID % 8);

          float
            rValue = float (texelFetch(cellData, nCellIDBytePosition).x );

          uint
            uValue = uint (rValue * 255.f);

          uint
            uValueBit = (uValue >> uCellIDBit) & 1u;

          rPropertyValue = (uValueBit != 0) ? 1.f : 0.f;

#else
          rPropertyValue = float (texelFetch(cellData, nCellID).x );
#endif

        }

#if (PROPERTY_SAMPLER_TYPE == PROPERTY_SAMPLER_TYPE_BOOL)
        // Not 'no value' support for bool
#else
        if (rPropertyValue == rPropertyNoValueFloat)
        {
          bool
            isVisible = isNoValueColorVisible;

          if (isVisible)
          {
            return false;
          }
          else
          {
            continue;
          }
        }
#endif

        bool
          isVisible;

#ifdef PROPERTY_LOGIC_OPERATION

        isVisible = rPropertyValue PROPERTY_LOGIC_OPERATION propertyThresholdValue;

#else
        float
          rTextureLookupPosition = (rPropertyValue + rOffset) * rScale;
        
        rTextureLookupPosition = clamp (rTextureLookupPosition, 0, 1);
        
        vec4
          vARGB = texture (transferFunctionData, rTextureLookupPosition);

        float
          rAlpha = vARGB.w;
 
        isVisible = (rAlpha != 0);
#endif

        if (isVisible)
        {
          return false;
        }
      }
    }
  }

  return true;             
}

