Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: NV_half_float

  1. #1
    Member Regular Contributor
    Join Date
    Jun 2000
    Location
    Karlsruhe, Germany
    Posts
    486

    NV_half_float

    Anyone knows which C++ datatype should be used for the "half" GL type?

    Regards,
    -Lev

    [This message has been edited by Lev (edited 02-24-2003).]

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2002
    Location
    Austria
    Posts
    280

    Re: NV_half_float

    Since half is a 16-bit IEEE-like floating point type, it'll nicely fit into a float on most machine architectures where float is typically a 32-bit IEEE floating point type.
    XEngine - The Platform- and API-Independent 3D Engine
    with Programmable Pipeline Support: [URL=http://xengine.sourceforge.net
    My]http://xengine.sourceforge.net

  3. #3
    Member Regular Contributor
    Join Date
    Jun 2000
    Location
    Karlsruhe, Germany
    Posts
    486

    Re: NV_half_float

    Well, I can't see how a 16 bit float would fit into 32 bit one. They have different mantissa sizes. On the other hand 32 bit is te smallest float type available on x86. should I just typedef GLhalf as float? then what's the point in introducing new entry points if they are the same as existing on existing architectures?

    regards,
    -Lev

  4. #4
    Super Moderator OpenGL Guru
    Join Date
    Feb 2000
    Location
    Montreal, Canada
    Posts
    4,421

    Re: NV_half_float

    There is no 16 float support on most architextures. YOu have to do a conversion in software I guess.

    Copy the mantissa, then OR the exponent and finally OR the sign bit on it. I'm going to check this out myself.
    ------------------------------
    Sig: http://glhlib.sourceforge.net
    an open source GLU replacement library. Much more modern than GLU.
    float matrix[16], inverse_matrix[16];
    glhLoadIdentityf2(matrix);
    glhTranslatef2(matrix, 0.0, 0.0, 5.0);
    glhRotateAboutXf2(matrix, angleInRadians);
    glhScalef2(matrix, 1.0, 1.0, -1.0);
    glhQuickInvertMatrixf2(matrix, inverse_matrix);
    glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
    glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

  5. #5
    Member Regular Contributor
    Join Date
    Jul 2001
    Location
    earth
    Posts
    263

    Re: NV_half_float

    Yep u should adjust it for your needs just match what is written into the specs.. But should look as follow..

    typedef short VR_FLOAT16;

    __forceinline VR_FLOAT16 floatToFloat16(VR_FLOAT f)
    {
    VR_LONG val;
    VR_FLOAT16 res;

    __asm{
    Fld dword ptr f
    Fstp dword ptr val
    }

    res = (VR_FLOAT16) (val>>MYMANT);
    return res;
    }
    __forceinline VR_FLOAT float16ToFloat(VR_FLOAT16 f16)
    {
    VR_LONG val;
    VR_FLOAT res;

    val = (VR_LONG) f16<<MYMANT;
    __asm{
    Fld dword ptr val
    Fstp dword ptr res
    }

    return res;
    }

    hth

  6. #6
    Junior Member Regular Contributor
    Join Date
    Sep 2000
    Location
    France
    Posts
    193

    Re: NV_half_float

    Hi,

    you can also use the portable code provided with the OpenEXR image lib (http://www.openexr.org/) that uses Half floats.

    In case you use VC, there is no official VC port yet but it's along the way - take a look at the OpenEXR forum.

    Regards,
    Nicolas.

  7. #7
    Senior Member OpenGL Pro
    Join Date
    Sep 2000
    Location
    Santa Clara, CA
    Posts
    1,463

    Re: NV_half_float

    The conversion is not as simple as has been suggested here -- it's fairly messy.

    Isn't the answer "GLhalf"? Or, if you want to be fancy, a C++ struct that contains a GLhalf data element and has a bunch of operator overloads?

    - Matt

  8. #8
    Junior Member Regular Contributor
    Join Date
    Sep 2001
    Location
    Wake Forest, NC, USA
    Posts
    176

    Re: NV_half_float

    There is no native support for half-precision floats in any CPU I'm aware off.

    We typedef GLhalf to "unsigned short" on Win32 platforms. To do anything CPU-wise with half-precision floats, you probably want to first convert them to float using a little bit of bit magic along the lines as those described in the posts above. Basically, we chose "unsigned short" because it takes the same number of bits and is the data type you'd want to use in this conversion.

    Even with the CPU overhead, GLhalf data is useful for cases where (1) the data sets are pre-converted or (2) the data is both generated and consumed by GPUs that have native support. 16-bit components take 1/2 the bandwidth of 32-bit ones, and that bandwidth (and space) savings can be important if it doesn't get eaten up by the CPU overhead.

  9. #9
    Intern Newbie
    Join Date
    Jun 2002
    Posts
    31

    Re: NV_half_float

    We used half float vertex attributes in most of the GeForce FX launch demos, primarily for basis vectors (tangents, binormals, and normals). Note that for performance reasons, any half array should be padded to be a half2 array (or just left as a float array), and any half3 array should be padded to be a half4 array.

    I've attached the basic conversion routines we used. We wrapped these in a class to automate the conversion process (like OpenEXR). The code isn't as efficient as it could be (half->float promotion could be performed with a 64K float lookup table), but it should be relatively self-explanatory. I'm hoping the formatting comes through ok, since I've copied it from the original file.

    Code :
      union nv_half_data {
        unsigned short bits;
        struct {
          unsigned long m : 10;
          unsigned long e : 5;
          unsigned long s : 1;
        } ieee;
      };
     
      union ieee_single {
        float f;
        struct {
          unsigned long m : 23;
          unsigned long e : 8;
          unsigned long s : 1;
        } ieee;
      };
     
      inline static float htof(unsigned short val) {
        nv_half_data h;
        h.bits = val;
        ieee_single sng;
        sng.ieee.s = h.ieee.s;
     
        //  handle special cases
        if ( (h.ieee.e==0) &amp;&amp; (h.ieee.m==0) ) {  // zero
          sng.ieee.m=0;
          sng.ieee.e=0;
        }
        else if ( (h.ieee.e==0) &amp;&amp; (h.ieee.m!=0) ) {  // denorm -- denorm half will fit in non-denorm single
          const float half_denorm = (1.0f/16384.0f); // 2^-14
          float mantissa = ((float)(h.ieee.m)) / 1024.0f;
          float sgn = (h.ieee.s)? -1.0f :1.0f;
          sng.f = sgn*mantissa*half_denorm;
        }
        else if ( (h.ieee.e==31) &amp;&amp; (h.ieee.m==0) ) { // infinity
          sng.ieee.e = 0xff;
          sng.ieee.m = 0;
        }
        else if ( (h.ieee.e==31) &amp;&amp; (h.ieee.m!=0) ) { // NaN
          sng.ieee.e = 0xff;
          sng.ieee.m = 1;
        }
        else {
          sng.ieee.e = h.ieee.e+112;
          sng.ieee.m = (h.ieee.m << 13);
        }
     
        return sng.f;
      }
     
      inline static unsigned short ftoh(float val) {
        ieee_single f;
        f.f = val;
        nv_half_data h;
     
        h.ieee.s = f.ieee.s;
     
        // handle special cases
     
        const float half_denorm = (1.0f/16384.0f);
     
        if ( (f.ieee.e==0) &amp;&amp; (f.ieee.m==0) ) { // zero
          h.ieee.m = 0;
          h.ieee.e = 0;
        }
        else if ( (f.ieee.e==0) &amp;&amp; (f.ieee.m!=0) ) {  // denorm -- denorm float maps to 0 half
          h.ieee.m = 0;
          h.ieee.e = 0;
        }
        else if ( (f.ieee.e==0xff) &amp;&amp; (f.ieee.m==0) ) { // infinity
          h.ieee.m = 0;
          h.ieee.e = 31;
        }
        else if ( (f.ieee.e==0xff) &amp;&amp; (f.ieee.m!=0) ) { // NaN
          h.ieee.m = 1;
          h.ieee.e = 31;
        }
        else { // regular number
          int new_exp = f.ieee.e-127;
          if (new_exp<-24) { // this maps to 0
    	h.ieee.m = 0;
    	h.ieee.e = 0;
          }
     
          if (new_exp<-14) { // this maps to a denorm
    	h.ieee.e = 0;
    	unsigned int exp_val = (unsigned int) (-14 - new_exp);  // 2^-exp_val
    	switch (exp_val) {
            case 0: fprintf(stderr, "ftoh: logical error in denorm creation!\n"); h.ieee.m = 0; break;
    	case 1: h.ieee.m = 512 + (f.ieee.m>>14); break;
    	case 2: h.ieee.m = 256 + (f.ieee.m>>15); break;
    	case 3: h.ieee.m = 128 + (f.ieee.m>>16); break;
    	case 4: h.ieee.m = 64 + (f.ieee.m>>17); break;
    	case 5: h.ieee.m = 32 + (f.ieee.m>>18); break;
    	case 6: h.ieee.m = 16 + (f.ieee.m>>19); break;
    	case 7: h.ieee.m = 8 + (f.ieee.m>>20); break;
    	case 8: h.ieee.m = 4 + (f.ieee.m>>21); break;
    	case 9: h.ieee.m = 2 + (f.ieee.m>>22); break;
    	case 10: h.ieee.m = 1; break;
    	}
          }
          else if (new_exp>15) { // map this value to infinity
    	h.ieee.m = 0;
    	h.ieee.e = 31;
          }
          else {
    	h.ieee.e = new_exp+15;
    	h.ieee.m = (f.ieee.m >> 13);
          }
        }
     
        return h.bits;
      }

  10. #10
    Member Regular Contributor
    Join Date
    May 2002
    Posts
    273

    Re: NV_half_float

    We used half float vertex attributes in most of the GeForce FX launch demos, primarily for basis vectors (tangents, binormals, and normals)
    What is benefit of using GLhalf instead of GLshort in such case?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •