Skip to main content
gamedev.net
🔒 Locked

Alpha Blending using DirectDraw

Started by Wicked Ewok 7 replies 550+ views
Original Post
Wicked Ewok
Wicked Ewok
I noticed that DirectDraw does not support Hardware Alpha Blending using 32bit ARGB mode. Even if it did support that, I think that animating sprites using a 32bit mode is too slow anyhow. How then, are lighting effects/fires etc created via DirectDraw? I''ve created a little snippet of code that performs AlphaBlending on a 16bit surface using the Lock and Unlock methods: //////////////////////////////////////////////////////////// pDDSDest->Lock(rDest,&ddsd,DDLOCK_WAIT,NULL);//surface dest pDDSSrc->Lock(rSrc, &ddsdSrc,DDLOCK_WAIT,NULL); //get pointers to surfaces using DWORD(32bits at a time) DWORD* pDDSColor = (DWORD*) ddsd.lpSurface; DWORD* SrcColor = (DWORD*) ddsdSrc.lpSurface; for(int iY = 0;iY <(int)rSrc->bottom;iY++) { for(int x = 0;x <(int)rSrc->right/2.0f;x++) { //arbitrary joining of the two DWORD pixels *pDDSColor = (DWORD)(*pDDSColor | *SrcColor); SrcColor++; pDDSColor++; } SrcColor = (DWORD*) ((BYTE*) ddsdSrc.lpSurface + ( iY + 1 ) * ddsdSrc.lPitch ); pDDSColor = (DWORD*) ((BYTE*) ddsd.lpSurface + ( iY + 1 ) * ddsd.lPitch ); } //////////////////////////////////////////////////////////// the only problem with this code is that its slow! first of all, if I could process each conversion using something larger than a DWORD(32bits) it can speed up the process tremendously. a) Anyone know how to do that? Next, is there a way to create lighting effects in DIRECTDRAW without AlphaBlends? I made a light animation sprite and blended it into the surface. Well if you have any suggestions or can speed up my code, please reply. Thanks! -=~''''^''''~=-.,_Wicked_,.-=~''''^''''~=-
-=~''^''~=-.,Wicked,.-=~''^''~=-
Wicked Ewok
Wicked Ewok
Sorry for doing the double post guys. Lag said it didn''t work the first time

