Pixmaps don't draw alpha?

BlitzMax Forums/BlitzMax Beginners Area/Pixmaps don't draw alpha?

spacerat(Posted 2008) [#1]
So I have started to make a painting program in Blitz using pixmaps, but I quickly came across a problem: pixmaps don't work with alpha.

In this piece of jumble I've put together, the gradient should get more transparent on the right, and more solid on the left. Also, try painting: the brush is solid, but it should be soft.

You can see, on mouse over, that I have encoded the pixels correctly (the first two letters of the hex value are for alpha), yet it doesn't draw correctly. And yes, the format is RGBA8888 and yes, ALPHABLEND is on.

SuperStrict
Framework brl.blitz
Import brl.glmax2d
Import brl.retro
Import brl.polledinput
Import brl.keycodes
Graphics 800, 600
	SetBlend(ALPHABLEND) 
	SetColor(255, 255, 255) 
	SetAlpha(1) 
	SetClsColor(255, 200, 200) 
Global pix:TPixmap = CreatePixmap(256, 256, PF_RGBA8888) 
ClearPixels(pix, $BBBBBBBB) 
For Local xx:Int = 0 To 255
	For Local yy:Int = 0 To 255
		WritePixel(pix, xx, yy, MakeCol(xx, 0, yy, 255)) 
	Next
Next
While Not AppTerminate() 
	Cls
	If MouseX() >= 20 And MouseX() < 276 And MouseY() >= 20 And MouseY() < 276 DrawText(Hex:String(ReadPixel(pix, MouseX() - 20, MouseY() - 20)), 310, 40) 
	If MouseDown(MOUSE_LEFT) DrawBrush() 
	DrawPixmap(pix, 20, 20) 
	
	Flip
Wend

Function MakeCol:Int(a:Byte, r:Byte, g:Byte, b:Byte) 
	Local n:Int
	Local m:Byte ptr = VarPtr n
	m[0] = b
	m[1] = g
	m[2] = r
	m[3] = a
	Return n
EndFunction

Function DrawBrush() 
	Local rx:Int = MouseX() - 20
	Local ry:Int = MouseY() - 20
	For Local aa:Int = 0 To 360 Step 2
		For Local d:Int = 0 To 17
			writepix(pix, rx + Ceil(d * Cos(aa)), ry + Ceil(d * Sin(aa)), MakeCol(Ceil(255 - (255 / 17) * d), 0, 255, 0)) 
		Next
	Next
End Function

Function writepix(pixmap:TPixmap, x:Int, y:Int, argb:Int) 
	If x >= 0 And x < pixmap.width And y >= 0 And y < pixmap.height And pixmap <> Null WritePixel(pixmap, x, y, argb) 
EndFunction



ImaginaryHuman(Posted 2008) [#2]
DrawPixmap transfers pixel data from main memory directly into the backbuffer in video ram. It doesn't do any `blending` whatsoever. It's basically kind of like a `CopyRect` function. You copy existing pixels as-is to a destination as-is. Blending modifies pixels on the fly which does not happen with pixmaps. If you want to blend your pixmap you must convert it to an Image first.


spacerat(Posted 2008) [#3]
Gah, I was afraid you would say something like that. However, I did find a function which does what I described, but it's buggy: GLDrawPixmap. Try replacing my DrawPixmap with it, and you'll see what I mean. You'll also see that my brush idea failed, but I've sorted that out now using http://en.wikipedia.org/wiki/Alpha_compositing that.

With that in mind, if I can't get DrawPixmap to work or GLDrawPixmap to work reliably, how fast would it be to draw the pixmap, alpha blended, pixel by pixel?


Jesse(Posted 2008) [#4]
try drawing your pixmap as image.

local pixmap:tpixmap
.
.
.
image:timage = loadimage(pixmap)


Bremer(Posted 2008) [#5]
How about this way:

SuperStrict
Framework brl.blitz
Import brl.glmax2d
Import brl.retro
Import brl.polledinput
Import brl.keycodes
Graphics 800, 600
	SetBlend(ALPHABLEND) 
	SetColor(255, 255, 255) 
	SetAlpha(1) 
	SetClsColor(255, 200, 200) 
Global img:TImage = CreateImage(256, 256, 0)
Global pix:TPixmap = CreatePixmap(256, 256, PF_RGBA8888) 
ClearPixels(pix, $BBBBBBBB) 
For Local xx:Int = 0 To 255
	For Local yy:Int = 0 To 255
		WritePixel(pix, xx, yy, MakeCol(xx, 0, yy, 255)) 
	Next
Next
img = LoadImage(pix,0)
While Not AppTerminate() 
	Cls
	If MouseX() >= 20 And MouseX() < 276 And MouseY() >= 20 And MouseY() < 276 DrawText(Hex:String(ReadPixel(pix, MouseX() - 20, MouseY() - 20)), 310, 40) 
	If MouseDown(MOUSE_LEFT) DrawBrush() 
	'DrawPixmap(pix, 20, 20) 
	DrawImage(img, 20, 20)
	
	Flip
Wend

Function MakeCol:Int(a:Byte, r:Byte, g:Byte, b:Byte) 
	Local n:Int
	Local m:Byte Ptr = Varptr n
	m[0] = b
	m[1] = g
	m[2] = r
	m[3] = a
	Return n
EndFunction

Function DrawBrush() 
	Local rx:Int = MouseX() - 20
	Local ry:Int = MouseY() - 20
	For Local aa:Int = 0 To 360 Step 2
		For Local d:Int = 0 To 17
			writepix(pix, rx + Ceil(d * Cos(aa)), ry + Ceil(d * Sin(aa)), MakeCol(Ceil(255 - (255 / 17) * d), 0, 255, 0)) 
		Next
	Next
	img = LoadImage(pix,0)
End Function

Function writepix(pixmap:TPixmap, x:Int, y:Int, argb:Int) 
	If x >= 0 And x < pixmap.width And y >= 0 And y < pixmap.height And pixmap <> Null WritePixel(pixmap, x, y, argb) 
EndFunction



spacerat(Posted 2008) [#6]
Damn... I can't believe I didn't notice that. Thanks :D


ImaginaryHuman(Posted 2008) [#7]
I suppose you could GrabPixmap from the backbuffer, do a manual alpha blend with your other pixmap, then DrawPixmap. But Images will be WAY faster to draw.


Grey Alien(Posted 2008) [#8]
I do what Jesse says.