打包DXT纹理压缩的16位颜色值

时间:2015-02-11 07:20:47

标签: c# bit-manipulation

我正在研究一个主要在c#中的3-D图形库(在互操作层下面有一些嵌入式本机c ++库),我试图尽可能地保持互操作层的尽可能高性能。 / p>

我在c#interop层中创建了一些结构,用于处理DXT纹理压缩(目前是DXT1,DXT3和DXT5),它们被传递给本机库,用于编组到GPU。

为此,需要一些“辅助”结构来帮助正确格式化数据,因为DXT使用的16位RGB颜色输入值是R的格式:5 G:6 B :5

我的问题是关于我为保存这些16位RGB值而创建的结构。 struct(DXTColor16)将打包值保存为无符号16位整数(ushort),并将各个颜色分量公开为字节值属性,这些属性使用位操作来在内部获取和设置打包值的值。

从下面这个结构的例子中,任何人都可以建议一种更有效的方法来处理结构中值的打包/解包吗?

/// <summary>
/// Helper struct for a 16-bit color of a DXT1, DXT3 or DXT5 block.
/// </summary>
/// <remarks>
/// <para>Dependent on little endian byte ordering.</para>
/// <para>For cross-platform compatability, this will need to be redesigned to account for endianness when packing/unpacking values.</para>
/// </remarks>
public struct DXTColor16
{
    private const byte MAX_5_BIT = 0x1F;    // 00011111
    private const byte MAX_6_BIT = 0x3F;    // 00111111

    private const ushort B_MASK = 0x1F;    // 0000000000011111
    private const ushort G_MASK = 0x7E0;   // 0000011111100000
    private const ushort R_MASK = 0xF800;  // 1111100000000000

    /// <summary>
    /// Red color component.
    /// </summary>
    /// <remarks>
    /// <para>Red color component is 5-bit.</para>
    /// </remarks>
    public byte R
    {
        get
        {
            return (byte)((Value & R_MASK) >> 11);  // extract R value and shift into byte value.
        }
        set
        {
            var r = (value & MAX_5_BIT) >> 11;  // trunc input to 5 valid bits and shift into place for masking when combining during set Value.
            var val = Value & (~R_MASK);        // clear existing R value with inverted R_MASK.
            Value = (ushort)(r | val);          // set Value.
        }
    }

    /// <summary>
    /// Green color component.
    /// </summary>
    /// <remarks>
    /// <para>Green color component is 6-bit.</para>
    /// </remarks>
    public byte G
    {
        get
        {
            return (byte)((Value & G_MASK) >> 5);   // extract G with G_MASK and shift into byte value.
        }
        set
        {
            var g = (value & MAX_6_BIT) >> 5;   // trunc input to 6 valid bits and shift into place for masking when combining during set Value.
            var val = Value & (~G_MASK);        // clear existing G value with inverted G_MASK.
            Value = (ushort)(g | val);          // set Value.
        }
    }

    /// <summary>
    /// Blue color component.
    /// </summary>
    /// <remarks>
    /// <para>Blue color component is 5-bit.</para>
    /// </remarks>
    public byte B
    {
        get
        {
            return (byte)(Value & B_MASK);  // extract B with B_MASK and return as byte value.
        }
        set
        {
            var b = value & MAX_5_BIT;      // trunc input to 5 valid bits. No shift needed, already in place for masking.
            var val = Value & (~B_MASK);    // clear existing B value with inverted B_MASK.
            Value = (ushort)(b | val);      // set Value.
        }
    }

    /// <summary>
    /// Packed 16-bit unsigned integer containing the blue, green and red color components.
    /// </summary>
    /// <remarks>
    /// <para>Color components are in R|G|B order.</para>
    /// </remarks>
    public ushort Value;
}

我能以更有效的方式处理逐位操作吗?非常感谢任何反馈。

0 个答案:

没有答案