2
0
Эх сурвалжийг харах

Added code to encode floats into 10 and 11 bit floating point formats

BearishSun 8 жил өмнө
parent
commit
7cb3dc80ea

+ 10 - 0
Source/BansheeCore/Source/BsPixelUtil.cpp

@@ -1261,6 +1261,16 @@ namespace bs
 			case PF_R8:
 			case PF_R8:
 				((UINT8*)dest)[0] = (UINT8)Bitwise::floatToFixed(r, 8);
 				((UINT8*)dest)[0] = (UINT8)Bitwise::floatToFixed(r, 8);
 				break;
 				break;
+			case PF_FLOAT_R11G11B10:
+				{
+					UINT32 value;
+					value = Bitwise::floatToFloat11(r);
+					value |= Bitwise::floatToFloat11(g) << 11;
+					value |= Bitwise::floatToFloat10(b) << 22;
+
+					((UINT32*)dest)[0] = value;
+				}
+				break;
             default:
             default:
                 LOGERR("Pack to " + getFormatName(format) + " not implemented");
                 LOGERR("Pack to " + getFormatName(format) + " not implemented");
                 break;
                 break;

+ 98 - 0
Source/BansheeUtility/Include/BsBitwise.h

@@ -10,6 +10,24 @@ namespace bs
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Floating point number broken down into components for easier access. */
+	union Float754 
+	{
+		UINT32 raw;
+		float value;
+		struct {
+#if BS_ENDIAN == BS_ENDIAN_BIG
+			UINT32 negative : 1;
+			UINT32 exponent : 8;
+			UINT32 mantissa : 23;
+#else
+			UINT32 mantissa : 23;
+			UINT32 exponent : 8;
+			UINT32 negative : 1;
+#endif
+		} field;
+	};
+
     /** Class for manipulating bit patterns. */
     /** Class for manipulating bit patterns. */
     class Bitwise 
     class Bitwise 
 	{
 	{
@@ -284,6 +302,86 @@ namespace bs
         
         
             return (s << 31) | (e << 23) | m;
             return (s << 31) | (e << 23) | m;
         }
         }
+
+		/** Converts a 32-bit float to a 10-bit float according to OpenGL packed_float extension. */
+		static UINT32 floatToFloat10(float v)
+		{
+			Float754 f;
+			f.value = v;
+
+			if (f.field.exponent == 0xFF)
+			{
+				// NAN or INF
+				if (f.field.mantissa > 0)
+					return 0x3E0 | (((f.raw >> 18) | (f.raw >> 13) | (f.raw >> 3) | f.raw) & 0x1F);
+				else if (f.field.negative)
+					return 0; // Negative infinity clamped to 0
+				else
+					return 0x3E0; // Positive infinity
+
+			}
+			else if (f.field.negative)
+				return 0; // Negative clamped to 0, no negatives allowed
+			else if (f.raw > 0x477C0000)
+				return 0x3DF; // Too large, clamp to max value
+			else
+			{
+				UINT32 val;
+				if (f.raw < 0x38800000U)
+				{
+					// Too small to be represented as a normalized float, convert to denormalized value
+					UINT32 shift = 113 - f.field.exponent;
+					val = (0x800000U | f.field.mantissa) >> shift;
+				}
+				else
+				{
+					// Rebias exponent
+					val = f.raw + 0xC8000000;
+				}
+
+				return  ((val + 0x1FFFFU + ((val >> 18) & 1)) >> 18) & 0x3FF;
+			}
+		}
+
+		/** Converts a 32-bit float to a 11-bit float according to OpenGL packed_float extension. */
+		static UINT32 floatToFloat11(float v)
+		{
+			Float754 f;
+			f.value = v;
+
+			if (f.field.exponent == 0xFF)
+			{
+				// NAN or INF
+				if (f.field.mantissa > 0)
+					return 0x7C0 | (((f.raw >> 17) | (f.raw >> 11) | (f.raw >> 6) | f.raw) & 0x3F);
+				else if (f.field.negative)
+					return 0; // Negative infinity clamped to 0
+				else
+					return 0x7C0; // Positive infinity
+
+			}
+			else if (f.field.negative)
+				return 0; // Negative clamped to 0, no negatives allowed
+			else if (f.raw > 0x477E0000)
+				return 0x7BF; // Too large, clamp to max value
+			else
+			{
+				UINT32 val;
+				if(f.raw < 0x38800000U)
+				{
+					// Too small to be represented as a normalized float, convert to denormalized value
+					UINT32 shift = 113 - f.field.exponent;
+					val = (0x800000U | f.field.mantissa) >> shift;
+				}
+				else
+				{
+					// Rebias exponent
+					val = f.raw + 0xC8000000;
+				}
+
+				return  ((val + 0xFFFFU + ((val >> 17) & 1)) >> 17) & 0x7FF;
+			}
+		}
     };
     };
 
 
 	/** @} */
 	/** @} */