Showing posts with label alpha-blending. Show all posts
Showing posts with label alpha-blending. Show all posts

Sunday, April 21, 2013

translucent ?

I managed to have some translucent effect through fast (60Hz) sprite flickering. That's mandatory if I want sprite-versus-sprite transparency. So if I want Bilou to look "inside" the inkjet, I need an extra patch of glass that will flicker over Bilou to partially obscure him.

J'étais tombé par hasard sur l'épisode "Spécial Disney" du joueur du grenier, dernièrement.  Après une bonne tranche de rire avec ma fée sur la partie "La Belle et La Bête", l'analyse (nettement plus grossière) de Fantasia par Infogrames me rappelle à quel point il est important de soigner la communication des règles du gameplay à travers l'aspect visuel. Le livre géant et menaçant qui est en réalité un bonus (et non un ennemi comme son aspect le suggère) et l'espèce de rond dans l'eau qui est en réalité une plate-forme.

Mais maintenant que j'ai le moyen technique de rendre les sprites transparents les uns par rapport aux autres, est-il intéressant de rendre l'encrier transparent ? C'est plus réaliste, sans aucun doute mais ça n'est pas forcément mieux pour autant. L'aspect d'Inkjet doit transmettre au joueur "solide, dangereux, mais pas blessant", et pas "fantôme immatériel mélangé à l'arrière plan". J'ai donc fort probablement commencé l'ajout des sprites rectangulaires (pourtant attendu depuis longtemps) sans que ça n'ait aucune utilité immédiate.

That being done, shouldn't the inkjet itself be translucent (against the background), and if so, how do I achieve that, given that the ink itself must remain opaque ? Basically, the only way is to separate the "glass" of the inkjet and the ink itself. That puts enormous stress on the vram as inkjet animation takes almost 1/4th of the spriteset so far. doubling it ? aouch. Hopefully, the ink only takes 16 pixels high, so that would be worth an update of SEDS to support wide (and tall?) in addition to square sprites.

Although its in progress, is it really wise to go that way ? Does the translucent inkjet on the right look better than the non-translucent (except for the patch) on the left ? Or does it rather look ghost-like rear object which you wouldn't expect to be solid and ride-able ? After all, form-fits-function is crucial in video games, and the only way to allow the player to have "eureka" feeling rather than progressing through frustrating trial-and-error.


Bref, c'est l'occasion de rajouter le terme "Form Fits Function" au tagtionaire... ce lien entre l'aspect et l'effet si cher à Miyamoto et qu'Infogrames a systématiquement ignoré.

PS: the DS also has 16-color sprites, and obviously, the inkjet shouldn't need more. Converting the whole sprite page into 16 colors could do the trick ... but that's not supported neither by the Game Engine nor by the Sprite Editor at the time of writing. At best, it's a wish.

PPS: pour ceux qui voudraient essayer le jeu, c'est par ici.

Saturday, September 03, 2011

OAM Alpha

Résumons un peu:
- si je veux un niveau de transparence variable pour un sprite, le seul moyen est d'utiliser un sprite en mode bitmap/direct color ((Attr 0, Bit10-11) to a value of 3) et d'utiliser le champ prévu pour le no de palette pour "personnaliser" le niveau de transparence.
- pour les sprites à palette, ce sont les mêmes registres "BLDCNT" et "BLDALPHA" qui régulent la transparence des sprites depuis le GBA.

REG_BLDCNT_SUB = BLEND_DST_BG0|BLEND_DST_BG3|    BLEND_SRC_BG2|BLEND_SRC_SPRITE|BLEND_ALPHA; permet donc d'afficher des sprites et le calque 2 transparents par-dessus BG0 et BG3 (pour autant que ces deux calques soient effectivement derrière eux, sans autre chose pour faire obstruction).

Mais comment faire pour que seuls certains sprites soient transparents?

OBJs that are defined as 'Semi-Transparent' in OAM memory are always selected as 1st Target (regardless of BLDCNT Bit 4), and are always using Alpha Blending mode (regardless of BLDCNT Bit 6-7).
nous apprend-on sur gbatek.

