Texture.h#
↰ Parent directory (texture
)
The main class that represents an Image (Texture).
Includes#
PVRCore/Errors.h
PVRCore/texture/TextureHeader.h
cmath
Included By#
Namespaces#
Classes#
Enums#
Functions#
Typedefs#
Source Code#
#pragma once
#include "PVRCore/Errors.h"
#include "PVRCore/texture/TextureHeader.h"
#include <cmath>
namespace pvr {
enum class CubeFace : uint32_t
{
PositiveX = 0,
NegativeX,
PositiveY,
NegativeY,
PositiveZ,
NegativeZ
};
enum class ImageType
{
Image1D,
Image2D,
Image3D,
Unallocated,
Unknown,
Count = Image3D + 1
};
enum class ImageViewType
{
ImageView1D,
ImageView2D,
ImageView3D,
ImageView2DCube,
ImageView1DArray,
ImageView2DArray,
ImageView2DCubeArray,
ImageViewUnknown,
};
inline float growFloat(const uint32_t& value, const uint8_t& mantissaBits, const uint8_t& exponentBits, const uint8_t& exponentBias, const bool hasSign /*=true*/)
{
// Union to avoid messy casting.
union
{
float fVal;
uint32_t uiVal;
} intToFloat;
// Float 32 constants.
static const uint8_t f32expBias = 127;
static const uint8_t f32signBits = 1;
static const uint8_t f32expBits = 8;
static const uint8_t f32manBits = 23;
static const uint8_t f32totBits = 32;
// Get the # of sign bits (always 1 or 0)
uint8_t signBits = static_cast<uint8_t>(hasSign ? 1 : 0);
// Work out the total bits
uint8_t totalBits = static_cast<uint8_t>(mantissaBits + exponentBits + signBits);
// Generate the masks for each bit.
uint32_t signMask = static_cast<uint8_t>(((1 << signBits) - 1) << (exponentBits + mantissaBits));
uint32_t expoMask = static_cast<uint8_t>(((1 << exponentBits) - 1) << mantissaBits);
uint32_t mantMask = static_cast<uint8_t>(((1 << mantissaBits) - 1));
// Get original exponent.
uint32_t originalExponent = ((value & expoMask) >> (mantissaBits));
bool originalIsNaN = (originalExponent == (uint32_t)((1 << exponentBits) - 1));
// Bit shift and edit until
uint32_t uSign = (value & signMask) << ((f32totBits - f32signBits) - (totalBits - signBits));
uint32_t uExponent = (originalExponent - exponentBias + f32expBias) << f32manBits;
uint32_t uMantissa = (value & mantMask) << (f32manBits - mantissaBits);
// Make sure NaN/Infinity is preserved if original was NaN/Infinity.
if (originalIsNaN) { uExponent = ((1 << f32expBits) - 1) << f32manBits; }
// Assign the expanded values to the union
intToFloat.uiVal = uSign | uExponent | uMantissa;
// Return the expanded float
return intToFloat.fVal;
}
inline ImageType imageViewTypeToImageBaseType(ImageViewType viewtype)
{
switch (viewtype)
{
case ImageViewType::ImageView1D:
case ImageViewType::ImageView1DArray: return ImageType::Image1D;
case ImageViewType::ImageView2D:
case ImageViewType::ImageView2DCube:
case ImageViewType::ImageView2DArray:
case ImageViewType::ImageView2DCubeArray: return ImageType::Image2D;
case ImageViewType::ImageView3D: return ImageType::Image3D;
default: return ImageType::Unallocated;
}
}
inline void convertXYZToCubeUV(float x, float y, float z, CubeFace& face, float& u, float& v)
{
float absX = fabs(x);
float absY = fabs(y);
float absZ = fabs(z);
if (absX == 0.f && absY == 0.f && absZ == 0.f) { throw new std::runtime_error("Cannot convert the zero vector to a cubemap sample"); }
int isXPositive = x > 0 ? 1 : 0;
int isYPositive = y > 0 ? 1 : 0;
int isZPositive = z > 0 ? 1 : 0;
float maxAxis = 0.0f;
float uc = 0.0f;
float vc = 0.0f;
// POSITIVE X
if (isXPositive && absX >= absY && absX >= absZ)
{
// u (0 to 1) goes from +z to -z
// v (0 to 1) goes from -y to +y
maxAxis = absX;
uc = -z;
vc = -y;
face = CubeFace::PositiveX;
}
// NEGATIVE X
if (!isXPositive && absX >= absY && absX >= absZ)
{
// u (0 to 1) goes from -z to +z
// v (0 to 1) goes from -y to +y
maxAxis = absX;
uc = z;
vc = -y;
face = CubeFace::NegativeX;
}
// POSITIVE Y
if (isYPositive && absY >= absX && absY >= absZ)
{
// u (0 to 1) goes from -x to +x
// v (0 to 1) goes from +z to -z
maxAxis = absY;
uc = x;
vc = z;
face = CubeFace::PositiveY;
}
// NEGATIVE Y
if (!isYPositive && absY >= absX && absY >= absZ)
{
// u (0 to 1) goes from -x to +x
// v (0 to 1) goes from -z to +z
maxAxis = absY;
uc = x;
vc = +z;
face = CubeFace::NegativeY;
}
// POSITIVE Z
if (isZPositive && absZ >= absX && absZ >= absY)
{
// u (0 to 1) goes from -x to +x
// v (0 to 1) goes from -y to +y
maxAxis = absZ;
uc = x;
vc = -y;
face = CubeFace::PositiveZ;
}
// NEGATIVE Z
if (!isZPositive && absZ >= absX && absZ >= absY)
{
// u (0 to 1) goes from +x to -x
// v (0 to 1) goes from -y to +y
maxAxis = absZ;
uc = -x;
vc = -y;
face = CubeFace::NegativeZ;
}
// Convert range from -1 to 1 to 0 to 1
u = 0.5f * (uc / maxAxis + 1.0f);
v = 0.5f * (vc / maxAxis + 1.0f);
}
struct ImageLayersSize
{
uint16_t numArrayLevels;
uint16_t numMipLevels;
uint16_t numPlaneLevels;
ImageLayersSize(uint16_t numArrayLevels = 1, uint8_t numMipLevels = 1, uint8_t numPlaneLevels = 1)
: numArrayLevels(numArrayLevels), numMipLevels(numMipLevels), numPlaneLevels(numPlaneLevels)
{}
};
struct ImageDataFormat
{
PixelFormat format;
VariableType dataType;
ColorSpace colorSpace;
explicit ImageDataFormat(const PixelFormat& format = PixelFormat::RGBA_8888(), VariableType dataType = VariableType::UnsignedByteNorm, ColorSpace colorSpace = ColorSpace::lRGB)
: format(format), dataType(dataType), colorSpace(colorSpace)
{}
bool operator==(const ImageDataFormat& rhs) const { return (format == rhs.format && dataType == rhs.dataType && colorSpace == rhs.colorSpace); }
bool operator!=(const ImageDataFormat& rhs) const { return !(*this == rhs); }
};
struct ImageStorageFormat : public ImageDataFormat
{
uint8_t numMipMapLevels;
uint8_t numSamples;
uint8_t numPlanes;
ImageStorageFormat(const PixelFormat& format = PixelFormat::RGBA_8888(), uint8_t numMipMapLevels = 1, ColorSpace colorSpace = ColorSpace::lRGB,
VariableType dataType = VariableType::UnsignedByteNorm, uint8_t numSamples = 1, uint8_t numPlanes = 1)
: ImageDataFormat(format, dataType, colorSpace), numMipMapLevels(numMipMapLevels), numSamples(numSamples), numPlanes(numPlanes)
{}
ImageStorageFormat(const ImageDataFormat& dataFmt, uint8_t numMipMapLevels = 1, uint8_t numSamples = 1, uint8_t numPlanes = 1)
: ImageDataFormat(dataFmt), numMipMapLevels(numMipMapLevels), numSamples(numSamples), numPlanes(numPlanes)
{}
};
template<typename T>
struct GenericExtent2D
{
T width;
T height;
GenericExtent2D(T width = 0, T height = 0) : width(width), height(height) {}
};
template<typename Txy, typename Tz>
struct GenericExtent3D : public GenericExtent2D<Txy>
{
Tz depth;
GenericExtent3D() {}
GenericExtent3D(Txy width, Txy height, Tz depth = 1) : GenericExtent2D<Txy>(width, height), depth(depth) {}
GenericExtent3D(const GenericExtent2D<Txy>& extent2D, Tz depth = 1) : GenericExtent2D<Txy>(extent2D), depth(depth) {}
};
template<typename T>
struct GenericOffset2D
{
T x;
T y;
GenericOffset2D(T offsetX = 0, T offsetY = 0) : x(offsetX), y(offsetY) {}
GenericOffset2D operator+(const GenericExtent2D<typename std::make_unsigned<T>::type>& rhs) const { return GenericOffset2D(*this) += rhs; }
GenericOffset2D& operator+=(const GenericExtent2D<typename std::make_unsigned<T>::type>& rhs)
{
x += rhs.width;
y += rhs.height;
return *this;
}
};
template<typename Txy, typename Tz>
struct GenericOffset3D : public GenericOffset2D<Txy>
{
Tz z;
GenericOffset3D(Txy offsetX = 0, Txy offsetY = 0, Tz offsetZ = 0) : GenericOffset2D<Txy>(offsetX, offsetY), z(offsetZ) {}
GenericOffset3D operator+(const GenericExtent3D<typename std::make_unsigned<Txy>::type, typename std::make_unsigned<Tz>::type>& rhs) const
{
return GenericOffset3D(*this) += rhs;
}
GenericOffset3D& operator+=(const GenericExtent3D<typename std::make_unsigned<Txy>::type, typename std::make_unsigned<Tz>::type>& rhs)
{
GenericOffset2D<Txy>::x += rhs.width;
GenericOffset2D<Txy>::y += rhs.height;
z += rhs.height;
return *this;
}
GenericOffset3D(const GenericOffset2D<Txy>& offsetXY, Tz offsetZ = 0) : GenericOffset2D<Txy>(offsetXY), z(offsetZ) {}
};
typedef GenericOffset2D<int32_t> Offset2D;
typedef GenericOffset3D<int32_t, int32_t> Offset3D;
typedef GenericExtent2D<uint32_t> Extent2D;
typedef GenericExtent3D<uint32_t, uint32_t> Extent3D;
enum class ImageAspectFlags : uint32_t
{
Color = 0x1,
Depth = 0x2,
Stencil = 0x4,
Metadata = 0x8,
DepthAndStencil = Depth | Stencil,
};
inline ImageAspectFlags operator|(ImageAspectFlags lhs, ImageAspectFlags rhs)
{
return static_cast<ImageAspectFlags>(static_cast<std::underlying_type<ImageAspectFlags>::type >(lhs) | static_cast<std::underlying_type<ImageAspectFlags>::type >(rhs));
}
inline void operator|=(ImageAspectFlags& lhs, ImageAspectFlags rhs)
{
lhs = static_cast<ImageAspectFlags>(static_cast<std::underlying_type<ImageAspectFlags>::type >(lhs) | static_cast<std::underlying_type<ImageAspectFlags>::type >(rhs));
}
inline ImageAspectFlags operator&(ImageAspectFlags lhs, ImageAspectFlags rhs)
{
return static_cast<ImageAspectFlags>(static_cast<std::underlying_type<ImageAspectFlags>::type >(lhs) & static_cast<std::underlying_type<ImageAspectFlags>::type >(rhs));
}
inline void operator&=(ImageAspectFlags& lhs, ImageAspectFlags rhs)
{
lhs = static_cast<ImageAspectFlags>(static_cast<std::underlying_type<ImageAspectFlags>::type >(lhs) & static_cast<std::underlying_type<ImageAspectFlags>::type >(rhs));
}
struct ImageSubresource
{
ImageAspectFlags aspect;
uint16_t arrayLayerOffset;
uint16_t mipLevelOffset;
uint16_t planeOffset;
ImageSubresource(ImageAspectFlags aspectFlags = ImageAspectFlags::Color, uint16_t mipLevelOffset = 0, uint16_t arrayLayerOffset = 0, uint16_t planeOffset = 0)
: aspect(aspectFlags), arrayLayerOffset(arrayLayerOffset), mipLevelOffset(mipLevelOffset), planeOffset(planeOffset)
{}
};
struct ImageSubresourceRange : public ImageLayersSize, public ImageSubresource
{
ImageSubresourceRange() {}
ImageSubresourceRange(const ImageLayersSize& layersSize, const ImageSubresource& baseLayers) : ImageLayersSize(layersSize), ImageSubresource(baseLayers) {}
};
struct ImageSubresourceLayers : public ImageSubresource
{
uint16_t numArrayLayers;
ImageSubresourceLayers() : numArrayLayers(1) {}
ImageSubresourceLayers(ImageSubresource baseLayers, uint16_t numArrayLayers) : ImageSubresource(baseLayers), numArrayLayers(numArrayLayers) {}
};
struct ImageRange : public Extent3D, public Offset3D
{
ImageRange() {}
ImageRange(const Extent3D& extents, const Offset3D& offset) : Extent3D(extents), Offset3D(offset) {}
};
struct ImageResolveRange
{
Offset3D srcOffset;
Offset3D dstOffset;
Extent3D extent;
ImageSubresourceLayers srcSubResource;
ImageSubresourceLayers dstSubResource;
ImageResolveRange() {}
ImageResolveRange(const Offset3D& srcOffset0, const Offset3D& dstOffset0, const Extent3D& extent0, const ImageSubresourceLayers& srcSubResource = ImageSubresourceLayers(),
const ImageSubresourceLayers& dstSubResource = ImageSubresourceLayers())
{
srcOffset = srcOffset0;
dstOffset = dstOffset0;
extent = extent0;
this->srcSubResource = srcSubResource;
this->dstSubResource = dstSubResource;
}
};
struct CompressedImageDataFormat
{
CompressedPixelFormat format;
};
struct ImageStorageFormatCompressed : public CompressedImageDataFormat
{
int8_t numMipMapLevels;
};
enum class TextureFileFormat
{
UNKNOWN = 0,
KTX,
DDX,
PVR,
TGA,
BMP,
DDS,
JPEG
};
class Texture : public TextureHeader
{
public:
Texture();
Texture(const TextureHeader& sHeader, const unsigned char* pData = NULL);
void initializeWithHeader(const TextureHeader& sHeader);
const unsigned char* getDataPointer(uint32_t mipMapLevel = 0, uint32_t arrayMember = 0, uint32_t face = 0, uint32_t plane = 0) const;
unsigned char* getDataPointer(uint32_t mipMapLevel = 0, uint32_t arrayMember = 0, uint32_t face = 0, uint32_t plane = 0);
unsigned char* getPixelPointer(uint32_t x, uint32_t y, uint32_t z = 0, uint32_t mipMapLevel = 0, uint32_t arrayMember = 0, uint32_t face = 0, uint32_t plane = 0)
{
uint8_t pelsize = getPixelSize();
size_t idx = (size_t)((size_t)x + (size_t)y * width + (size_t)z * width * height) * pelsize;
return getDataPointer(mipMapLevel, arrayMember, face, plane) + idx;
}
unsigned char* getPixelPointerByUvw(float u, float v, float w = 0, uint32_t mipMapLevel = 0, uint32_t arrayMember = 0, CubeFace face = (CubeFace)0, uint32_t plane = 0)
{
uint32_t x = (u <= 0.f) ? 0 : (u >= 1.f) ? getWidth(mipMapLevel) - 1 : uint32_t(u * getWidth(mipMapLevel));
uint32_t y = (v <= 0.f) ? 0 : (v >= 1.f) ? getHeight(mipMapLevel) - 1 : uint32_t(v * getHeight(mipMapLevel));
uint32_t z = (w <= 0.f) ? 0 : (w >= 1.f) ? getDepth(mipMapLevel) - 1 : uint32_t(w * getDepth(mipMapLevel));
return getPixelPointer(x, y, z, mipMapLevel, arrayMember, (uint32_t)face, plane);
}
unsigned char* getCubemapPixel(float x, float y, float z, uint32_t mipMapLevel = 0, uint32_t arrayMember = 0, uint32_t plane = 0)
{
CubeFace face;
float u, v;
convertXYZToCubeUV(x, y, z, face, u, v);
return getPixelPointerByUvw(u, v, 0, mipMapLevel, arrayMember, face, plane);
}
uint8_t getPixelSize() const;
ImageType getDimension() const { return getDepth() > 1 ? ImageType::Image3D : getHeight() > 1 ? ImageType::Image2D : ImageType::Image1D; }
ImageLayersSize getLayersSize() const { return ImageLayersSize(static_cast<uint16_t>(getNumArrayMembers() * getNumFaces()), static_cast<uint8_t>(getNumMipMapLevels())); }
Extent3D getDimensions(uint32_t miplevel = 0) const
{
return Extent3D(static_cast<uint16_t>(getWidth(miplevel)), static_cast<uint16_t>(getHeight(miplevel)), static_cast<uint16_t>(getDepth(miplevel)));
}
void addPaddingMetaData(uint32_t alignment);
private:
std::vector<unsigned char> _pTextureData; // Pointer to texture data.
};
TextureFileFormat getTextureFormatFromFilename(const char* assetname);
} // namespace pvr