-=~''''^''''~=-.,_Wicked_,.-=~''''^''''~=-
-=~''^''~=-.,Wicked,.-=~''^''~=-
TV
TV
It is nice to see some information being shared for a change- as most posts are requesting it! (not that that's bad, doods)

Well, it goes without saying... it is never to early to learn to write assembly functions... If you use your compiler to output C code, you can see how CPU unfriendly code (especially loops) can be! Of course, this is relative to the speed of tight assembly code and C in almost all cases.

However, there are several algorithmic changes that should prove a significant speed up...

(1) Ditch the int->float conversions. Here they are not needed. Instead of "/2.0" use a shift right ( >> 1 ).

(2) You can safely unroll this loop 16 times, as all monitor resolutions are evenly divisible by 32. (16 unrolls * 2 pixels per DWORD) The jump (bottom of loop to top) is eliminated by 15 times, which we can declare as "pretty sweet".

(3) I am not sure of how compilers handle this... but postfix increment (variable++) creates a copy of a variable (needed to return 'variable' before it is incremented) while prefix increment (++variable) doesn't create a copy. Even if this copy goes unused, it still adds extra cycles that can be eliminated. (Not sure... anyone know do compilers catch this and swap v++ for ++v, when return not needed?)

(4) Read from non video memory surfaces. A read from video memory is very costly, no matter what anybody says.

(5) Again... learn to write assembly functions!!! You would be surprised of how easy this function is to implement! (And dispite what people say: Learning ASM is not hard nor scary!)

.travois.

Edited by - tv on January 20, 2001 10:42:43 PM
TV
TV
Oh...

and (6) remove the multiplys from your loop. Rather than calculating the offset each time (a) create a lookup table and access it for Y every frame or (b) keep a base pointer and ADD pitch to it every time to find row offsets.

!travois!
Wicked Ewok
Wicked Ewok
wow thanks tv, that''s a lot of info

Not sure what you mean by unrolling it 16 times though..
You mean write this loop 16 times bigger to elimate the jump?

I think in most C++ compilers, y = v++; means that v is stored in y, then the v is incremented by 1, while y = ++v; means that v is first incremented by 1, then the value of v is stored in y.

Assembly requires the code to be chip specific right? I''m running on an AMDK-6..dunno if I want to learn that many commands for each chip to make the program compatible with most cpus.

-=~''''^''''~=-.,_Wicked_,.-=~''''^''''~=-
-=~''^''~=-.,Wicked,.-=~''^''~=-
TV
TV
By "unrolling" loops:

If you look at the execution of your loop at different resolutions, it will always execute in a multiple of 16 times (2 pixels a loop). (The important thing to look at is the horizontal- 320x240x16, 512x384x16, 640x480x16, 800x600x16... all multiples of 32) With this knowledge you can perform 16 DWORDs, or 32 pixels per loop (at 16bpp of course). After you execute the 16 DWORDs operations, then do your jump. This will cut down your loop from X/2 (screen width at 1 DWORDs per loop) to X/32 (screen width at 16 DWORDs per loop).

And about that C++ thing (++V and V++)...

++V returns itself, so it increments itself and returns. (from a function sense)

V++ has to make a copy of itself (which it returns), increment itself, then return the copy. (You can't return original then increment.)

I was just wondering if compilers looked for cases where the return of V++ was not needed and replaced it with ++V. (My doubts that compilers (especially with classes) take this liberty is that functions can be overloaded and ++V and V++ can do completely arbitrary things.)

Hope this clears things up.

.travois.


Edited by - tv on January 22, 2001 12:19:08 AM
Serge K
Serge K
quote:
Original post by TV
I was just wondering if compilers looked for cases where the return of V++ was not needed and replaced it with ++V. (My doubts that compilers (especially with classes) take this liberty is that functions can be overloaded and ++V and V++ can do completely arbitrary things.)



You''ll be surprized..
Good compiler don''t give a shit about overloading, classes, etc.
It will optimize everything.
(in case of VC - everything except asm. VC for Alpha can do even more - its back-end optimizer makes no difference between its own code and inline asm.)

About "My doubts that compilers (especially with classes) take this liberty..." - it don''t have to. You see - compiler know it exactly, it have to compile this code after all... It''s what compilers are made for.
TV
TV
Actually, I am not surprised...

If you use your compiler to output in asm from C++, you can easily find much room for improvement. For one, compilers aren''t so hot keeping both pipes executing in Pentium optimizations-- but this is way down on the list on the compiler blues.

And compilers would NEVER substitute a pre-increment method for a post-increment method in a class. As I said, they could do arbitrary things; ++object could increase an internal counter, while object++ could save all objects to disk and return the size of the file written. I don''t know why someone would write methods to do that, but you can, and thats why compilers never would perform that swap. (And compilers are not going to compare the two methods and determine if they are swappable; maybe one of Batman''s (60''s Batman) computers could do it...)

It is from that reasoning that I wondered if integers swapped V++ with ++V (when return goes unused); however, those can be overloaded (am I right?) so they would then be unswappable. (What if ++int was overloaded to increase int by 4?)

I am curious as to this ++int and int++ deal, so I will investigate it...

Never place all bets on your compiler... they will never produce code at fast as it could be (At least in non trivial operations).

Don''t get me wrong, compilers are wonderful tools; but they are not miracle workers-- thats what your brain and assembly language are for. (Can you tell I take all Michael Abrash writings to heart? ha!)

Thanks for reading...

.travois.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.