take a look at this project....
i want the smoke puffs to be drawn half transparent...
it looks like the blitting is drawn with less than 32-bit colors
Printable View
take a look at this project....
i want the smoke puffs to be drawn half transparent...
it looks like the blitting is drawn with less than 32-bit colors
oh! forgot to attach!
By half Tranparent do you mean Alpha BlendinG?
Yes, he means alpha-blending. From what I hear, alpha-blending is very slow with the current API's such as AlphaBlend and TransparentBlt in big projects, though I'm really not sure because I haven't used them in a larger project -- such as a game. You should check out these links:
http://www.allapi.net/apilist/AlphaBlend.shtml
http://www.allapi.net/apilist/GdiTransparentBlt.shtml
http://www.allapi.net/apilist/TransparentBlt.shtml
i want to blend some parts in the pic more than other parts....
i could use get/setpixel but that would be too slow...
Hi - you can use AlphaBlend in one of two ways - the first is that you can use it to make the entire inmage uniformly transparent. This is relatively widely documented on the internet.
You can also use it to make only parts of an image transparent. This is very complicated -- you have to make a 32-bit bitmap, set the transparency, etc...
I figured out how to do this a while ago, and am attaching a converter I made. This was for a game project that has now been converted to directx.
Essentially, this program will load a .tga file, display it, and output it to its own file format (essentially the raw bitmap data with some other stuff thrown in).
Notes: the .tga file you load should be a 32-bit .tga with an alpha channel. Also, my program works reasonably well under windows 2k and xp. It will work on win9x as well, but if I remember correctly I had all sorts of problems getting alphablend to work with win9x.
OK - hope this helps
BM
ps. It's been a while since I've looked at this code, but I'd be glad to answer any questions you might have...
i already know how to make a mask that makes the bitblt only draw some parts....but i want some of the parts in the face to be drawn blended - some parts drawn 100%, some 0% and some 10%, 20% etc...
its seems possible with bitblt the way i made it...i made the face all black and the mask in gradient with white outside and grey inside...this should make the program draw the inner part about 50% of the face (50% black, 50% of the bg) and the outer part 0% (only bg)....and it does....the problem is in between this..where it should draw many different colors where it only draws some of them.....take a look at the program and see for yourself....compare the mask with the finished image!
Hi- an image's alpha channel lets you define how transparent parts of the image should be. AlphaBlend will blend an image with a source image based upon the image's alpha channel. if an alpha pixel is set to a value of 128 (50%) then alphablend will draw the corresponding color channel pixel with an opacity of 50%. You can set some of an image's alpha pixels to 20%, some to 50%, etc...
To illustrate this, I've combined parts of my code with your code. The result (at least codewise) is not pretty, but it shows the difference.
Alpha Blend:
http://php.indiana.edu/~bmoberly/GameDev/ablt.gif
TransBlt:
http://php.indiana.edu/~bmoberly/GameDev/tblt.gif
I changed the color of your picture2 to blue, and I think that this has exasperated the effect that you were originally seeing.
If you select the alphablend option, then the program draws a bitmap loaded from a tga file -- this tga file has an alpha channel.
I'm uploading the new project -- see if it works. Again - the code is not pretty. My goal was to illustrate alphablend quickly using your code, not to optimize it for readability, etc...
BM
thank you!
i'll look into that after school today!
Is it fast, though? Unfortunately, most methods are painfully slow =(
that was really nice...i changed some things and i think it looks really good! hehe :)
is there any way to draw it faster? (no dx or ogl)
Hi - I see what you mean; on one of my work machines (the really nice one), your program runs very fast and your program looks really good (I've been making smoke rings all afternoon), but on my other work machine, the performance is really slow.
Now I'm remembering why I switched to directx...
I can only give you some general suggestions -- I think the alphablnd api is slower than bitblt, and there aren't very many ways around this unless you can write your own alpha blending routine in .asm. This is beyond me, though...
Since I can't say directx or opengl, can I say GDI+ -- .net will let you use GDI+ and it is supposed to be a lot more optimized than regular windows gdi.
Other suggestions-
1) limit the size of your points -- smaller ones will render faster
2) I notice you repeat a lot a math where you could substitute a constant or at least a value stored in a variable.
For example, in your drawparticles routine, you say TGAHeader.width / 2 and tgaheader.height / 2 -- since you have to do this calculation over and over and it doesn't change, you should calculate this in advance in assign it to a variable. This way you only have to do the calculation once...
For example, this is how I would revise your drawparticles routine:
VB Code:
Public Sub DrawParticles(ByVal TarDC As Long, ByVal SrcDC1 As Long) Dim i As Long Dim successvar As Long Dim nXOffset As Long Dim nYoffset As Long Dim nWidth As Long Dim nHeight As Long Dim bUseTransBlend As Boolean nXOffset = TGAHeader.width * 0.5 - 1 nYoffset = TGAHeader.height * 0.5 - 1 nWidth = TGAHeader.width - 1 nHeight = TGAHeader.height - 1 bUseTransBlend = Form1.Option1(0).Value If Not bUseTransBlend Then For i = 0 To ParticleCount successvar = AlphaBlend(TarDC, Particle(i).x - nXOffset, Particle(i).y - nYoffset, nWidth, nHeight, SrcDC1, 0, 0, nWidth, nHeight, blendlng) Next Else For i = 0 To ParticleCount TransBlt Form1.Picture2.hdc, 0, 0, Form1.Picture3.hdc, 0, 0, TarDC, Particle(i).x, Particle(i).y, Form1.Picture2.ScaleWidth, Form1.Picture2.ScaleHeight Next End If End Sub
What I've done is taken all of the things that you have to compute every frame and computed them at the start of the routine. I've also taken the if test outside of the loop (why test for this every rendering pass -- I think I put this in originally - oops).
This is esp. important to do when you do Sin... calculations -- for example, sin(.02) or sin(.03) will always be the same value, so calculate them once rather than over and over... I've read that Sin, etc... operations can be really slow.
The same holds true for expressions like pi/180 -- this will always be the same value, so assign it to a constant or variable...
I was thinking you might implement lookup arrays in your particle tick routine. This would involve you're having to round your angles to integer values, but what if you were to make two arrays:
AngleSinLookup(359)
AngleCosLookup(359)
and fill them with the appropriate values when your program starts:
AngleSinLookup(0) = Sin((180 - 0)
AngleSinLookup(1) = Sin((180 - 1)
AngleSinLookup(2) = Sin((180 - 2)
etc...
Then you could just say AngleSinLookup(.angle) and not have to do the Sin and Cos calculations every time. Here again, if you were just doing 5 calculations, this would not be such a big deal, but since you're doing 500-1000 each frame...
Alternatively (and if I'm reading your particletick routine right), you might consider doing your sin and cos calculations in your particleblow routine (you could still use a lookup array here) and storing them as part of the particle structure -- it doesn't look like your angles change outside of particle blow, so why recompute them every frame... Just make two new members of your particle structure and fill them in particleblow like this:
.AngleSin = Sin((180 - .Angle) * (Pi / 180))
.AngleCos = Cos((180 - .Angle) * (Pi / 180))
Then in particletick say this:
.x = .x + .AngleSin * .Speed
.y = .y + .AngleCos * .Speed
3) since you are dealing with so many particles, maybe you could implement some sort of culling. You could definitely use the intersectrect api routines to see if a particle falls within picture1 -- if not, you should not render it. Testing for visibility, etc... will introduce more complexity into your draw particles routine, but if, as I suspect, the slowdown is caused by the alphablnd api, it might be faster to cull out, and not draw primitives that aren't visible.
4) only redraw when you have to or maybe not so much - I notice that you're redrawing every twenty milliseconds - what if you only redrew once every third time you reset your particles? The movement might not be that smooth, but it could speed things up a little.
5) consider combining your particletick and your drawparticles into one routine. With the current structure of your program, you do 500-1000 calculations and then do 500-1000 more draws. Why not draw after you calculate?
For example:
VB Code:
Dim i As Long Dim successvar As Long Dim nXOffset As Long Dim nYoffset As Long Dim nWidth As Long Dim nHeight As Long Dim nSin03 As Single nXOffset = TGAHeader.width * 0.5 - 1 nYoffset = TGAHeader.height * 0.5 - 1 nWidth = TGAHeader.width - 1 nHeight = TGAHeader.height - 1 nSin03 = Sin(0.03) For i = 0 To ParticleCount With Particle(i) If .Speed < 0.0001 Then .Speed = 0 Else .x = .x + .AngleSin * .Speed .y = .y + .AngleCos * .Speed .Speed = .Speed - nSin03 * .StartSpeed End If successvar = AlphaBlend(tardc, .x - nXOffset, .y - nYoffset, nWidth, nHeight, srcDc, 0, 0, nWidth, nHeight, blendlng) End With Next i
Note that if you do this, then suggestion #4 gets a little harder to implement. Also, I changed your if test a little, so you don't do any calculations if the particle has no speed...
OK - that's about it -- I didn't mean to go on for this long. No, you can't optimize the alphablend api, but you can optimize the things you're doing between calls to alphablend.
Good luck -
BM
There is quite a fast way to do this, but it requires a bit of setup. I'll see if I can't fish it out... On my old computer (celly 533), you could get 10fps 800x600 doing ANY pixel manipulation, and this was in the IDE. I can only assume that when you optimise it more (it was creating a handle every single time it blitted, removing this could speed it up 200%) and have it outside of the IDE, you could easily get a fluid 30fps compiled. Of course, for smaller things, it's going to go a lot faster.
Just a second.
Here you are... it reports sub-millisecond render times (64x64 picture, XP 2000+), in the IDE.
Good luck! =)
Okay, just a little update; it actually is reporting in seconds, not milliseconds. Sorry about that =)
Hi - wow...
cyborg, you should consider adding this to your program and seeing how it performs.
Thanks-
BM
Like I said, it's quite hard to setup correctly, so you should back up your project first.
By the way:
12.4 ms in IDE,
1.1 ms compiled.
thanks alot bmoberly!
i'll try to do as many speedups as possible....there's just one problem...
if i use many particles, its only slow in the BlowParticles routine....
when blowing alot i can see that the framerate lowers alot until i stop blowing.
Sastraxi, i cant get your program to run....
i get subscript out of range in this line:
ReDim Preserve myBitUDT.hPic(0 To (.biWidth * .biHeight) - 1)
That's cause you're not running my program, are you.
Set AutoRedraw to true on the picboxes.
wow!
i changed so it shows fps instead.
i got 61114 fps!
can that be correct?
is it that fast?
this is how the code looks: lblTimer.Caption = Round(1 / (myTimer.RetTime / 1000))
why cant i cls the pic before i AlphaBltFast to it?
I actually had the same problem with the program -- instead of getting the bitmap handle from the api, I had to fill the pSrc, etc... structure with the .hdc value of the picture box and the .handle value of the picturebox's picture. Alternatively, you can just set the width and the height values manually instead of getting them from the api function (sorry my specific memory of the function is not that good).
About cls - if I understand how the alphafast stuff works, it writes values directly to the device context -- instead of cls'ing, maybe you could just clear the values in the device context?
BM
sTime returns seconds =P ;)
I don't know why its not working for you guys - I'll search around and see what I can come up with for you =)
the line that shows the elapsed time:
lblTimer.Caption = "Timer reads " & CStr(myTimer.RetTime) & "ms"
doesnt "ms" mean milliseconds?
thanks for your help!
If you read a few posts up, I apologised for incorrectly stating that it was in ms.
By the way... it's a lot faster compiled with MMX optimisation ;)
oh...sorry that i didnt read that....
i tried to add this to my program but it gets alot (!) slower if i draw like 2-3 of them!
Then take out the bits2dc call at the end, and call it yourself when everything is done. Should speed it up a lot =)
... Can't sleep either? :(
I updated the sub that I mentioned I made, so that it will work when a shift color sub is called.
Paste this in InitStuff to see how one might program the alpha channel
Dim DrawX&
Dim DrawY&
Dim x1!
Dim y1!
Dim slope_x!
Dim slope_y!
Dim Brightness&
Dim BrushHeight&
BrushHeight = 1000
slope_x = BrushHeight / ShipSprite.halfW
slope_y = BrushHeight / ShipSprite.halfH
y1 = -BrushHeight
For DrawY = 0 To ShipSprite.TopRight.Y
x1 = -BrushHeight
For DrawX = 0 To ShipSprite.TopRight.X
Brightness = BrushHeight - Sqr(x1 * x1 + y1 * y1)
If Brightness < 0 Then Brightness = 0
If Brightness > 255 Then Brightness = 255
ShipSprite.Dib(DrawX, DrawY).Alpha = Brightness
x1 = x1 + slope_x
Next DrawX
y1 = y1 + slope_y
Next DrawY
CyborgBlit TileSurf, ShipSprite, 80, 80
Sastraxi: i just went to bed after that post :p
dafhi: damn, thats a fast engine! i got 40 fps in it!
i see that youre using the AnimSurf2D stuff that you showed me another time!
i'll look into the code later today...