I\'m looking for/writing a C++ implementation of a 16-bit floating point number to use with OpenGL vertex buffers (texture coordinates, normals, etc). Here are my requireme
Edit: The most obvious error appears in your VertexHalf structure. You have an element of padding. Yet when you specify your glVertexAttribPointer you specify a 0 in the stride which indicates it is tightly packed. So you can either change VertexHalf to remove the padding or change your glVertexAttribPointer to have a stride of 8 bytes.
I use the following class with DirectX for float16 support and it works perfectly.
Float16.h:
#ifndef THE__FLOAT_16_H_
#define THE__FLOAT_16_H_
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
extern short FloatToFloat16( float value );
extern float Float16ToFloat( short value );
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
class Float16
{
protected:
short mValue;
public:
Float16();
Float16( float value );
Float16( const Float16& value );
operator float();
operator float() const;
friend Float16 operator + ( const Float16& val1, const Float16& val2 );
friend Float16 operator - ( const Float16& val1, const Float16& val2 );
friend Float16 operator * ( const Float16& val1, const Float16& val2 );
friend Float16 operator / ( const Float16& val1, const Float16& val2 );
Float16& operator =( const Float16& val );
Float16& operator +=( const Float16& val );
Float16& operator -=( const Float16& val );
Float16& operator *=( const Float16& val );
Float16& operator /=( const Float16& val );
Float16& operator -();
};
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16::Float16()
{
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16::Float16( float value )
{
mValue = FloatToFloat16( value );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16::Float16( const Float16 &value )
{
mValue = value.mValue;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16::operator float()
{
return Float16ToFloat( mValue );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16::operator float() const
{
return Float16ToFloat( mValue );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator =( const Float16& val )
{
mValue = val.mValue;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator +=( const Float16& val )
{
*this = *this + val;
return *this;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator -=( const Float16& val )
{
*this = *this - val;
return *this;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator *=( const Float16& val )
{
*this = *this * val;
return *this;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator /=( const Float16& val )
{
*this = *this / val;
return *this;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16& Float16::operator -()
{
*this = Float16( -(float)*this );
return *this;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
/*+----+ Friends +----+*/
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16 operator + ( const Float16& val1, const Float16& val2 )
{
return Float16( (float)val1 + (float)val2 );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16 operator - ( const Float16& val1, const Float16& val2 )
{
return Float16( (float)val1 - (float)val2 );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16 operator * ( const Float16& val1, const Float16& val2 )
{
return Float16( (float)val1 * (float)val2 );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
inline Float16 operator / ( const Float16& val1, const Float16& val2 )
{
return Float16( (float)val1 / (float)val2 );
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
#endif
Float16.cpp:
#include "Types/Float16.h"
//#include <d3dx9.h>
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
short FloatToFloat16( float value )
{
short fltInt16;
int fltInt32;
memcpy( &fltInt32, &value, sizeof( float ) );
fltInt16 = ((fltInt32 & 0x7fffffff) >> 13) - (0x38000000 >> 13);
fltInt16 |= ((fltInt32 & 0x80000000) >> 16);
return fltInt16;
}
/+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+/
float Float16ToFloat( short fltInt16 )
{
int fltInt32 = ((fltInt16 & 0x8000) << 16);
fltInt32 |= ((fltInt16 & 0x7fff) << 13) + 0x38000000;
float fRet;
memcpy( &fRet, &fltInt32, sizeof( float ) );
return fRet;
}
/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
The GLM library supports half-float types. The prefix used is 'h' so where glm::vec3
is a 3 element vector of floating points values, glm::hvec3
is a 3 element vector of half-floats.
I only know of OpenEXR library that has an implementation for half
. The good thing is that the implementation of half has the functions you are looking for, and it even works with NVIDIA CG toolkit.
The bad thing is that i don't know if the half
type is compatible out of the box with the opengl version you use (in theory it should be), so you should do some testing before you decide to use it.