C'est donc le rôle de ATTR0_TYPE_BLENDED (à utiliser à la place de ATTR0_TYPE_NORMAL) qui sélectionne le sprite en question comme "source d'alpha-blending" indépendamment de la valeur de BLEND_SRC_SPRITE dans le registre BLDCNT.

Cool. Je suis prêt à attaquer l'implémentation de "l'onion skin" dans AnimEDS ^_^

I need 'onion skin' preview of the previous/next frame in AnimEDS, which suppose some sort of alpha-blending on the frame editor, which is made of sprites. I've got a DS alpha-blending tutorial around for some years now, but my last attempt to have that working in the level editor was rather disappointing. So here's a recap:
  • You can make all the sprites have some alpha-blending by turning on BLEND_SRC_SPRITE in REG_BLDCNT_SUB ... not that useful. You're more likely to want a BG translucent that let sprites show through as well. That's with REG_BLDCNT_SUB|=BLEND_DST_SPRITE
  • You can selectively turn on blending of some sprites by using ATTR0_TYPE_BLENDED. That's what I need in my editors, but the blending level will be the same for all sprites (and layers).c
  • bitmap-type sprites use direct colors (bypassing the palettes), so the ATTR2_PALETTE() field of GBA sprites is useless and has been recycled into ATTR2_ALPHA. I guess you still depend on REG_BLDCNT to tell *what* you're transparent against... Oh, and don't forget to set REG_BLDALPHA to some value, of course.

Saturday, September 09, 2006

Alpha blending.

Okay, i'm trying to make sense of the alpha-blending bits of the nintendo DS. I'd like a blended grid for my editor ;)

So, let's see the specs first:

4000050h 2 R/W BLDCNT Color Special Effects Selection (BLEND_CR)
4000052h 2 W BLDALPHA Alpha Blending Coefficients (BLEND_AB)
4000054h 2 W BLDY Brightness (Fade-In/Out) Coefficient (BLEND_Y)
Bion. Voyons voir comment marche l'alpha-blending -- c'est à dire la transparence sur les fonds -- sur la console DS (j'aimerais bien pouvoir "estomper" la grille de mon sprite editor, si vous voulez tout savoir). Trois registres jouent un rôle dans les "effets spéciaux" (fade-in/fade-out et blending) : BLEND_CR, BLEND_AB et BLEND_Y. Je suis reparti de la démo Complex2D du devkitpro pour étudier comment ça marche.

You have 3 registers responsible of "special effects", including fade-in, fade-out and alpha blending. The latter one is the one we want (mixing two layers to have one of them appearing "translucent" and seeing the second one through. Clearly, we want it for fogs, clouds, mirrors, ghosts and plenty other reasons ;)

So, let's take the Complex2D demo from devkitpro and spice it up a little bit.

//set up the sub display
videoSetModeSub(MODE_0_2D |
DISPLAY_SPR_1D_LAYOUT |
DISPLAY_SPR_ACTIVE |
DISPLAY_BG0_ACTIVE |
DISPLAY_BG1_ACTIVE );

//set up two backgrounds to scroll around
SUB_BG0_CR = BG_COLOR_256 | (1 << SCREEN_SHIFT) | BG_PRIORITY(0);
SUB_BG1_CR = BG_COLOR_256 | (2 << SCREEN_SHIFT) | BG_PRIORITY(1);
BG_PALETTE_SUB[0] = RGB15(10,10,10);
BG_PALETTE_SUB[1] = RGB15(0,16,0);
BG_PALETTE_SUB[2] = RGB15(0,0,31);
vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);

There is two background layers, one being green-checker (BG0) and the other one being blue-checker (BG1). Each checker's "dark" squares are actually see-through pixels (purely transparent), which you achieve with color 0. Moreover, you have the 'backdrop' layer (here a dark-grey colour) that is seen when all pixels of all layers use color 0 (you typically never see the backdrop in a game, for instance).

Dans cette démo, on construit deux damiers, l'un vert (BG0) et l'autre bleu (BG1). Les cases "noires" de ces damiers sont en fait des pixels complètement transparents (couleur #0) et la couleur de fond (le "backdrop" -- que l'on préfère ne jamais voir dans un jeu vidéo) est gris-foncé.

//load the maps with alternating tiles (0,1 for bg0 and 0,2 for bg1)
for(iy = 0; iy < 32; iy++)
for(ix = 0; ix <32; ix++) {
map0[iy * 32 + ix] = ((ix ^ iy) & 2)>>1;
map1[iy * 32 + ix] = ((ix ^ iy) & 2);
}

//fill 2 tiles with different colors
for(i = 0; i < 64 / 2; i++) {
BG_GFX_SUB[i+32] = 0x0101;
BG_GFX_SUB[i+32+32] = 0x0202;
}


So far, we'll use SUB_BLEND_AB=0x1010, which is full intensity for both layers. If one is blue, the other red and that blending occurs, we should see purple somewhere. The initial priority is set to green-over-blue and we slowly scroll the green checker over the blue one. No blending is activated so far.

  • with SUB_BLEND_CR=BLEND_ALPHA|BLEND_SRC_BG0|BLEND_SRC_BG1; we do not change much things, as both layers are used as "blending source" but no layer is definde "transparent".

  • SUB_BLEND_CR=BLEND_ALPHA|BLEND_SRC_BG0|BLEND_DST_BG1; is more interesting. The green checker is still over the blue one, but it no longer "hides" blue pixels. Instead, it mixes with them to produce
    light-blue.

  • SUB_BLEND_CR=BLEND_ALPHA|BLEND_DST_BG0|BLEND_SRC_BG1; and SUB_BLEND_CR=BLEND_ALPHA| BLEND_DST_BG0|BLEND_DST_BG1|BLEND_SRC_BACKDROP appear such as the initial (no destination) blending.


Now, if we swap the priorities (e.g. blue checker-BG1 over green checker-BG0), the first setting (SRC_BG0|SRC_BG1) still show both layers opaque, but now that's (DST_BG0|SRC_BG1) that shows
alpha-blending while (SRC_BG0|DST_BG1) only shows opaque pixels.

In other words:
  • the source layer(s) must be over destination layer(s) to have some blending displayed. that means the priority of source layers should be numerically lower than the priority of destination layers.

  • the source layer is what is going to be translucent, the destination(s) is what is going to be seen through (and yes, i find this rather confusing).

En clair, le layer 'source' doit être par-dessus le layer "destination" pour que l'effet soit visible. Cela signifie que la priorité du layer "source" doit être numériquement inférieure à celle du layer "destination". Et oui, la libnds appelle "source" le layer qui sera transparent et "destination" le layer que l'on voit à travers l'effet. C'est perturbant, mais c'est comme ça.
J'ai parlé de transparence 50/50, mais une valeur 0x1010 pour BLEND_AB correspond plutôt à une composition additionnelle: R = 1*Ra + 1*Rb, V = 1*Va + 1*Vb ... ce qui peut être perturbant aussi. Supposons qu'on veuille faire un nuage ou un fantôme (qui sera donc notre source), on prendra une valeur de 1 pour le multiplicateur des layers-destination (histoire que le fantôme n'assombrisse jamais le décor) mais le fantôme étant du blanc pur, on ne l'affichera qu'à 50%, ce qui donnera BLEND_AB = 0x0810.

Note that calling 0x1010 a 50/50 blending is a bit exagerated. what it means is that you end up with a pixel whose values are R = 1*Ra + 1*Rb, G = 1*Ga +1*Gb and B = 1*Ba + 1*Bb. That may be a bit confusing too.
For clouds/ghosts, you want the cloud-carrying layer to be the source. The other layers should keeps they alpha-blending value to 1 (so that the cloud doesn't "darken" them), but the cloud itself (bright white) should e.g. only affect by 0.5, so that your grey tower appearslightgrey where the cloud is. That leads to e.g. BLEND_AB=0x0810.

The full demo code is available here.
Btw, See also liranuna's witch demo for alpha-blending of sprites over backgrounds.