Fix definition and use of non-indexed sprite color channels.

Our SpriteFrameType names refer to the byte channel order rather than
the bit order, meaning that SpriteFrameType.BGRA corresponds to the
standard Color.ToArgb() etc byte order when the (little-endian) integer
is read as 4 individual bytes.

The previous code did not account for the fact that non-indexed Png
uses big-endian storage for its RGBA colours, and that SheetBuilder
had the color channels incorrectly swapped to match and cancel this out.

New SpriteFrameType enums are introduced to distinguish between BGRA
(little-endian) and RGBA (big-endian) formats, and also for 24bit data
without alpha. The channel swizzling / alpha creation is now handled
when copying into the texture atlas, removing the need for non-png
ISpriteLoader implementations to allocate an additional temporary array
and reorder the channels during load.
This commit is contained in:
Paul Chote
2020-12-19 12:05:56 +00:00
committed by abcdefg30
parent 6e7ad9df25
commit ce09b402d0
15 changed files with 205 additions and 142 deletions

View File

@@ -18,7 +18,29 @@ using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public enum SpriteFrameType { Indexed, BGRA }
/// <summary>
/// Describes the format of the pixel data in a ISpriteFrame.
/// Note that the channel order is defined for little-endian bytes, so BGRA corresponds
/// to a 32bit ARGB value, such as that returned by Color.ToArgb()!
/// </summary>
public enum SpriteFrameType
{
// 8 bit index into an external palette
Indexed,
// 32 bit color such as returned by Color.ToArgb() or the bmp file format
// (remember that little-endian systems place the little bits in the first byte!)
BGRA,
// Like BGRA, but without an alpha channel
BGR,
// 32 bit color in big-endian format, like png
RGBA,
// Like RGBA, but without an alpha channel
RGB
}
public interface ISpriteLoader
{
@@ -47,7 +69,7 @@ namespace OpenRA.Graphics
public class SpriteCache
{
public readonly Cache<SpriteFrameType, SheetBuilder> SheetBuilders;
public readonly Cache<SheetType, SheetBuilder> SheetBuilders;
readonly ISpriteLoader[] loaders;
readonly IReadOnlyFileSystem fileSystem;
@@ -57,7 +79,7 @@ namespace OpenRA.Graphics
public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders)
{
SheetBuilders = new Cache<SpriteFrameType, SheetBuilder>(t => new SheetBuilder(SheetBuilder.FrameTypeToSheetType(t)));
SheetBuilders = new Cache<SheetType, SheetBuilder>(t => new SheetBuilder(t));
this.fileSystem = fileSystem;
this.loaders = loaders;
@@ -103,7 +125,7 @@ namespace OpenRA.Graphics
{
if (unloaded[i] != null)
{
sprite[i] = SheetBuilders[unloaded[i].Type].Add(unloaded[i]);
sprite[i] = SheetBuilders[SheetBuilder.FrameTypeToSheetType(unloaded[i].Type)].Add(unloaded[i]);
unloaded[i] = null;
}
}