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);
}
#endifOffline
branches/libconversion contains this code and a separate example usage
BC
Offline