// source_ptr is pointer what u get when u lock the surface
// back_buffer is ur back buffers pointer
// both types are USHORT*
// back_lpitch
// lpitch
// are memory pitches
int spixe; // use these to locate pixels, note that two is needed becose lpitch can be difrend
int dpixe;
USHORT alpha = 50; // 50% transparency, use 0-100
USHORT nalpha = 100 - alpha; // reverse value of alpha
USHORT sr,sg,sb; // source colors
USHORT dr,dg,db; // destination colors
int x2=0; // needed second loop values becose destination can be used
int y2=0;
for(int y = des_y; y < (des_y+height); y++)
{
for(int x = des_x; x < (des_x+width); x++)
{
spixe = (x2 + y2 * lpitch);
dpixe = (x + y * back_lpitch);
if(source_ptr[spixe]==0) {x2++; continue;} // dont draw black
// extract...
sr = ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwRBitMask) >> 8) | ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwRBitMask) >> 13);
sg = ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwGBitMask) >> 3) | ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwGBitMask) >> 8);
sb = ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwBBitMask) << 3) | ((source_ptr[spixe] & ddsd2.ddpfPixelFormat.dwBBitMask) >> 2);
dr = ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwRBitMask) >> 8) | ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwRBitMask) >> 13);
dg = ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwGBitMask) >> 3) | ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwGBitMask) >> 8);
db = ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwBBitMask) << 3) | ((back_buffer[dpixe] & ddsd2.ddpfPixelFormat.dwBBitMask) >> 2);
// ...compress
back_buffer[dpixe] = RGB16(
(PercentOf(sr,nalpha) + PercentOf(dr,alpha)),
(PercentOf(sg,nalpha) + PercentOf(dg,alpha)),
(PercentOf(sb,nalpha) + PercentOf(db,alpha)) );
x2++;
}
x2=0;
y2++;
}
#define RGB16(red, green, blue) ( ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3))
int PercentOf(int val,int cto)
{
return((cto/100)*val);
}
🔒 Locked
Alpha color code
Advertisement
Original Post
I got my alpha blitter done and becose i have got a lotof help here in gamedev i though i should share this code.
i didnt pass the whole function here becose there was some of my own stuff, so there might be some typos in this code becose i had to modify it roughly.
This works in 16bit mode.
Btw theres slight error in the pixel value extracting, but its so minor it doesnt count.
So feedback is welcome, like optimazing, bug fixing, yada yada u suck man, and so on.
i havent thinked about the speed much at this point but i think its pretty fast...
The (y2 * lpitch) and (y * back_lpitch) components of those calculations should be moved outside the ''x'' loop as they don''t change. (They''re a type of loop invariants.) This may give you a small speed increase.
Also, PercentOf is bugged. With the code you give there, there''s no way that it can ever return a value other than zero. If you divide an integer by a larger integer, you always get zero. You need to reorder the expression so that you do the multiplication first.
[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]
Also, PercentOf is bugged. With the code you give there, there''s no way that it can ever return a value other than zero. If you divide an integer by a larger integer, you always get zero. You need to reorder the expression so that you do the multiplication first.
[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]
quote:
Original post by Kylotan
The (y2 * lpitch) and (y * back_lpitch) components of those calculations should be moved outside the ''x'' loop as they don''t change. (They''re a type of loop invariants.) This may give you a small speed increase.
Good idea, i do that.
quote:
Also, PercentOf is bugged. With the code you give there, there''s no way that it can ever return a value other than zero. If you divide an integer by a larger integer, you always get zero. You need to reorder the expression so that you do the multiplication first.
Do u mean if i use it like this: PercentOf(30,110) then the result is bad?
Alright first of all the way you extract you color elements r,g and b has me a little confused.
I always though you could extract the element by first masking off bits unrelated to its bit field then shifting the bits over to the data''s zero bit position.
Extracting Elements from 565 pixel format.
red = pixel >> 11; // don''t need to mask the shift will remove the unwanted bits
green = (pixel & greenmask) >> 5;
blue = pixel & bluemask // don''t need to shift because field is aready at zero position
Second you could use lookup tables to determine the weight values for blending the elements.
5 bit field Weight table (e is element, w is weight)
for(e=0;e<32;e++)
for(w=0;w<32;w++)
Weight5[e][w] = e / w;
6 bit field Weight table
for(e=0;e<64;e++)
for(w=0;w<64;w++)
Weight6[e][w] = e / w;
**Note: Make these lookup tables global to this function so you only have to create them once and don''t have to pass them into the function.
Convert 100 to weight for 5 bit field
w = (percent * 31)/31
Convert 100 to weight for 6 bit field
w = (percent * 63)/63
calculate weights (outside of rendering loops)
sw5 = (percent * 31)/31
dw5 = 31 - sw5; // invert destination blend weight according to source blend weight
sw6 = (percent * 63)/63
dw6 = 63 - sw5; // invert destination blend weight according to source blend weight
Blending the values would look like this (br is blended red, etc..)
br = Weight5[sr][sw5] + Weight5[dr][dw5];
bg = Weight6[sg][sw6] + Weight6[dg][dw6];
bb = Weight5[sb][sw5] + Weight5[db][dw5];
Construct the pixel
pixel = (br << 11) + (bg << 5) + bb;
I hope this helps you out a little!
Please give me a little feedback by posting any problems.
I always though you could extract the element by first masking off bits unrelated to its bit field then shifting the bits over to the data''s zero bit position.
Extracting Elements from 565 pixel format.
red = pixel >> 11; // don''t need to mask the shift will remove the unwanted bits
green = (pixel & greenmask) >> 5;
blue = pixel & bluemask // don''t need to shift because field is aready at zero position
Second you could use lookup tables to determine the weight values for blending the elements.
5 bit field Weight table (e is element, w is weight)
for(e=0;e<32;e++)
for(w=0;w<32;w++)
Weight5[e][w] = e / w;
6 bit field Weight table
for(e=0;e<64;e++)
for(w=0;w<64;w++)
Weight6[e][w] = e / w;
**Note: Make these lookup tables global to this function so you only have to create them once and don''t have to pass them into the function.
Convert 100 to weight for 5 bit field
w = (percent * 31)/31
Convert 100 to weight for 6 bit field
w = (percent * 63)/63
calculate weights (outside of rendering loops)
sw5 = (percent * 31)/31
dw5 = 31 - sw5; // invert destination blend weight according to source blend weight
sw6 = (percent * 63)/63
dw6 = 63 - sw5; // invert destination blend weight according to source blend weight
Blending the values would look like this (br is blended red, etc..)
br = Weight5[sr][sw5] + Weight5[dr][dw5];
bg = Weight6[sg][sw6] + Weight6[dg][dw6];
bb = Weight5[sb][sw5] + Weight5[db][dw5];
Construct the pixel
pixel = (br << 11) + (bg << 5) + bb;
I hope this helps you out a little!
Please give me a little feedback by posting any problems.
Cool, I just saw a bug in my logic!!
You can't divide by zero so w in the lookup table construction will have to change.
5 bit field Weight table (e is element, w is weight)
for(e=0;e<32;e++)
for(w=0;w<32;w++)
{if(w!=0){Weight5[e][w] = e / w;}
else {Weight5[e][w] = 0;}
}
6 bit field Weight table
for(e=0;e<64;e++)
for(w=0;w<64;w++)
{if(w!=0){Weight6[e][w] = e / w;}
else {Weight6[e][w] = 0;}
}
And another detail! The percent of blend should effect the source not the destination. Sorry had it backwards.
calculate weights (outside of rendering loops)
dw5 = (percent * 31)/31
sw5 = 31 - dw5; // invert source blend weight according to destination blend weight
dw6 = (percent * 63)/63
sw6 = 63 - dw5; // invert source blend weight according to destination blend weight
Damn it! That should work now???
[edited by - CodeJunkie on October 25, 2002 9:55:47 PM]
You can't divide by zero so w in the lookup table construction will have to change.
5 bit field Weight table (e is element, w is weight)
for(e=0;e<32;e++)
for(w=0;w<32;w++)
{if(w!=0){Weight5[e][w] = e / w;}
else {Weight5[e][w] = 0;}
}
6 bit field Weight table
for(e=0;e<64;e++)
for(w=0;w<64;w++)
{if(w!=0){Weight6[e][w] = e / w;}
else {Weight6[e][w] = 0;}
}
And another detail! The percent of blend should effect the source not the destination. Sorry had it backwards.
calculate weights (outside of rendering loops)
dw5 = (percent * 31)/31
sw5 = 31 - dw5; // invert source blend weight according to destination blend weight
dw6 = (percent * 63)/63
sw6 = 63 - dw5; // invert source blend weight according to destination blend weight
Damn it! That should work now???
[edited by - CodeJunkie on October 25, 2002 9:55:47 PM]
Good lord nobody has caught this one yet!!
Fine that gives me the chance to correct it.
to convert percentage to the correct weigth you mulity by the largest weight then divide by the largest percentage
w = (percent * 31)/100 not w = (percent *31)/31
calculate weights (outside of rendering loops)
dw5 = (percent * 31)/100 // ***was wrong***
sw5 = 31 - dw5; // invert source blend weight according to destination blend weight
dw6 = (percent * 63)/100 // ***was wrong***
sw6 = 63 - dw5; // invert source blend weight according to destination blend weight
Wow I''m really rusty.
Thanks for not picking on me!!
Fine that gives me the chance to correct it.
to convert percentage to the correct weigth you mulity by the largest weight then divide by the largest percentage
w = (percent * 31)/100 not w = (percent *31)/31
calculate weights (outside of rendering loops)
dw5 = (percent * 31)/100 // ***was wrong***
sw5 = 31 - dw5; // invert source blend weight according to destination blend weight
dw6 = (percent * 63)/100 // ***was wrong***
sw6 = 63 - dw5; // invert source blend weight according to destination blend weight
Wow I''m really rusty.
Thanks for not picking on me!!
Okay after all the screw ups here is a little code for a pixel alpha blender to give people an understanding of what I'm trying to do...
Yes the code is not complete. I slapped it together to show how implementing it might look.
(hopefully it's not buggy)
Sorry for all the posts but I had fun making them!
And no this won't render a bitmap but it gives a great start on doing so. I don't want to have all the fun. Good luck!!
P.S. - Make sure not to read from vram that will slow you down if you use the alpha blending alot! Use system ram to render to then fastblt that to your backbuffer to get ready to display.
[edited by - CodeJunkie on October 26, 2002 2:04:38 AM]
[edited by - CodeJunkie on October 26, 2002 2:29:45 AM]
[edited by - CodeJunkie on October 26, 2002 4:44:02 AM]
Yes the code is not complete. I slapped it together to show how implementing it might look.
(hopefully it's not buggy)
////////////////////////////////////////////////////////////////
// Globals
BYTE Weight5[32][32];
BYTE Weight6[64][64];
////////////////////////////////////////////////////////////////
// Function Declarations
// Important Initialization Functions
void InitAlphaBlendTables();
// Graphics Primitives
void Blend565Pixel(int x ,int y, WORD clr, int percent, WORD *vbuffer, unsigned long pitch);
////////////////////////////////////////////////////////////////
// Function Definitions
// InitAlphaBlendTables
// purpose: generates lookup tables used for alpha blending pixels
// Input: Special(warning evil globals) Weight5, and Weight6 arrays
// Output: Arrays are correctly Initialized
void InitAlphaBlendTables()
{
int e,w;
// Fill Weight 5 table
for(e=0;e<32;e++)
for(w=0;w<32;w++)
{if(w!=0){Weight5[e][w] = e /w;}
else{Weight5[e][w] = 0;}
}
// Fill Weight 6 table
for(e=0;e<64;e++)
for(w=0;w<64;w++)
{if(w!=0){Weight6[e][w] = e /w;}
else{Weight6[e][w] = 0;}
}
// end of InitAlphaBlendTables
}
// Blend565Pixel
// purpose: blends a pixel onto it destination pixel
// input:
// output:
void Blend565Pixel(int x ,int y, WORD clr, int percent, WORD *vbuffer, unsigned long pitch)
{
BYTE sr,sg,sb,dr,dg,db,br,bg,bb;
BYTE dw5,sw5,dw6,sw6;
WORD *pixel;
// Data Validation tests
// Percent range (1-100)
if(percent<1){return;}// pixel is invisible so return}
if(percent>100)percent = 100;
// Clipping
// if clipping failed then return
// if clipping passed calculate pixel's destination address
pixel = &vbuffer[(y*(pitch>>1))+ x];
// calculate weights
dw5 = (percent * 31)/100;
sw5 = 31 - dw5; // invert destination blend weight according to source blend weight
dw6 = (percent * 63)/100;
sw6 = 63 - dw5; // invert destination blend weight according to source blend weight
// Extract Color elements
sr = clr >> 11;
sg = (clr & 0x07e0) >> 5; // not sure if masks are correct?
sb = clr & 0x001f;
dr = *pixel >> 11;
dg = (*pixel & 0x07e0) >> 5;
db = *pixel & 0x001f;
// Blending the values
br = Weight5[sr][sw5] + Weight5[dr][dw5];
bg = Weight6[sg][sw6] + Weight6[dg][dw6];
bb = Weight5[sb][sw5] + Weight5[db][dw5];
//Construct and plot the pixel
*pixel = (br << 11) + (bg << 5) + bb;
// End of Blend565Pixel
return;
}
Sorry for all the posts but I had fun making them!
And no this won't render a bitmap but it gives a great start on doing so. I don't want to have all the fun. Good luck!!
P.S. - Make sure not to read from vram that will slow you down if you use the alpha blending alot! Use system ram to render to then fastblt that to your backbuffer to get ready to display.
[edited by - CodeJunkie on October 26, 2002 2:04:38 AM]
[edited by - CodeJunkie on October 26, 2002 2:29:45 AM]
[edited by - CodeJunkie on October 26, 2002 4:44:02 AM]
Well it doesn''t make 6 function calls per pixel for one, the extraction should be a little quicker and pixel construction.
I guess it would be 3 to 6 times faster.(don''t hold me to that)
However, the best thing to do would be to use mmx for the quickest results. Sorry, I can''t help in that direction.
Good Luck.
P.S. If you discover some really neat hack for blending please share it.
I guess it would be 3 to 6 times faster.(don''t hold me to that)
However, the best thing to do would be to use mmx for the quickest results. Sorry, I can''t help in that direction.
Good Luck.
P.S. If you discover some really neat hack for blending please share it.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement