Difference between revisions of "GSoC Sprite Sheets Shuger"

From The Battle for Wesnoth Wiki
(add link to SoC application)
(Performane)
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{SoC2010Student}}
+
{{SoC2010Student_2|shuger|SoC Ideas SpriteSheets}}
 +
[[Category:SoC Ideas SpriteSheets]]
  
 
=Description=
 
=Description=
I want add sprite sheet support to Wesnoth. The general idea is to assemble multiple small images into few bigger.
+
====Shuger - sprite sheet support====
 +
I want add sprite sheet support to Wesnoth. The general idea is to assemble multiple small images into few bigger
  
 
=IRC=
 
=IRC=
Line 8: Line 10:
  
 
=SoC Application=
 
=SoC Application=
[http://socghop.appspot.com/gsoc/student_proposal/review/google/gsoc2010/shuger/t127075149747 t127075149747]
+
[http://socghop.appspot.com/gsoc/student_proposal/review/google/gsoc2010/shuger/t127075149747 Wesnoth application]
  
 
=Questionnaire=
 
=Questionnaire=
Line 15: Line 17:
 
=Implementation=
 
=Implementation=
 
==Sprite Formats==
 
==Sprite Formats==
In my idea of implementation there are three possible sprite formats:
+
In my idea of implementation there are two possible sprite formats:
 
* separate files
 
* separate files
* normal sprite sheet
+
* sprite sheet
* optimized sprite sheet
 
 
===separate files===
 
===separate files===
 
Current way of managing sprites, each image in a separate file.
 
Current way of managing sprites, each image in a separate file.
Line 24: Line 25:
 
wml remains the same.
 
wml remains the same.
  
===normal sprite sheet===
+
===sprite sheet===
Multiple sprites on one big image. This is a way for artists to work if they prefer sprite sheets over separate images. The artist can place sprites in a sheet in any way he/she wants.
 
 
 
example wml:
 
[frame]
 
    x_position = 32
 
    y_position = 32
 
    x_size = 32
 
    y_size = 32
 
    image="units/elves-wood/archer+female-spritesheet.png"
 
[/frame]
 
 
 
x_position and y_position - position of the sprite in the sheet, in pixels from top left corner(because of the way SDL coordinate system works).
 
 
 
x_size and y_size - optimized sprite size.
 
 
 
===optimzed sprite sheet===
 
 
This format is not for manual editing. It is created from separete files or normal sprite sheet automatically. To generate it special packing algorithms will be used to optimize it's size. This will be the format normally used. Generation should occur at build time uing a custom tool added to build process. It will be possible too run tool manually if someon desires.
 
This format is not for manual editing. It is created from separete files or normal sprite sheet automatically. To generate it special packing algorithms will be used to optimize it's size. This will be the format normally used. Generation should occur at build time uing a custom tool added to build process. It will be possible too run tool manually if someon desires.
  
Line 46: Line 31:
 
1. Parse wml file created by artist and collect all information about needed sprites for certain unit.
 
1. Parse wml file created by artist and collect all information about needed sprites for certain unit.
 
2. Load all needed images, parts normal sprite sheet specified by wml file.
 
2. Load all needed images, parts normal sprite sheet specified by wml file.
3. Optimze all sprites by cutting unneeded part of sprites.
+
3. Use a rectangle packing algorithm to pack them into as small space as possible.
4. Use a rectangle packing algorithm to pack them into as small space as possible.
+
4. Bake optimized sprites onto new optimized sprite sheet using information from step 4. Write it to a new file.
5. Bake optimized sprites onto new optimized sprite sheet using information from step 4. Write it to a new file.
+
5. Update wml file with changing all references to optimized version and adding each sprite offset and size information.
6. Update wml file with changing all references to optimized version and adding each sprite offset and size information.
 
  
 
example wml frame definition:
 
example wml frame definition:
Line 57: Line 41:
 
     x_size = 24
 
     x_size = 24
 
     y_size = 24
 
     y_size = 24
    x_offset = 6
 
    y_offset = 6
 
 
     image="units/elves-wood/archer+female-spritesheet.png"
 
     image="units/elves-wood/archer+female-spritesheet.png"
 
  [/frame]
 
  [/frame]
Line 67: Line 49:
 
x_size and y_size - optimized sprite size.
 
x_size and y_size - optimized sprite size.
  
x_offset and y_offset - If image was optimized by cutting transparent border it needs to be offset during blitting.
+
Optional algorithm step:
 
+
Once all other features will be completed additional step maybe added. However it will need to be tested whetever it gives some reasonable gains.
 
 
Comment on step 3:
 
 
Many sprites have image (say 72x72 pixels) where only a part is actually a sprite and the rest is wide transparent border. This doesn't considerably impact image size on disk, because of png compression but is taking significant amount of uneeded memory when loaded into SDL surface (which doesn't use compression). The point of this step is to crop the image by finding a minimal rectangle to fit entire sprite in and then store the size and offset of this rectangle in comparison to original image in order to blit image properly.
 
Many sprites have image (say 72x72 pixels) where only a part is actually a sprite and the rest is wide transparent border. This doesn't considerably impact image size on disk, because of png compression but is taking significant amount of uneeded memory when loaded into SDL surface (which doesn't use compression). The point of this step is to crop the image by finding a minimal rectangle to fit entire sprite in and then store the size and offset of this rectangle in comparison to original image in order to blit image properly.
  
