January 26, 2021, 05:12:11 AM

Author Topic: [bb] OptimizeAlphaChannel by jfk EO-11110 [ 1+ years ago ]  (Read 1295 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] OptimizeAlphaChannel by jfk EO-11110 [ 1+ years ago ]
« on: June 29, 2017, 12:28:43 AM »
Title : OptimizeAlphaChannel
Author : jfk EO-11110
Posted : 1+ years ago

Description : 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.


Code :
Code: BlitzBasic
  1. Graphics3D 640,480,32,2
  2. SetBuffer BackBuffer()
  3.  
  4. ;this array is used by the OptimizeAlphaChannel function!
  5. Dim tex_memory(0,0)
  6.  
  7.  
  8. ; create a simple test scene:
  9. camera=CreateCamera()
  10. CameraClsColor camera,127,127,127
  11. TranslateEntity camera,0,0,-2.5
  12. light=CreateLight()
  13. RotateEntity light,45,45,0
  14.  
  15. cube=CreateCube()
  16. EntityFX cube,16
  17.  
  18.  
  19. ; create a test texture
  20. s=128
  21. tex=CreateTexture(s,s,4)
  22. SetBuffer TextureBuffer(tex)
  23. For i=0 To 25
  24.  Color Rand(255),Rand(255),Rand(255)
  25.  Oval Rand(-25,s+25),Rand(-25,s+25),25,25,1
  26. Next
  27. SetBuffer BackBuffer()
  28. EntityTexture cube,tex
  29.  
  30.  
  31.  
  32. ; *** compare these two ways of masking the texture: ***
  33.  
  34. ;SetMaskChannel(tex)        ; standard method, also used by Loading with flag 4
  35. OptimizeAlphaChannel(tex)   ; optimized method, paint edges with neighbour colors to
  36.                             ; prevent fade-To-black edges
  37.  
  38. ;(you may also skip both functions to see how the texture is unmasked after painting to it:
  39. ;although created with flag 4, after painting to it the alpha channel is set to <>zero (aka opaque))
  40.  
  41.  
  42.  
  43. ; test loop
  44. While KeyDown(1)=0
  45.  TurnEntity cube,.1,.2,.3
  46.  RenderWorld()
  47.  Flip
  48. Wend
  49. End
  50.  
  51.  
  52.  
  53.  
  54. Function SetMaskChannel(tex)
  55.  ;this function will set the alpha channel of black pixels to be fully transparent
  56.  ;(as required by masked textures using flag 4).
  57.  Local w,h,rgb,r,g,b,x,y,x2,y2,count,average_rgb
  58.  w=TextureWidth(tex)
  59.  h=TextureHeight(tex)
  60.  Dim tex_memory(w,h)
  61.  SetBuffer TextureBuffer(tex)
  62.  LockBuffer()
  63.  For y=0 To h-1
  64.   For x=0 To w-1
  65.    rgb=ReadPixelFast(x,y) And $FFFFFF
  66.    If rgb=0 Then
  67.     WritePixelFast x,y,0
  68.    Else
  69.    EndIf
  70.   Next
  71.  Next
  72.  UnlockBuffer()
  73.  SetBuffer BackBuffer()
  74. End Function
  75.  
  76.  
  77.  
  78. Function OptimizeAlphaChannel(tex)
  79.  ;this function will set the alpha channel of black pixels to be fully transparent
  80.  ;(as required by masked textures using flag 4). Additionally it will paint the RGB of transparent
  81.  ; pixels with the average neighbour color to prevent black edge bleeding artefacts.
  82.  Local w,h,rgb,r,g,b,x,y,x2,y2,count,average_rgb
  83.  w=TextureWidth(tex)
  84.  h=TextureHeight(tex)
  85.  Dim tex_memory(w,h)
  86.  SetBuffer TextureBuffer(tex)
  87.  LockBuffer()
  88.  For y=0 To h-1
  89.   For x=0 To w-1
  90.    rgb=ReadPixelFast(x,y) And $FFFFFF
  91.    tex_memory(x,y)=rgb
  92.   Next
  93.  Next
  94.  For y=0 To h-1
  95.   For x=0 To w-1
  96.    If tex_memory(x,y)=0
  97.     count=0
  98.     r=0
  99.     g=0
  100.     b=0
  101.     For y2=y-1 To y+1
  102.      For x2=x-1 To x+1
  103.       If (x<>x2 Or y<>y2) And ((x2>=0) And (x2<w) And (y2>=0) And (y2<h))
  104.        If tex_memory(x2,y2)<>0
  105.         r=r+ ((tex_memory(x2,y2) And $FF0000) Shr 16)
  106.         g=g+ ((tex_memory(x2,y2) And $FF00)   Shr 8)
  107.         b=b+ ((tex_memory(x2,y2) And $FF))
  108.         count=count+1
  109.        EndIf
  110.       EndIf
  111.      Next
  112.     Next
  113.     If count>0
  114.      r=r/count
  115.      g=g/count
  116.      b=b/count
  117.      average_rgb=(r Shl 16) Or (g Shl 8) Or b
  118.     Else
  119.      average_rgb=0
  120.     EndIf
  121.     WritePixelFast x,y,average_rgb
  122.    EndIf
  123.   Next
  124.  Next
  125.  UnlockBuffer()
  126.  SetBuffer BackBuffer()
  127.  Dim tex_memory(0,0)
  128. End Function


Comments :


puki(Posted 1+ years ago)

 Great"jfk" is my pal.


jfk EO-11110(Posted 1+ years ago)

 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-11110(Posted 1+ years ago)

 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 willset 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.


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal