Code archives/3D Graphics - Misc/OptimizeAlphaChannel
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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
| ||
Great "jfk" is my pal. |
| ||
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. |
| ||
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