public static Bc7Block EncodeBlock(RawBlock4X4Rgba32 block, int startingVariation, int bestPartition) { Bc7Block output = new Bc7Block(); const Bc7BlockType type = Bc7BlockType.Type2; ColorRgba32[] endpoints = new ColorRgba32[6]; ReadOnlySpan <int> partitionTable = Bc7Block.Subsets3PartitionTable[bestPartition]; byte[] indices = new byte[16]; int[] anchorIndices = new int[] { 0, Bc7Block.Subsets3AnchorIndices2[bestPartition], Bc7Block.Subsets3AnchorIndices3[bestPartition] }; for (int subset = 0; subset < 3; subset++) { Bc7EncodingHelpers.GetInitialUnscaledEndpointsForSubset(block, out var ep0, out var ep1, partitionTable, subset); ColorRgba32 scaledEp0 = Bc7EncodingHelpers.ScaleDownEndpoint(ep0, type, true, out byte _); ColorRgba32 scaledEp1 = Bc7EncodingHelpers.ScaleDownEndpoint(ep1, type, true, out byte _); byte pBit = 0; Bc7EncodingHelpers.OptimizeSubsetEndpointsWithPBit(type, block, ref scaledEp0, ref scaledEp1, ref pBit, ref pBit, startingVariation, partitionTable, subset, false, false); ep0 = Bc7EncodingHelpers.ExpandEndpoint(type, scaledEp0, 0); ep1 = Bc7EncodingHelpers.ExpandEndpoint(type, scaledEp1, 0); Bc7EncodingHelpers.FillSubsetIndices(type, block, ep0, ep1, partitionTable, subset, indices); if ((indices[anchorIndices[subset]] & 0b10) > 0) //If anchor index most significant bit is 1, switch endpoints { var c = scaledEp0; scaledEp0 = scaledEp1; scaledEp1 = c; //redo indices ep0 = Bc7EncodingHelpers.ExpandEndpoint(type, scaledEp0, 0); ep1 = Bc7EncodingHelpers.ExpandEndpoint(type, scaledEp1, 0); Bc7EncodingHelpers.FillSubsetIndices(type, block, ep0, ep1, partitionTable, subset, indices); } endpoints[subset * 2] = scaledEp0; endpoints[subset * 2 + 1] = scaledEp1; } output.PackType2(bestPartition, new[] { new byte[] { endpoints[0].r, endpoints[0].g, endpoints[0].b }, new byte[] { endpoints[1].r, endpoints[1].g, endpoints[1].b }, new byte[] { endpoints[2].r, endpoints[2].g, endpoints[2].b }, new byte[] { endpoints[3].r, endpoints[3].g, endpoints[3].b }, new byte[] { endpoints[4].r, endpoints[4].g, endpoints[4].b }, new byte[] { endpoints[5].r, endpoints[5].g, endpoints[5].b } }, indices); return(output); }
public static Bc7Block EncodeBlock(RawBlock4X4Rgba32 block, int startingVariation) { bool hasAlpha = block.HasTransparentPixels(); Bc7Block output = new Bc7Block(); Bc7EncodingHelpers.GetInitialUnscaledEndpoints(block, out var ep0, out var ep1); ColorRgba32 scaledEp0 = Bc7EncodingHelpers.ScaleDownEndpoint(ep0, Bc7BlockType.Type6, false, out byte pBit0); ColorRgba32 scaledEp1 = Bc7EncodingHelpers.ScaleDownEndpoint(ep1, Bc7BlockType.Type6, false, out byte pBit1); ReadOnlySpan<int> partitionTable = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const int subset = 0; //Force 255 alpha if fully opaque if (!hasAlpha) { pBit0 = 1; pBit1 = 1; } Bc7EncodingHelpers.OptimizeSubsetEndpointsWithPBit(Bc7BlockType.Type6, block, ref scaledEp0, ref scaledEp1, ref pBit0, ref pBit1, startingVariation, partitionTable, subset, hasAlpha, hasAlpha); ep0 = Bc7EncodingHelpers.ExpandEndpoint(Bc7BlockType.Type6, scaledEp0, pBit0); ep1 = Bc7EncodingHelpers.ExpandEndpoint(Bc7BlockType.Type6, scaledEp1, pBit1); byte[] indices = new byte[16]; Bc7EncodingHelpers.FillSubsetIndices(Bc7BlockType.Type6, block, ep0, ep1, partitionTable, subset, indices); if ((indices[0] & 0b1000) > 0) //If anchor index most significant bit is 1, switch endpoints { var c = scaledEp0; var p = pBit0; scaledEp0 = scaledEp1; pBit0 = pBit1; scaledEp1 = c; pBit1 = p; //redo indices ep0 = Bc7EncodingHelpers.ExpandEndpoint(Bc7BlockType.Type6, scaledEp0, pBit0); ep1 = Bc7EncodingHelpers.ExpandEndpoint(Bc7BlockType.Type6, scaledEp1, pBit1); Bc7EncodingHelpers.FillSubsetIndices(Bc7BlockType.Type6, block, ep0, ep1, partitionTable, subset, indices); } output.PackType6(new[]{ new byte[]{scaledEp0.r, scaledEp0.g, scaledEp0.b, scaledEp0.a}, new byte[]{scaledEp1.r, scaledEp1.g, scaledEp1.b, scaledEp1.a}, }, new[] { pBit0, pBit1 }, indices); return output; }