Thursday, May 26, 2011

grayscale preview : done.

Well, I guess it would be fair enough to admit that my knowledge in image processing turned out to be insufficient to provide a "magic contrast boost" slider in SEDS. Yet I regularly have contrast issues with my sprites, and I've learnt on Pixelation forums that turning your sprite into grayscale is a nice way to investigate whether a sprite is contrasted and readable enough. So the plan was

gray = red*.30+grn*.59+blu*.11
C'est la formule qui permet de passer d'une couleur RGB à un niveau de gris "équivalent". Or, passer son sprite en niveau de gris, c'est le truc ultime des gurus de Pixelation pour savoir si le contraste est suffisant ou non. A défaut d'un "boosteur de contraste" magique, c'est le moins que je puisse tenter.

Reste à le mettre en oeuvre. C'est le genre de chose qui aurait été impensable avec mes éditeurs sous DOS, n'ayant qu'une palette unique de 256 couleurs ... Mais ici, avec le soutient des "sprites DirectColor" (ou ATTR0_BMP), c'est une autre histoire ... Moyennant une consommation de mémoire vidéo un peu plus importante, je peux directement donner les composant RGB de chaque pixel individuellement et indépendamment des palettes "background" et "sprite".

Ca n'aura pas été sans mal quand même, tant le fonctionnement de ces sprites diffère de celui de mes "bons vieux sprites habituels". D'abord, exit le tiling. Le pixel (x,y) à l'intérieur du sprite est stocké dans le y*width+x ème "short", tout simplement. Vu que la dénomination officielle est "SPR_BITMAP", il fallait un peu s'y attendre, celà dit :P
Deuxio, ces sprites-là ont leur propre bits de contrôle dans REG_DISPCNT, et peuvent donc rester en "mode 2D" alors que les autres sprites sont en mode 1D. On dirait d'ailleurs que desmume a encore quelques soucis avec ça et qu'il utilise ces sprites en mode 1D quoi qu'il advienne 0_0.
Enfin, le "numéro de tile" n'est plus du tout interprété de la même manière. L'interprétation exacte est donnée sur gbatek, mais en ce qui me concerne je me suis contenté d'une heuristique du genre "tileno/2" avec un 'padding' pour aligner les données du sprites sur le bloc de 32 tiles le plus proche:

tileno=Engine::allocate(Engine::RES_SPRITETILE,32+PAD); // will use directcolor.
if (PAD && tileno&(PAD-1)) tileno=(tileno+PAD)&(~(PAD-1));
sprdata = SPRITE_GFX + tileno*32;
Engine::sprites[oam].attribute[0]=ATTR0_BMP|ATTR0_ROTSCALE_DOUBLE|OBJ_Y(0);
Engine::sprites[oam].attribute[1]=ATTR1_ROTDATA(rot)|ATTR1_SIZE_32|OBJ_X(96);
Engine::sprites[oam].attribute[2]=ATTR2_PRIORITY(1)|ATTR2_ALPHA(1)|(tileno/2);
The idea was to use "direct-color" sprites in order to have the freedom of picking RGB colors without messing up with the sprite palette (sprites are already used to render the whole palette at the bottom of the editor, so that we have enough freedom for widgets). That would only cost me some more video memory (clearly affordable in this context) ... and some discovery of these new sprites' oddities...
A separate control on 1D/2D sprites, a specific scheme for reading data out of the VRAM (lowest bits of "tileno" are now used as a horizontal shift in an otherwise bitmap area) ... And of course, no tiling of the sprite data (these are named "BITMAP" sprites. What exactly did you expect, hmm ?)

Well, that's all done, now. Just give me some more time to remove debugging statements, and I should be able to release Sprite Editor 0.4 by Monday.

No comments: