Code archives/Graphics/Seamless Tiles
This code has been declared by its author to be Public Domain code.
Download source code
| Create a seamless tile pixmap from a source pixmap |
Rem
Seamless Texture Tiling Example
ORIGINAL AUTHOR (Article and C Code):
Paul Bourke
January 2000
http://local.wasp.uwa.edu.au/~pbourke/texture/tiling/
REQUIREMENTS:
BlitzMax 1.22
Windows XP (Linux and MacOS untested)
PURPOSE:
Create a seamless 'tile' pixmap from a source pixmap
EndRem
SuperStrict
AppTitle = "Seamless Texture Tiling Example"
Graphics 1024, 768
SetBlend SOLIDBLEND
Local tex:TPixmap = LoadPixmap("tex.png") '<--- Provide your own texture for this example. <---
If (tex.format <> PF_RGBA8888) Then tex = ConvertPixmap(tex, PF_RGBA8888)
Local tile:TPixmap = createSeamlessTile(tex, MASK_RADIAL)
Local img:TImage = LoadImage(tile)
SetClsColor 255, 255, 255
While Not KeyHit(KEY_ESCAPE)
Cls
SetViewport 0, 0, GraphicsWidth(), GraphicsHeight()
DrawText "Source:", 2, 2
DrawPixmap tex, 2, 22
DrawText "Result:", 2, tex.height + 42
DrawPixmap tile, 2, tex.height + 62
DrawText "Tiled Result:", tex.width + 20, 2
SetViewport tex.width + 20, 22, GraphicsWidth() - tex.width - 22, GraphicsHeight() - 26
TileImage img
Flip 1
Wend
End
'*************** SEAMLESS TILE FUNCTION AND RELATED CONSTANTS *************************************
Const MASK_LINEAR:Int = 0
Const MASK_RADIAL:Int = 1
Function createSeamlessTile:TPixmap(src:TPixmap, masktype:Int = MASK_LINEAR)
'src: Source pixmap texture. Format should be PF_RGBA8888.
'masktype: Mask type. MASK_LINEAR or MASK_RADIAL. Some textures tile better using a different mask.
'Returns a new 'tileable' pixmap.
Local outp:TPixmap = CreatePixmap(src.width, src.height, src.format)
Local diag:TPixmap = CreatePixmap(src.width, src.height, src.format)
Local temp:TPixmap = PixmapWindow(src, 0, 0, src.width / 2, src.height / 2)
For Local x:Int = 0 To temp.width - 1
For Local z:Int = 0 To temp.height - 1
WritePixel diag, (src.width / 2) + x, (src.height / 2) + z, ReadPixel(temp, x, z)
Next
Next
temp = PixmapWindow(src, src.width / 2, src.height / 2, src.width / 2, src.height / 2)
For Local x:Int = 0 To temp.width - 1
For Local z:Int = 0 To temp.height - 1
WritePixel diag, x, z, ReadPixel(temp, x, z)
Next
Next
temp = PixmapWindow(src, src.width / 2, 0, src.width / 2, src.height / 2)
For Local x:Int = 0 To temp.width - 1
For Local z:Int = 0 To temp.height - 1
WritePixel diag, x, (src.height / 2) + z, ReadPixel(temp, x, z)
Next
Next
temp = PixmapWindow(src, 0, src.height / 2, src.width / 2, src.height / 2)
For Local x:Int = 0 To temp.width - 1
For Local z:Int = 0 To temp.height - 1
WritePixel diag, (src.width / 2) + x, z, ReadPixel(temp, x, z)
Next
Next
Local masksize:Int
If (src.width > src.height) Then masksize = src.width Else masksize = src.height
Local mask:TPixmap = CreatePixmap(masksize, masksize, PF_RGB888)
For Local x:Int = 0 To masksize / 2
For Local z:Int = 0 To masksize / 2
Local d:Float = 0.0
If masktype = MASK_RADIAL
d = Sqr((x - (masksize / 2)) * (x - (masksize / 2)) + (z - (masksize / 2)) * (z - (masksize / 2))) / (masksize / 2)
Else
If masktype = MASK_LINEAR
d = Max(Float((masksize / 2) - x), Float((masksize / 2) - z)) / Float(masksize / 2)
EndIf
EndIf
d = 255 - (255 * d)
If d < 1 Then d = 1
If d > 255 Then d = 255
WritePixel mask, x, z, Int(Byte(d) Shl 16 | Byte(d) Shl 8 | Byte(d))
WritePixel mask, x, (masksize - 1 - z), Int(Byte(d) Shl 16 | Byte(d) Shl 8 | Byte(d))
WritePixel mask, (masksize - 1 - x), z, Int(Byte(d) Shl 16 | Byte(d) Shl 8 | Byte(d))
WritePixel mask, (masksize - 1 - x), (masksize - 1 - z), Int(Byte(d) Shl 16 | Byte(d) Shl 8 | Byte(d))
Next
Next
mask = ResizePixmap(mask, src.width, src.height)
For Local z:Int = 0 To src.height - 1
For Local x:Int = 0 To src.width - 1
Local a1:Float = Float(Byte(ReadPixel(mask, x, z) Shr 16))
Local a2:Float = Float(Byte(ReadPixel(mask, ((x + src.width / 2) Mod src.width), ((z + src.height / 2) Mod src.height)) Shr 16))
Local px1:Int = ReadPixel(src, x, z)
Local px1a:Byte = px1 Shr 24
Local px1b:Byte = px1 Shr 16
Local px1g:Byte = px1 Shr 8
Local px1r:Byte = px1
Local px2:Int = ReadPixel(diag, x, z)
Local px2a:Byte = px2 Shr 24
Local px2b:Byte = px2 Shr 16
Local px2g:Byte = px2 Shr 8
Local px2r:Byte = px2
Local pxRa:Byte = px1a
Local pxRb:Byte = (a1 * (px1b / (a1 + a2))) + (a2 * (px2b / (a1 + a2)))
Local pxRg:Byte = (a1 * (px1g / (a1 + a2))) + (a2 * (px2g / (a1 + a2)))
Local pxRr:Byte = (a1 * (px1r / (a1 + a2))) + (a2 * (px2r / (a1 + a2)))
Local pxR:Int = Int(pxRa Shl 24 | pxRb Shl 16 | pxRg Shl 8 | pxRr)
WritePixel outp, x, z, pxR
Next
Next
Return outp
EndFunction |