Blending sprites

Post Reply
surffer3d
Posts: 4
Joined: Tue Aug 17, 2010 12:08 am

Blending sprites

Post by surffer3d » Tue Aug 17, 2010 12:29 am

Hello,

I'm learning about libnds, and now I'm facing sprite blending. I could get the sprites to blend all at once, but I need to enable/disable the effect on each one. I don't know if this is possible, or maybe I missed it in the provided examples. Anyway, I'm finding this blending topic a little difficult, so I wanted to ask if the way I'm approaching it is correct:

1) Activate alpha blending. For that I use the following code, since I didn't found any function to do that tasks (the offset 0x1000 just for the subengine). The register information comes from http://nocash.emubase.de/gbatek.htm

Code: Select all

    u16* mem_BLDCNT_SUB = (u16*)(0x04000050 + 0x1000);
    *mem_BLDCNT_SUB = BIT(4) | BIT(6) | BIT(11); // Alpha blend objects with bg_layer 3

    u16* mem_BLDALPHA_SUB = (u16*)(0x04000052 + 0x1000);
    *mem_BLDALPHA_SUB = (8) | (16<<8); // Change the factors as needed
2) Well, I couldn't get anywhere else. The documentation states that in bitmap sprites the palette index of oamSet is used as alpha factor, but I coudln't get any change in that way (just using the up global value worked). Then I checked the oamSet function in sprite.c and found the following code:

Code: Select all

    // format is of type SpriteColorFormat
    if(format != SpriteColorFormat_Bmp) {
        oam->oamMemory[id].colorMode = format;
    } else {
        oam->oamMemory[id].blendMode = format;
    }
I've tried changing myself the blendMode option directly for different kinds of tiles (bitmap and 8bit palette), but nothing worked. Has anyone a solution for this or knows if it is possible to achieve?

zeromus
Posts: 212
Joined: Wed Mar 31, 2010 6:05 pm

Re: Blending sprites

Post by zeromus » Tue Aug 17, 2010 1:59 am

you can modify the bitmap_sprites example to get the desired effect.

change line 23:
{0, SpriteSize_32x32, SpriteColorFormat_Bmp, 0, 8, 20, 0}, //moves it up so that you can see it blend on text, and changes alpha from 15 to 8

and add this somewhere

//blend objects onto all layers, and backdrop
vu16* mem_BLDCNT_SUB = (vu16*)(0x04000050 + 0x1000);
*mem_BLDCNT_SUB = BIT(4) | BIT(0) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13);

registers should be volatile (check all the dozens of libnds headers). speaking of libnds headers, why not use the register declared in there?

Youre using the sub engine blend controls. Are you putting the sprites on sub engine?

One other thing you may try is manually setting colormode=0

oamSub.oamMemory[0].colorMode = (ObjColMode)0;

It seems from available reference material and personal experiments that this truly must be 0 to get a bitmap sprite
Last edited by zeromus on Tue Aug 17, 2010 2:32 am, edited 2 times in total.

WinterMute
Site Admin
Posts: 2003
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Blending sprites

Post by WinterMute » Tue Aug 17, 2010 2:29 am

Code: Select all

REG_BLDALPHA_SUB = (8) | (16<<8); // Change the factors as needed
REG_BLDCNT_SUB = BLEND_ALPHA | BLEND_SRC_SPRITE | BLEND_DST_BG0 |BLEND_DST_BG1 | BLEND_DST_BG2 | BLEND_DST_BG3 | BLEND_DST_SPRITE | BLEND_DST_BACKDROP;
might be a bit more obvious about what it's doing, although I guess we could do with some macros for the blend factors.
Help keep devkitPro toolchains free, Donate today

Personal Blog

surffer3d
Posts: 4
Joined: Tue Aug 17, 2010 12:08 am

Re: Blending sprites

Post by surffer3d » Tue Aug 17, 2010 11:31 am

Thanks for the replies! I didn't know that the registers where available in the documentation, so thanks to point this out! It would be nice if them could be also added to the documentation in the future. And also I didn't realize about the variables should be declared volatile.

I've tried with the example that zeromus suggested, and I modified it a little for testing the blending capabilites in the following ways:
1) now the 3 sprites are of bitmap type
2) I simplified it a little to avoid unnecessay code for the test (so no orientation, for instance). Here is the code:

Code: Select all

#include <cstdio>
#include <nds.h>

