* Tutorial.16 特殊効果 ブレンド [#s73e55be]
ブレンドはBGやスプライトから2つのグループを選択し、~
一定の割合で色を混ぜて表示する''アルファブレンド''と、~
白か黒を一定の割合で混ぜて表示する''フェード''があります。~

 #define REG_BLDCNT		*((vu16 *)(REG_BASE + 0x50))
 
 #define BLEND_TOP_BG0    (1<<0)    //TOP
 #define BLEND_TOP_BG1    (1<<1)
 #define BLEND_TOP_BG2    (1<<2)
 #define BLEND_TOP_BG3    (1<<3)
 #define BLEND_TOP_OBJ    (1<<4)
 #define BLEND_TOP_BD     (1<<5)
 
 #define BLEND_LOW_BG0    (1<<8)    //LOW
 #define BLEND_LOW_BG1    (1<<9)
 #define BLEND_LOW_BG2    (1<<10)
 #define BLEND_LOW_BG3    (1<<11)
 #define BLEND_LOW_OBJ    (1<<12)
 #define BLEND_LOW_BD     (1<<13)
 
 #define BLEND_MODE_OFF   (0<<6)    //MODE
 #define BLEND_MODE_ALPHA (1<<6)
 #define BLEND_MODE_LIGHT (2<<6)
 #define BLEND_MODE_DARK  (3<<6)

一番目のグループと二番目のグループに、どのBGやスプライトを割り当てるかの設定です。~
TOPのほうは一番目のグループに、LOWのほうは二番目のグループに割り当てます。~
両方のグループに同じものを割り当てることもできます。~

BG0-BG3はその番号のBG、OBJはスプライトすべて、BDは背景(詳細は不明)です。~
フェードモードのときはTOPに設定したものだけが対象になります。~
スプライトはスプライト同士の色の混ぜ合わせは行われないようです。~

MODEはブレンドの種類です。OFFは何もしません。~
- ALPHA 2つのグループの色を混ぜ合わせるアルファブレンド。
- LIGHT グループと白色を一定の割合で混ぜます。
- DARK グループと黒色を一定の割合で混ぜます。

*** アルファブレンド [#vaa779d0]
 #define REG_BLDALPHA	*((vu16 *)(REG_BASE + 0x52))
 
 #define BLEND_LOW(n)     ((n)<<0)
 #define BLEND_HIGH(n)    ((n)<<8)
 #define BLEND_LEVEL(n)   (BLEND_LOW(n) | BLEND_HIGH(n))
 #define BLEND_BALANCE(n) (BLEND_LOW(n) | BLEND_HIGH(16-n))

アルファブレンドを選んだ場合のそれぞれのグループの色を混ぜる割合です。~
LOWが2番目のグループ、HIGHが1番目のグループの割合になります。~

数値は0-16が設定できます。~
0が全くそのグループの色を発色せず、数値が大きくなるとその色が濃くなりますが、~
16が最高の割合で、それ以上の数値になっても変化しません。~

LEVELは2つのグループの発色を同じにします。~
BALANCEは2つのグループの値の合計が16(100%)になるようにします。~

*** フェード [#hc3b913e]
 #define REG_BLDY		*((vu16 *)(REG_BASE + 0x54))
 
 #define BLEND_DEPTH(n) ((n)<<0)

こちらはフェードを選んだ場合の黒または白と混ぜ合わせる割合です。

** ブレンドを使用した例 [#s13ac1b1]
** ブレンドの使用例 [#s13ac1b1]
 #include "lib/gba.h"
 #include "res.h"
 
 #define BG_MAX_CNT 4
 
 typedef struct {
 	u32  mapBase;
 	u16* mapBaseAdr;
 	u32  tileBase;
 	u16* tileBaseAdr;
 } ST_BG;
 
 //---------------------------------------------------------------------------
 ST_BG Bg[BG_MAX_CNT];
 
 //---------------------------------------------------------------------------
 void WaitForVsync(void)
 {
 	while(*(vu16*)0x4000006 >= 160) {};
 	while(*(vu16*)0x4000006 <  160) {};
 }
 //---------------------------------------------------------------------------
 void BgInitMem(void)
 {
 	const u32 mapBase[]  = { 11, 12,  0,  0 };
 	const u32 tileBase[] = {  0,  2,  0,  0 };
 	s32 i;
 
 	for(i=0; i<BG_MAX_CNT; i++)
 	{
 		Bg[i].mapBase     = MAP_BASE(mapBase[i]);
 		Bg[i].mapBaseAdr  = MAP_BASE_ADR(mapBase[i]);
 		Bg[i].tileBase    = TILE_BASE(tileBase[i]);
 		Bg[i].tileBaseAdr = TILE_BASE_ADR(tileBase[i]);
 	}
 
 	for(i=0; i<32*32; i++)
 	{
 		Bg[0].mapBaseAdr[i] = 0;
 		Bg[1].mapBaseAdr[i] = 0;
 		Bg[2].mapBaseAdr[i] = 0;
 		Bg[3].mapBaseAdr[i] = 0;
 	}
 
 	for(i=0; i<0x2000; i++)
 	{
 		Bg[0].tileBaseAdr[i] = 0;
 		Bg[1].tileBaseAdr[i] = 0;
 		Bg[2].tileBaseAdr[i] = 0;
 		Bg[3].tileBaseAdr[i] = 0;
 	}
 }
 //---------------------------------------------------------------------------
 void BgInit(void)
 {
 	BgInitMem();
 
 	REG_DISPCNT = MODE_0 | BG0_ON | BG1_ON;
  	REG_BLDCNT  = BLEND_TOP_BG0 | BLEND_LOW_BG1 | BLEND_MODE_ALPHA ;
 
 	REG_BG0CNT  = (BG_SIZE_0 | BG_16_COLOR | Bg[0].tileBase | Bg[0].mapBase);
 	REG_BG1CNT  = (BG_SIZE_0 | BG_16_COLOR | Bg[1].tileBase | Bg[1].mapBase);
 }
 //---------------------------------------------------------------------------
 void BgSetTile(u32 bg, u16* pDat, u32 size)
 {
 	volatile u32 i;
 
 	for(i=0; i<size; i++)
 	{
 		Bg[bg].tileBaseAdr[i] = pDat[i];
 	}
 }
 //---------------------------------------------------------------------------
 void BgSetPal(u32 pal, u16* pDat)
 {
 	volatile u32 i;
 
 	for(i=0; i<16; i++)
 	{
 		BG_PALETTE[pal*16+i] |= pDat[i];
 	}
 }
 //---------------------------------------------------------------------------
 void BgSetMap(void)
 {
 	volatile u32 i;
 
 	for(i=0; i<32*20; i++)
 	{
 		Bg[0].mapBaseAdr[i] = i;
 		Bg[1].mapBaseAdr[i] = i | (1 << 12);
 	}
 }
 //---------------------------------------------------------------------------
 int main(void)
 {
 	BgInit();
 
 	BgSetTile(0, (u16*)&imageTiles, imageTilesLen/2);
 	BgSetTile(1, (u16*)&image2Tiles, image2TilesLen/2);
 
 	BgSetPal(0, (u16*)&imagePal);
 	BgSetPal(1, (u16*)&image2Pal);
 
 	BgSetMap();
 
 
  	s16 vcnt = 10;
 
 	for(;;)
 	{
 		WaitForVsync();
 
  		REG_BLDALPHA = BLEND_BALANCE(vcnt);
 
  		if( !(REG_KEYINPUT & KEY_UP)   ) vcnt--;
  		if( !(REG_KEYINPUT & KEY_DOWN) ) vcnt++;
  		if(vcnt <  0) vcnt = 0;
  		if(vcnt > 16) vcnt = 16;
 	}
 }

*** 動作画面 [#k43d1c41]
#ref(clip_1.png,nolink)


** 履歴 [#yfc8880c]
- 2014/01/04
- 2007/09/07