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.
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.
SuperStrict SetGraphicsDriver GLMax2DDriver() Graphics (1000, 500,,,GRAPHICS_ALPHABUFFER) SetClsColor2 0, 0, 0, 0 Cls SeedRnd 0 For Local c:Int = 1 To 50 Local size:Int = Rnd(50, 125) Local x:Int = Rnd(100, 300) Local y:Int = Rnd(100, 300) SetColor Rnd(255), Rnd(255), Rnd(255) ColorMaskColor SetBlend ALPHABLEND SetAlpha.5 DrawOval x, y, size, size SetColor 150, 150, 150 ResetColorMask SetBlend LIGHTBLEND SetAlpha.5 x = Rnd(100, 300) y = Rnd(100, 300) DrawOval x, y, size, size Next SeedRnd 0 ColorMaskAlpha For Local c:Int = 1 To 50 Local size:Int = Rnd(50, 125) Local x:Int = Rnd(100, 300) Local y:Int = Rnd(100, 300) SetColor Rnd(255), Rnd(255), Rnd(255) SetBlendAlphaONE SetAlpha.5 DrawOval x, y, size, size glEnable GL_BLEND glBlendFunc GL_SRC_ALPHA, GL_ONE SetColor 150, 150, 150 SetAlpha.5 x = Rnd(100, 300) y = Rnd(100, 300) DrawOval x, y, size, size Next glColorMask(True, True, True, True) Local pixmapalpha:TPixmap = GrabPixmapAlpha(0, 0, 500, 500) Local pixmapcolor:TPixmap = GrabPixmapColor(0, 0, 500, 500) Local pixmapfinal:TPixmap = mergepixmaps(pixmapalpha, pixmapcolor) SavePixmapPNG(pixmapfinal, "test.png") SetAlpha 1 SetColor 255, 255, 255 SetBlend ALPHABLEND Local testimg:TImage = LoadImage("test.png") DrawImage testimg, 500, 0 Flip WaitKey Function SetClsColor2(red:Float, green:Float, blue:Float, alpha:Float = 255) glClearColor red / 255.0, green / 255.0, blue / 255.0, alpha / 255.0 End Function Function GrabPixmapAlpha:TPixmap(x:Float, y:Float, w:Float, h:Float) Local p:TPixmap = CreatePixmap(w, h, PF_A8) glReadPixels x, GraphicsHeight() - h - y, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, p.pixels p = YFlipPixmap(p) Return ConvertPixmap(p, PF_RGBA8888) End Function Function GrabPixmapColor:TPixmap(x:Float, y:Float, w:Float, h:Float) Local p:TPixmap = CreatePixmap(w, h, PF_RGB888) glReadPixels x, GraphicsHeight() - h - y, w, h, GL_RGB, GL_UNSIGNED_BYTE, p.pixels p = YFlipPixmap(p) Return ConvertPixmap(p, PF_RGBA8888) End Function Function SetBlendAlphaSRC() glEnable GL_BLEND glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDisable GL_ALPHA_TEST End Function Function SetBlendAlphaONE() glEnable GL_BLEND glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) glDisable GL_ALPHA_TEST End Function Function ColorMaskColor() glColorMask(True, True, True, False) End Function Function ColorMaskAlpha() glColorMask(False, False, False, True) End Function Function ResetColorMask() glColorMask(True, True, True, True) End Function Function mergepixmaps:TPixmap(alpha:TPixmap, color:TPixmap) Local p:TPixmap = CreatePixmap(alpha.width, alpha.height, PF_RGBA8888) ClearPixels(p, 0) Local c:Int Local a:Int Local r:Int Local g:Int Local b:Int Local t1:Int For Local x:Int = 0 To alpha.width - 1 For Local y:Int = 0 To alpha.height - 1 a = ReadPixel(alpha, x, y) c = ReadPixel(color, x, y) b = c & $000000FF g = (c & $0000FF00) Shr 8 r = (c & $00FF0000) Shr 16 t1 = (a & $FF000000) Shr 24 If r Then r = Float(r) / (Float(t1) / 255.0) If g Then g = Float(g) / (Float(t1) / 255.0) If b Then b = Float(b) / (Float(t1) / 255.0) WritePixel(p, x, y, b + (g Shl 8) + (r Shl 16) + (t1 Shl 24)) Next Next Return p End Function
This example shows how to use alphablend and lightblend in the same scene.