Code archives/3D Graphics - Misc/OptimizeAlphaChannel

This code has been declared by its author to be Public Domain code.

Download source code

OptimizeAlphaChannel by jfk EO-111102006
Masked Textures require the transparent pixes to be black. Due to texture filtering the edges of the transparent areas will show black bleeding artefacts. This function will determine the average RGB of the surrounding pixels and use that color instead, while setting the alpha channel to zero.

This is especially needed with plants textures that are using flag 4.
Graphics3D 640,480,32,2
SetBuffer BackBuffer()

;this array is used by the OptimizeAlphaChannel function!
Dim tex_memory(0,0)


; create a simple test scene:
camera=CreateCamera()
CameraClsColor camera,127,127,127
TranslateEntity camera,0,0,-2.5
light=CreateLight()
RotateEntity light,45,45,0

cube=CreateCube()
EntityFX cube,16


; create a test texture
s=128
tex=CreateTexture(s,s,4)
SetBuffer TextureBuffer(tex)
For i=0 To 25
 Color Rand(255),Rand(255),Rand(255)
 Oval Rand(-25,s+25),Rand(-25,s+25),25,25,1
Next
SetBuffer BackBuffer()
EntityTexture cube,tex



; *** compare these two ways of masking the texture: ***

;SetMaskChannel(tex)        ; standard method, also used by Loading with flag 4
OptimizeAlphaChannel(tex)   ; optimized method, paint edges with neighbour colors to 
                            ; prevent fade-To-black edges

;(you may also skip both functions to see how the texture is unmasked after painting to it: 
;although created with flag 4, after painting to it the alpha channel is set to <>zero (aka opaque))



; test loop
While KeyDown(1)=0
 TurnEntity cube,.1,.2,.3
 RenderWorld()
 Flip
Wend
End




Function SetMaskChannel(tex)
 ;this function will set the alpha channel of black pixels to be fully transparent 
 ;(as required by masked textures using flag 4).
 Local w,h,rgb,r,g,b,x,y,x2,y2,count,average_rgb
 w=TextureWidth(tex)
 h=TextureHeight(tex)
 Dim tex_memory(w,h)
 SetBuffer TextureBuffer(tex)
 LockBuffer()
 For y=0 To h-1
  For x=0 To w-1
   rgb=ReadPixelFast(x,y) And $FFFFFF
   If rgb=0 Then
    WritePixelFast x,y,0
   Else
   EndIf
  Next
 Next
 UnlockBuffer()
 SetBuffer BackBuffer()
End Function



Function OptimizeAlphaChannel(tex)
 ;this function will set the alpha channel of black pixels to be fully transparent 
 ;(as required by masked textures using flag 4). Additionally it will paint the RGB of transparent 
 ; pixels with the average neighbour color to prevent black edge bleeding artefacts.
 Local w,h,rgb,r,g,b,x,y,x2,y2,count,average_rgb
 w=TextureWidth(tex)
 h=TextureHeight(tex)
 Dim tex_memory(w,h)
 SetBuffer TextureBuffer(tex)
 LockBuffer()
 For y=0 To h-1
  For x=0 To w-1
   rgb=ReadPixelFast(x,y) And $FFFFFF
   tex_memory(x,y)=rgb
  Next
 Next
 For y=0 To h-1
  For x=0 To w-1
   If tex_memory(x,y)=0
    count=0
    r=0
    g=0
    b=0
    For y2=y-1 To y+1
     For x2=x-1 To x+1
      If (x<>x2 Or y<>y2) And ((x2>=0) And (x2<w) And (y2>=0) And (y2<h)) 
       If tex_memory(x2,y2)<>0
        r=r+ ((tex_memory(x2,y2) And $FF0000) Shr 16)
        g=g+ ((tex_memory(x2,y2) And $FF00)   Shr 8)
        b=b+ ((tex_memory(x2,y2) And $FF))
        count=count+1
       EndIf
      EndIf
     Next
    Next
    If count>0
     r=r/count
     g=g/count
     b=b/count
     average_rgb=(r Shl 16) Or (g Shl 8) Or b
    Else
     average_rgb=0
    EndIf
    WritePixelFast x,y,average_rgb
   EndIf
  Next
 Next
 UnlockBuffer()
 SetBuffer BackBuffer()
 Dim tex_memory(0,0)
End Function

Comments

puki2006
Great

"jfk" is my pal.


jfk EO-111102006
BTW since Blitz3D Version 1.98 we can also use DDS textures as masked textures. For several reasons I'd strongly suggest to use DXT3 DDS textures for masked stuff. THis will also solve the bleeding dark edges problem discussed before.

EG:
Use a layer-capable graphics tool, eg. Photoshop or Gimp. Use transparency as the default background when creating a new image. Don't use an additional channel for alpha, instead leave the unpainted areas transparent on RGB. Finally blur the outline of the masked content, this will prevent flickering mask edges.
Use the Gimp or PhotoShop DDS-export plugin. Export as DXT3 with alpha. Load the texture in Blitz3D with the mask flag.


jfk EO-111102007
And since were at it: I think this hint came from Fredborg (?): Usually DirectX fades the outlines of masked DDS textures to white, which will result in white bleding edges!. To tell DDS (DXT3 or DXT5) the right "matte color" (don't ask, go wiki), you have to duplicate the masked image as a layer (still in gimp or ps), put it under the original layer, blur it gaussian (radius maybe about 1.5 or so), set it's transparency to 1%. This virtually invisible border, caused by the gaussian blur will
set the matte color in a decent way.

You may think ok what's so special about it. I can only say this info is like a piece of gold.


Code Archives Forum