You are not logged in.

#1 2009-07-23 04:44:47

BlueChip
Moderator

Texture Composition

By popular demand, it's nearly 4am and I think I've just got it working ...beta test your little hearts out big_smile

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 wink

Code:

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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

I can be found on efnet, freenode, msn, gtalk, aim, ychat & icq ...PM me for details

Offline

 

#2 2009-07-29 12:03:16

BlueChip
Moderator

Re: Texture Composition

branches/libconversion contains this code and a separate example usage

BC


I can be found on efnet, freenode, msn, gtalk, aim, ychat & icq ...PM me for details

Offline

 

Board footer

Powered by FluxBB