You are not logged in.
By popular demand, it's nearly 4am and I think I've just got it working ...beta test your little hearts out
Please read the comments before asking me questions ...If there is anything that is not totally clear, I am more likely to tweak the comments and upload new code than give a straight answer
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include "GRRLIB.h" #include <string.h> // Compositions Modes // NORMAL : a-over-b alpha composition (normal) // ...more to come typedef enum Composition_Modes { GRRLIB_COMPOSE_NORMAL, } GRRLIB_ComposeMode; // Feel free to convert these to inline functions if it floats your boat #define R(c) (((c) >>24) &0xFF) // Exract RED component of colour #define G(c) (((c) >>16) &0xFF) // Exract GREEN component of colour #define B(c) (((c) >> 8) &0xFF) // Exract BLUE component of colour #define A(c) ( (c) &0xFF) // Exract ALPHA component of colour // Build an RGB pixel from components #define RGBA(r,g,b,a) ( (u32)( ( ((u32)(r)) <<24) | \ ((((u32)(g)) &0xFF) <<16) | \ ((((u32)(b)) &0xFF) << 8) | \ ( ((u32)(a)) &0xFF ) ) ) inline void GRRLIB_ClearTex(GRRLIB_texImg* tex) ; void GRRLIB_Compose( int xoff, int yoff, GRRLIB_texImg* layer, GRRLIB_texImg* canvas, GRRLIB_ComposeMode mode ) ; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //============================================================================== /** * Compose a layer/sprite to a canvas/textured-image * Currently only performs "a-over-b (normal) alpha compositing" (opacity) * Ie. Light source is behind the eye, not behind the canvas! * Author : BlueChip * @param xoff : The x-offset within the canvas (negative values allowed) * @param yoff : The y-offset within the canvas (negative values allowed) * @param layer : The layer/sprite to draw * @param canvas : The canvas/textured-image on which to draw * @param mode : Currently unused - will be composition mode */ //============================================================================== void GRRLIB_Compose( int xoff, int yoff, GRRLIB_texImg* layer, GRRLIB_texImg* canvas, GRRLIB_ComposeMode mode ) { int x, y; // x & y on layer int cnv_x, cnv_y; // x & y on canvas float cnv_a, lyr_a, alpha; // Alpha of canvas & layer & result u32 cnv_c, lyr_c; // Colour of pixel from canvas & layer u32 new_r, new_g, new_b, new_a; // R, G, B & A values of result // Loop through the layer, one pixel at a time for (y = 0; y < layer->h; y++) { cnv_y = y +yoff; // y coord of canvas pixel to be changed if (cnv_y < 0) continue ; // not on the canvas yet if (cnv_y >= canvas->h) break; // off the bottom of the canvas for (x = 0; x < layer->w; x++) { cnv_x = x +xoff; // x coord of canvas pixel to be changed if (cnv_x < 0) continue ; // not on the canvas yet if (cnv_x >= canvas->h) break; // off the right of the canvas // Grab the working pixels from the canvas and layer cnv_c = GRRLIB_GetPixelFromtexImg(cnv_x,cnv_y, canvas); lyr_c = GRRLIB_GetPixelFromtexImg(x,y, layer); // Calculate alpha value as 0.0 to 1.0 in 255th's cnv_a = A(cnv_c) /255.0; lyr_a = A(lyr_c) /255.0; // Perform desired composition switch (mode) { default: case GRRLIB_COMPOSE_NORMAL : // Perform "a-over-b (normal) alpha compositing" (opacity) // http://en.wikipedia.org/wiki/Alpha_compositing new_a = (u32)( A(lyr_c) + (A(cnv_c) *(1.0 -lyr_a)) ); alpha = new_a /255.0; new_r = ( (R(lyr_c) *lyr_a) + (R(cnv_c) *cnv_a *(1 -lyr_a)) ) /alpha; new_g = ( (G(lyr_c) *lyr_a) + (G(cnv_c) *cnv_a *(1 -lyr_a)) ) /alpha; new_b = ( (B(lyr_c) *lyr_a) + (B(cnv_c) *cnv_a *(1 -lyr_a)) ) /alpha; break; } // Replace the old canvas pixel with the new one GRRLIB_SetPixelTotexImg( cnv_x,cnv_y, canvas, RGBA(new_r, new_g, new_b, new_a) ); }//for x }// for y GRRLIB_FlushTex(canvas); } //============================================================================== /** * Clear a texture to transparent black * @param tex : Texture to clear */ //============================================================================== inline void GRRLIB_ClearTex(GRRLIB_texImg* tex) { bzero(tex->data, (tex->h *tex->w) <<2); GRRLIB_FlushTex(tex); } //------------------------------------------------------------------------------ // Test Harness /* My testcard PNG's can be found here: 152x152 Blue 70% (0x00`00`FF`B2) - http://imagebin.ca/view/cNIZhp3.html 152x152 Red 50% (0xFF`00`00`7F) - http://imagebin.ca/view/MyJrxj.html ...use raw2c (from devkitpro) to reduce them to .c files PaintShopPro_X2 readings: | | Blue-over-Red | Red-over-Blue | |--------+---------------+---------------| | Normal | 0x2D'00'D2'D8 | 0x96'00'69'D8 | | | | | */ //------------------------------------------------------------------------------ #include "..\gfx\testcards\red50.c" #include "..\gfx\testcards\blue70.c" #include <stdlib.h> // exit #include <wiiuse/wpad.h> #include "grrlib.h" // We will need to check the screen size extern GXRModeObj* rmode; // Another bug in GRRLIB (svn 102) #define LOAD_TEX_ROT0(pGRR, img) do { \ pGRR = GRRLIB_LoadTexture(img); \ pGRR->handlex = 0; \ pGRR->handley = 0; \ } while(0) void test_compose(void) { int redOnTop = 0; // Red square starts behind the blue one // Our two translucent test images GRRLIB_texImg* red = GRRLIB_LoadTexture(red50); GRRLIB_texImg* blu = GRRLIB_LoadTexture(blue70); // The canvas we will be composing on GRRLIB_texImg* cnv = GRRLIB_CreateEmptyTexture(400,400); // Init graphics subsystem GRRLIB_Init(); // Init Wiimote #1 WPAD_Init(); WPAD_SetVRes(0, rmode->fbWidth+200, rmode->xfbHeight+300); WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); // Loop until home key pressed do { // Scan the Wiimote ir_t ir; WPAD_ScanPads(); WPAD_IR(0, &ir); // 'A' toggles z-coord of red sqaure if (WPAD_ButtonsDown(0) & WPAD_BUTTON_A) redOnTop ^= 1 ; // Clear canvas GRRLIB_ClearTex(cnv); bzero(cnv->data, (cnv->h *cnv->w) <<2); GRRLIB_FlushTex(cnv); // Compose canvas if (!redOnTop) GRRLIB_Compose(ir.x-180,ir.y-180, red, cnv, GRRLIB_COMPOSE_NORMAL) ; GRRLIB_Compose(125,125, blu, cnv, GRRLIB_COMPOSE_NORMAL) ; if ( redOnTop) GRRLIB_Compose(ir.x-180,ir.y-180, red, cnv, GRRLIB_COMPOSE_NORMAL) ; // Paint the screen black GRRLIB_FillScreen(0x000000FF); // Draw frame GRRLIB_Rectangle(38,38,404,404,0x808080FF,false); GRRLIB_Rectangle(39,39,402,402,0x808080FF,false); // Draw Test bar GRRLIB_Rectangle(283,50,20,380,0xFFFFFFFF, true); // Draw Composed Canvas GRRLIB_DrawImg(40,40, cnv,0.0, 1.0,1.0, 0xFFFFFFFF); // Test card (alpha performed by Wii) GRRLIB_Rectangle(570,50,20,450,0xFFFFFFFF, true); GRRLIB_DrawImg(450, 65, red,0.0, 1.0,1.0, 0xFFFFFFFF); GRRLIB_DrawImg(450,165, blu,0.0, 1.0,1.0, 0xFFFFFFFF); GRRLIB_DrawImg(450,265, red,0.0, 1.0,1.0, 0xFFFFFFFF); // Draw it [and workaround bug in GRRLIB] GRRLIB_Render(); if (rmode->viTVMode &VI_NON_INTERLACE) VIDEO_WaitVSync() ; } while(!(WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)); // Exit on home key // Clear the frame buffers for next program GRRLIB_FillScreen(0); GRRLIB_Render(); GRRLIB_FillScreen(0); GRRLIB_Render(); // Clear up memory GRRLIB_Exit(); exit(0); } #if 0 // <- change to 1 if you want to compile this as a standalone app int main(int argc, char** argv) { (void)argc; (void)argv; test_compose(); exit(0); } #endif
Offline
branches/libconversion contains this code and a separate example usage
BC
Offline