==Memory==
+
==Performance==
First gain for the memory will come from cropping sprites as described earlier. Second will come from using a cache. There is no need to store every spritesheet in uncompressed format as it will requie a lot of memory even if not needed. On the other hand disk operations are very slow so reading spriteshhets during game should be avoided. The solution to this is to hold currently unused sprites in compressed format. SDL_image allows it. Instead of directly loading into a surface images can be loaded without parsing into memory. It will take only as much memory as file on hard drive. Also compressing one big image gives better results then many small ones.  
+
===General info===
 +
When optimizing anything you can never assume anything that's why all things mentioned in this section must be profiled in prototype stage of implementation to see if they bring any considerable gains.
 +
===RLE Surfaces===
 +
SDL allows RLE surfaces. Typically RLE alogrithms are used to compress images, but SDL RLE surfaces are made for speed not for memory usage. This is going with some additional processsing that's needs to be done during loading. Despite for SDL RLE focus on speed in images like in wesnoth were there are long horizontal strips of the same color(example: transparent border) there is also smaller memory usage.
 +
===Caching===
 +
Proper use of caching may lower memory requiements. Instead of holding spritesheets in memory at all times, only the needed ones should be loaded. This can be implemented by using a caching algorithm to manage what spritesheets to keep in memory an which ones to load/unload.  
  
First step is to load image from hard drive using SDL_RWFromFile function. Then once cached sprite sheet will be needed it will unpacked using IMG_Load_RW (this is from SDL_image library). Once not needed anymore, uncompressed surface will be deleted from memory.
+
Because loading an image from hard drive can be slow(disk operations in general then to be very slow) cache can hold currently unused spritesheets in unprocessed format which has the same size as image on the hard drive. SDL supports it (IMG_Load_RW, SDL_RWFromFile, etc).
  
This may require some changes to Wesnoth cache code. Also while it may seem that uncompressing raw data is performance loss, it's actually not that slow compared to reading from disk which takes most of the time neded to load image completely
+
This may require some changes to Wesnoth cache code. Also while it may seem that uncompressing raw data is performance loss, it's actually not that slow compared to reading from disk which takes most of the time neded to load image completely.
 
 
==Performance==
 
Croping sprites will increase blitting speed beacause there will be less data for SDL to process in blitting functions.
 
  
==Workfolw==
+
Other game code shouldn't have to concern itself with were the image is(memory/hard drive) so it should fetch them threw a special locator.
1. Artist makes sprite bay making separate images or normal sprite sheet.
 
  
2. He can test those normally. The game will support both formats.
+
===Packing===
 +
Artists cannot be expected and shouldn't be bothered with making spritesheets memory efficient. Therefore during spritesheet loading all sprite frames from current group(ex. elf warrior) will be fetched from their respective sources and put on new generated spritesheet. Special packing algorithm will be used to make it efficient. This problem is algorithmically hard therefore different algorithm should be considered and tested before final choice can be made. One example algorithm is here: http://www-rcf.usc.edu/~skoenig/icaps/icaps04/icapspapers/ICAPS04KorfR.pdf
  
3. Special tool will be run at build time to process al images and sprite sheets
+
==Tools==
 +
Important part of making it easy for artists to work with spritesheets are tools. There will be a tool that would allow to generate spritesheets from multiple images and modify or create wml accordingly. It will also allow to update already done spritesheet if needed. It tool will be written in python with simple to use gui(pyQt or pyGTK can be used for this).

Revision as of 21:12, 18 April 2010


This page is related to Summer of Code 2010
See the list of Summer of Code 2010 Ideas



This is a Summer of Code 2010 student page
Project: SoC Ideas SpriteSheets


Description

Shuger - sprite sheet support

I want add sprite sheet support to Wesnoth. The general idea is to assemble multiple small images into few bigger

IRC

Shuger

SoC Application

Wesnoth application

Questionnaire

http://wiki.wesnoth.org/User:Shuger

Implementation

Sprite Formats

In my idea of implementation there are two possible sprite formats:

  • separate files
  • sprite sheet

separate files

Current way of managing sprites, each image in a separate file.

wml remains the same.

sprite sheet

This format is not for manual editing. It is created from separete files or normal sprite sheet automatically. To generate it special packing algorithms will be used to optimize it's size. This will be the format normally used. Generation should occur at build time uing a custom tool added to build process. It will be possible too run tool manually if someon desires.

Algorithm: 1. Parse wml file created by artist and collect all information about needed sprites for certain unit. 2. Load all needed images, parts normal sprite sheet specified by wml file. 3. Use a rectangle packing algorithm to pack them into as small space as possible. 4. Bake optimized sprites onto new optimized sprite sheet using information from step 4. Write it to a new file. 5. Update wml file with changing all references to optimized version and adding each sprite offset and size information.

example wml frame definition:

[frame]
    x_position = 32
    y_position = 32
    x_size = 24
    y_size = 24
    image="units/elves-wood/archer+female-spritesheet.png"
[/frame]

notes:

x_position and y_position - position of the sprite in the sheet, in pixels from top left corner(because of the way SDL coordinate system works).

x_size and y_size - optimized sprite size.

Optional algorithm step: Once all other features will be completed additional step maybe added. However it will need to be tested whetever it gives some reasonable gains. Many sprites have image (say 72x72 pixels) where only a part is actually a sprite and the rest is wide transparent border. This doesn't considerably impact image size on disk, because of png compression but is taking significant amount of uneeded memory when loaded into SDL surface (which doesn't use compression). The point of this step is to crop the image by finding a minimal rectangle to fit entire sprite in and then store the size and offset of this rectangle in comparison to original image in order to blit image properly.

Performance

General info

When optimizing anything you can never assume anything that's why all things mentioned in this section must be profiled in prototype stage of implementation to see if they bring any considerable gains.

RLE Surfaces

SDL allows RLE surfaces. Typically RLE alogrithms are used to compress images, but SDL RLE surfaces are made for speed not for memory usage. This is going with some additional processsing that's needs to be done during loading. Despite for SDL RLE focus on speed in images like in wesnoth were there are long horizontal strips of the same color(example: transparent border) there is also smaller memory usage.

Caching

Proper use of caching may lower memory requiements. Instead of holding spritesheets in memory at all times, only the needed ones should be loaded. This can be implemented by using a caching algorithm to manage what spritesheets to keep in memory an which ones to load/unload.

Because loading an image from hard drive can be slow(disk operations in general then to be very slow) cache can hold currently unused spritesheets in unprocessed format which has the same size as image on the hard drive. SDL supports it (IMG_Load_RW, SDL_RWFromFile, etc).

This may require some changes to Wesnoth cache code. Also while it may seem that uncompressing raw data is performance loss, it's actually not that slow compared to reading from disk which takes most of the time neded to load image completely.

Other game code shouldn't have to concern itself with were the image is(memory/hard drive) so it should fetch them threw a special locator.

Packing

Artists cannot be expected and shouldn't be bothered with making spritesheets memory efficient. Therefore during spritesheet loading all sprite frames from current group(ex. elf warrior) will be fetched from their respective sources and put on new generated spritesheet. Special packing algorithm will be used to make it efficient. This problem is algorithmically hard therefore different algorithm should be considered and tested before final choice can be made. One example algorithm is here: http://www-rcf.usc.edu/~skoenig/icaps/icaps04/icapspapers/ICAPS04KorfR.pdf

Tools

Important part of making it easy for artists to work with spritesheets are tools. There will be a tool that would allow to generate spritesheets from multiple images and modify or create wml accordingly. It will also allow to update already done spritesheet if needed. It tool will be written in python with simple to use gui(pyQt or pyGTK can be used for this).