//a simple sprite structure 
//it is generally preferred to separate your game object
//from OAM
typedef struct  
{
   u16* gfx;
   SpriteSize size;
   SpriteColorFormat format;
   int rotationIndex;
   int paletteAlpha;
   int x;
   int y;
}MySprite;

int main(int argc, char** argv) {
	
   //three bitmap sprites
   MySprite sprites[] = {
      {0, SpriteSize_32x32, SpriteColorFormat_Bmp, -1, 0, 20, 5},
      {0, SpriteSize_32x32, SpriteColorFormat_Bmp, -1, 8, 20, 70},
      {0, SpriteSize_32x32, SpriteColorFormat_Bmp, -1, 15, 20, 126}
   };

   videoSetModeSub(MODE_0_2D);

   consoleDemoInit();
   
   REG_BLDALPHA_SUB = (8) | (8<<8); // Change the factors as needed
   REG_BLDCNT_SUB = BLEND_ALPHA | 
                    BLEND_SRC_SPRITE | 
                    BLEND_DST_BG0 |BLEND_DST_BG1 | BLEND_DST_BG2 | BLEND_DST_BG3 | BLEND_DST_SPRITE | BLEND_DST_BACKDROP;

   //initialize the sub sprite engine with 1D mapping 128 byte boundary
   //and no external palette support
   oamInit(&oamSub, SpriteMapping_Bmp_1D_128, false);

  
   vramSetBankD(VRAM_D_SUB_SPRITE);
   
   //allocate some space for the sprite graphics
   for(int i = 0; i < 3; i++)
      sprites[i].gfx = oamAllocateGfx(&oamSub, sprites[i].size, sprites[i].format);
   
   //ugly positional printf
   printf("\x1b[1;1HDirect Bitmap: RED");
   printf("\x1b[9;1HDirect Bitmap: GREEN");
   printf("\x1b[16;1HDirect Bitmap: BLUE");
   
   //fill bmp sprite with the color red
   dmaFillHalfWords(ARGB16(1,31,0,0), sprites[0].gfx, 32*32*2);
   //fill the 256 color sprite with index 1 (2 pixels at a time)
   dmaFillHalfWords(ARGB16(1,0,31,0), sprites[1].gfx, 32*32*2);
   //fill the 16 color sprite with index 1 (4 pixels at a time)
   dmaFillHalfWords(ARGB16(1,0,0,31), sprites[2].gfx, 32*32*2);

   while(1)
   {
      for(int i = 0; i < 3; i++)
      {
         oamSet(
         &oamSub, //sub display 
         i,       //oam entry to set
         sprites[i].x, sprites[i].y, //position 
         0, //priority
		 sprites[i].paletteAlpha, //alpha (since we just have bmp sprites)
         sprites[i].size, 
		 sprites[i].format, 
		 sprites[i].gfx, 
		 -1,  // no rotation
         true, //double the size of rotated sprites
         false, //don't hide the sprite
		 false, false, //vflip, hflip
		 false //apply mosaic
         );

        //oamSub.oamMemory[i].colorMode = (ObjColMode)1;
        //oamSub.oamMemory[i].blendMode = (ObjBlendMode)3;
      }

      swiWaitForVBlank();

      //send the updates to the hardware
      oamUpdate(&oamSub);
   }
   return 0;
}
However, if you try it (I'm trying on No$GBA) you'll see all the sprites share the same alpha blending level, even I assigned to them different values in the array construction (0,8 and 15). Commenting the REG_BLDALPHA_SUB line just makes the sprites completely black, but I think this is just the case where the blending coeficients are both 0.

So the problem is that I still can't get a different alpha level for each sprite. (I also played directly modifying colorMode and blendMode, but nothing). Could you tell me how to do that?

zeromus
Posts: 212
Joined: Wed Mar 31, 2010 6:05 pm

Re: Blending sprites

Post by zeromus » Tue Aug 17, 2010 10:44 pm

two problems:

1. always test on hardware
2. if you are testing in emulators, always use more than one. if you insist on only using one, then make it desmume, where at least you have some recourse if the emulation fails. in this case, nocash is rendering incorrectly.

surffer3d
Posts: 4
Joined: Tue Aug 17, 2010 12:08 am

Re: Blending sprites

Post by surffer3d » Wed Aug 18, 2010 12:53 am

You were right ... it was working fine on the console but not on the emulator, my fault. From now I will test more often on console.

Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests