grabpixmap and save with alpha

BlitzMax Forums/BlitzMax Programming/grabpixmap and save with alpha

Pete Rigz(Posted 2008) [#1]
I've been creating a little particle editor and I wanted to add a feature where you can save a animation strip of the effect with all alpha info etc. After searching the forums here for clues I got as far as saving it ok except it's just not quite right, like the image it's saving isn't as opaque as it should be. The below code demonstrates the problem:



Basically that should draw a few ovals grab it as a pixmap then load that as an image and draw it to the right to compare. How it appears on the right is how it saves too and as you should see it's not grabbing the image properly somehow.

Hopefully it's something simple but any ideas would be greatly appreciated!


Dreamora(Posted 2008) [#2]
the backbuffer does not store any alpha.
So it does not make any difference if you draw it with alpha or not for grabbing. it only makes a difference in the color mixing on the backbuffer.

if you need alpha you must operate on pixmaps directly.
There recently has been a thread on that as well that (not sure, so please don't nail me it on it) shows how to enable the alphabuffer beside the backbuffer to render with alpha into it and get information with alpha from it.


Pete Rigz(Posted 2008) [#3]
I think I've seen the post you're referring too and have implemented it already in the post above. I'm calling graphics with GRAPHICS_ALPHABUFFER flag and using a different cls function to set the alpha to 0 when it clears the screen.

If you save the pixmap as a png file and look at it in a paint program it certainly has alpha, just seems like it's too much.


MGE(Posted 2008) [#4]
Remember, what you render onto (a black background) will also affect the alpha saved level. ;)


ImaginaryHuman(Posted 2008) [#5]
The backbuffer DOES have alpha in a 32-bit screen and if asked for, but it's a matter of whether anything you draw puts anything into the screen's alpha channel and how useful that is to you and whether you want to make use of it when you download it to a pixmap. DrawImage doesn't draw to the destination alpha channel, for example, so you can't draw something with it and then expect to grab alpha values from the screen.


Pete Rigz(Posted 2008) [#6]
The background isn't really black though, it's transparent. If you save the pixmap in the program above you'll see that there is no background.

I think I can tell what's happening though, the grabbed pixels alpha will only be a maximum of whatever you set setalpha to. Why this is though I'm not sure, it must be something to do with how glreadpixels is working, I'm hardly an expert on GL tho! Think I'll have to hunt on google a bit more.


Pete Rigz(Posted 2008) [#7]
Right, that's making a bit more sense i think, thanks. Will have to look some more tomorrow getting late now :)


Jake L.(Posted 2008) [#8]
See this for a working OpenGL example. To make this work with DX7, you'll need to alter brl.d3d7max2d (search for GrabPixmap):

change
pixmap=TPixmap.Create( width,height,PF_BGR888 )

to
pixmap=TPixmap.Create( width,height,PF_BGRA8888 )


I made a local GrabPixmapDX7 function (90% copy&paste), so it isn't neccessary to change the original module at all.

Mods: Am I allowed to poste complete code parts from BRL modules here?

EDIT: Though this makes the DX7 version work the same as the GL version, he problem you describe is still existing:(


Pete Rigz(Posted 2008) [#9]
Thanks for posting Jake. I'd seen your other post when I was researching this problem, unfortunately it's still got me stumped. I also posted it on the open GL forum with an example of the same problem happening with klepto's render to texture code here. Good find with the dx version, that explains why clearing the screen with alpha didn't appear to do anything. Interesting that the same problem happens, hopefully solving it for one version will fix it for the other.


Pete Rigz(Posted 2008) [#10]
Very nearly there with this, after googling I found out about glcolormask to draw in 2 passes, colour then alpha, it's not perfect but nearly there, I think maybe there's zbuffer issues, not sure tho:




Pete Rigz(Posted 2008) [#11]
Think I've cracked it, this probably isn't the fastest way to do this but I'm not too worried about that, just that it works. This is just OpenGL version but I'm sure DX shouldn't be too hard to replicate.

Basically I render the scene in 2 passes, one with colormask set to not draw to alpha, the other with alpha. Although if you use lightblend then the first pass needs to be drawn with no color mask, but the second pass should always be alpha only. Then I made 2 new grabpixmap functions, one that grabs colour only and another that grabs alpha. I then merge these pixmaps together dividing each colour in the pixmap by the alpha to restore the colour to its original value.



This example shows how to use alphablend and lightblend in the same scene.