GSoC project: Sprite engine overhaul - Weekly A&O report
Weekly A&O report
Hi everyone!
This is the very first of my weekly "Achievements and Objects", which will give you some ideas on what I've done so far and what i've planned for the next week.
Achievements
The first big piece of work that I already finished - actually I have done this during GSoC application period - is the rectangle packer.
The general problem is to fit a set of given small rectangles inside a larger rectangle which shall be as small as possible. The reason for wanting this is that graphics hardware prefers working with a single or few large textures over hundreds of small ones.
Unfortunateley there are no known algorithms that solve this problem perfect within feasable time.
Thats why some algorithm that doesnt necesarrily produce perfect results but at least "quite good" results is required.
In particular I've ported the MAXRECTS packer using the bssf heuristic as described here:
More Rectangle Bin Packing
This page contains quite a lot of in depth information about the general problem and as well visualizes different approaches.
The packers are licensed as public domain and thus the port is safe to be used for hedgewars.
You can take a look at my port here uBinPacker.pas.
As well try the test app test.pas
Last week I pretty much started messing around with the games code base.
Currently in the engine a sprite is represented like this: (ommiting irrelevant members)
TTexture = record
w, h: LongInt;
rx, ry: GLfloat;
vb, tb: array [0..3] of TVertex2f;
end;
w and h represent the physical dimension of the sprite in pixels. however the actual texture itself can be larger.
This was required as some GPUs only support certain texture sizes.
You might interpret this behaviour as some unoptimized atlas where each sprite gets packed into a (possibly larger) texture.
rx and ry encode scaling factors in case the sprite size differs from the texture size.
vb and tb hold precomputed texel positions and vertex positions to render a quad using the sprite at origin.
However this representation has issues:
It only would allow packing exactly one sprite into one physical texture.
It may may only be packed to a fixed corner.
What is needed is splitting logic between a physical texture and a sprite like so:
PTexture = ^TTexture;
TTexture = record
.. (irrelevant members that represent the texture)
end;
TSpriteInfo = record
atlas: PTexture;
physicalRect: RectangleI; // 4 integers
texelRect: RectangleF; // 4 floats
// either a scale factor here or a vertex rect as 2 points as with vb would go here if sprites shall be scalable,
// note that both, a scaling and rect would be redundant
end;
With this "trivial" looking change and replacing all TTexture occurrences with TSpriteInfos i hit quite massive impact within several files.
See the diff for the impact.
At least, after being a useless try, this gave me quite some insights about the codes structure and where I potentially cause impact.
Objectives
This leads me to my objectives for the ongoing week:
Extend the functionality to allow sprite/texture indirections, but without causing high impact.
Optionally in a second separate commit refactor data layout and naming, which however, cause larger impact.
Having both, functional changes and refactoring in one commit just causes too much mess.
To keep the impact low the new approach will simply go like this: (should have done this from start on)
TTexture = record
// This defines the physical rect
w,h: Longint; // physical size of the sprite as with the original TTexture
x,y: Longint; // offset in the atlas
atlas: PAtlas; // pointer to the actual texture
// texel and vertex rect for blitting this are just pre-computed cached values
// note that tb now might contain a rotated cut-out of the sprite that is the tb rects width corresponds to h
// while the height corresponds to w
vb, tb: array [0..3] of TVertex2f;
// scale factor is encoded to vb, if the engine requires this for collision detection means or whatever we should rather
// store it as precomputed ints? I need to investigate the actual impact of the scale factor for details to decide on this.
end;
During a seperate refactoring commit it'd be possible to rename and restructure the code like I originally tried.
- WolfgangSt's blog
- Login or register to post comments
Dark Spyro
Good work