• ### What is your GameDev Story?

#### Archived

This topic is now archived and is closed to further replies.

# Fast and dirty opacity algorithm (check it out :)

This topic is 6544 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey all, Been working on alpha/opacity rendering on 2d surfaces. I read a bunch of articles by different people on how to do it and then decided "to hell with it, lemme try this." It''s not exactly an accurate opacity generator, but it''s darned close. Light areas tend to get lighter and any black (0x000000) areas totally disappear. Anyways, give me your opinions and if you see any optimiziations I''d be more than interested in it. I should mention that the algorithm also covers sizing, thus there''s a few "extra" variables in it. I''m not overly concerned about the sizing part of it right now, that part has been only minimally optimized.
srcDD.lPitch >>= 2;
destDD.lPitch >>= 2;
destRaw += destDD.lPitch * p.y + p.x;
srcRaw = (DWORD*)srcDD.lpSurface;

for (indexYd = 0, indexYs = 0; indexYd < bHeight; indexYd++, indexYs += advGfxY)
{
for (indexXs = 0; indexXs < bWidth; indexXs += advGfxX)
{
srcVal = srcRaw[(int)indexXs];
*destRaw |= (lookup[(BYTE)(srcVal    )]    ) |
(lookup[(BYTE)(srcVal>>=8)]<<8 ) |
(lookup[(BYTE)(srcVal>> 8)]<<16);
destRaw++;
}
destRaw += dpitch;
tempY = (int)indexYs;
if (tempY)
{
srcRaw += spitch * tempY;
indexYs -= tempY;
}
}

An explanation... most of you won''t need this, but here it is anyways. Resets the pitch to the size of a DWORD instead of unsigned char.
srcDD.lPitch >>= 2;
destDD.lPitch >>= 2;

Set start points for each graphic.
destRaw += destDD.lPitch * p.y + p.x;
srcRaw = (DWORD*)srcDD.lpSurface;

Loop through the height of the graphic (bHeight). (int)indexYd is a destination pixel counter whereas (float) indexYs is the source index counter. advGfxY is a float which specifies how far ahead each iteration should move in the y direction.
for (indexYd = 0, indexYs = 0; indexYd < bHeight; indexYd++, indexYs += advGfxY)
{

Basically, this is a standard pixel copy. The difference is, since we''re doing opacity, we''ll OR the original with a lookup value of the source. The lookup value is a 256 byte array and is set beforehand (when they set the opacity of a sprite) with the calculation: lookup[index] = (BYTE)(opacity * index); opacity is a value ranging from 0.0f to 0.99f. Opacities outside of this range are handled a touch differently (opacity is ignored )
  for (indexXs = 0; indexXs < bWidth; indexXs += advGfxX)
{
srcVal = srcRaw[(int)indexXs];
*destRaw |= (lookup[(BYTE)(srcVal    )]    ) |
(lookup[(BYTE)(srcVal>>=8)]<<8 ) |
(lookup[(BYTE)(srcVal>> 8)]<<16);
destRaw++;
}

Here, we advance the destination raw by dpitch, which is simply (destDD.lPitch - graphic width). Then, we check to see if we need to advance the source Y. The only case in which we shouldn''t advance is if the graphic is being stretched on the Y axis. I haven''t put a whole lot of thought into this part of it yet. It works though.
  destRaw += dpitch;
tempY = (int)indexYs;
if (tempY)
{
srcRaw += spitch * tempY;
indexYs -= tempY;
}
}

Anyways, if you guys could give me your opinions, I''d greatly appreciate it. Any optimizations are welcome (even assembly, muhaha!) I''ve got a feeling that some background colors combined with some foreground colors will produce "interesting" results, but I haven''t had time to test this all out yet. Thanks! --- Wait, you mean I have to actually... THINK?!

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 10
• 11
• 13
• 9
• 11
• ### Forum Statistics

• Total Topics
634089
• Total Posts
3015460
×