Code archives/Graphics/Fast Fading
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| Doing effect such as fade to black (or fade to another image) is not very efficient if done in pure 2D, as it requires for each frame of the fading to modifye each pixel. Here is an alternative way of doing cool fading effects that is on my computer 320 times faster than brute force alpha blending! The idea is to have a gray bitmap that drives the way the two images are merged. In this example I have put 3 methods: 1) the brute force alpha blended fading 2) the brute force "new" fading method 3) the optimized "new" fading method Also the the gray bitmap here is procedural (it's a spiral pattern, with random paramaters giving different results each time), but the intent is really to use a bitmap that you have created in your favorite 2D tool. Try to mess with the filters of Photoshop, you can get interesting results. The functions of interest here are CreateFastFadingPattern that preprocesses the gray level image (the "fading pattern") and creates a bank holding the data, and DrawFastFading that actually draws a frame of the fading sequence (there are 256 frames, one for each level of gray). Last word: to see how fast this really is, deactivate vertical sync when asked. Enough of boring talking, you'll see by yourself. NB: don't forget to modify the lines img1% = LoadImage("adobe.jpg") img2% = LoadImage("MossyGround.bmp") to point tou your own images. | |||||
; === Fast Fading by Koriolis ===
; Brute force alpha blended fading
; Could still be enhanced a bit by storing the image information in an array
Function DrawAlphaFading(alpha%, img1%, img2)
; NB: img1 and img2 must have the same dimensions
alpha_inv% = 255 - alpha
SetBuffer(BackBuffer())
w% = ImageWidth(img1)-1
h% = ImageHeight(img1)-1
img1Buf% = ImageBuffer(img1)
img2Buf% = ImageBuffer(img2)
LockBuffer(BackBuffer())
LockBuffer(img1Buf)
LockBuffer(img2Buf)
For i = 0 To w
For j = 0 To h
c1% = ReadPixelFast(i, j, img1Buf)
c2% = ReadPixelFast(i, j, img2Buf)
r% = (((c1 And 255) * alpha) + ((c2 And 255) * alpha_inv)) Shr 8
g% = ((((c1 Shr 8) And 255) * alpha) + (((c2 Shr 8) And 255) * alpha_inv)) Shr 8
b% = ((((c1 Shr 16) And 255) * alpha) + (((c2 Shr 16) And 255) * alpha_inv)) Shr 8
WritePixel(i, j, r Or (g Shl 8) Or (b Shl 16))
Next
Next
UnlockBuffer(img1Buf)
UnlockBuffer(img2Buf)
UnlockBuffer(BackBuffer())
End Function
; brute force "new" fading
Function DrawSlowFading(grayLevel%, img%, mixMap%)
SetBuffer(BackBuffer())
w% = ImageWidth(img)-1
h% = ImageHeight(img)-1
imgBuf% = ImageBuffer(img)
mixMapBuf% = ImageBuffer(mixMap)
LockBuffer(BackBuffer())
LockBuffer(imgBuf)
LockBuffer(mixMapBuf)
For i = 0 To w
For j = 0 To h
a% = ReadPixelFast(i, j, mixMapBuf) And 255
If a = grayLevel Then
WritePixelFast(i, j, ReadPixelFast(i, j, imgBuf))
EndIf
Next
Next
UnlockBuffer(mixMapBuf)
UnlockBuffer(imgBuf)
UnlockBuffer(BackBuffer())
End Function
Dim CFFP_counts%(256)
Function CreateFastFadingPattern%(fadingImg%)
w% = ImageWidth(fadingImg)
h% = ImageHeight(fadingImg)
bank% = CreateBank(w*h*4 + 1028)
For layer = 0 To 256
CFFP_counts(layer) = 0
Next
fadingImgBuf% = ImageBuffer(fadingImg)
w = w - 1
h = h - 1
LockBuffer(fadingImgBuf)
For i = 0 To w
For j = 0 To h
a% = (ReadPixelFast(i, j, fadingImgBuf) And 255) + 1
CFFP_counts(a) = CFFP_counts(a) + 4
Next
Next
PokeInt(bank, 0, CFFP_counts(0))
For layer = 1 To 256
CFFP_counts(layer) = CFFP_counts(layer) + CFFP_counts(layer-1)
CFFP_counts(layer-1) = CFFP_counts(layer-1) + 1028
PokeInt(bank, layer Shl 2, CFFP_counts(layer))
Next
CFFP_counts(256) = CFFP_counts(256) + 1028
For i = 0 To w
For j = 0 To h
a% = ReadPixelFast(i, j, fadingImgBuf) And 255
PokeShort(bank, CFFP_counts(a), i)
PokeShort(bank, CFFP_counts(a)+2, j)
CFFP_counts(a) = CFFP_counts(a) + 4
Next
Next
UnlockBuffer(fadingImgBuf)
Return bank
End Function
; optimized "new" fading
Function DrawFastFading(grayLevel%, img%, fadingPattern%)
SetBuffer(BackBuffer())
st% = PeekInt(fadingPattern, grayLevel Shl 2)
en% = PeekInt(fadingPattern, (grayLevel+1) Shl 2) - 1
imgBuf% = ImageBuffer(img)
LockBuffer(BackBuffer())
LockBuffer(imgBuf)
For ofs = st To en Step 4
i% = PeekShort(fadingPattern, ofs)
j% = PeekShort(fadingPattern, ofs + 2)
WritePixel(i, j, ReadPixelFast(i, j, imgBuf))
Next
UnlockBuffer(imgBuf)
UnlockBuffer(BackBuffer())
End Function
;============================ little test ===============================
Graphics 256,256,16,2
; TODO: replace these images by two 256x256 images of your own
img1% = LoadImage("adobe.jpg")
img2% = LoadImage("MossyGround.bmp")
frame% = 0
vsync% = Lower(Input("VSync ? (y/n) "))="y"
Print("")
Print("1) Alpha blended fading, slooow")
Print("2) Slow fading (almost as slow)")
Print("3) Fast fading (really fast)")
Select Input("Select method ")
Case 1
Color 0,0,255
While Not KeyHit(1)
If (frame And 255) = 0 Then
DrawImage(img1, 0, 0)
startMS% = MilliSecs()
EndIf
DrawAlphaFading(frame And 255, img1, img2)
Flip(vsync)
frame = frame + 1
If (frame And 255) = 255
Cls
Print "Duration : " + (MilliSecs() - startMS) + " ms"
EndIf
Wend
Case 2
Color 0,0,255
While Not KeyHit(1)
If (frame And 255) = 0 Then
If mixMap <> 0 Then FreeImage(mixMap)
mixMap% = CreateTestFadingImage(2*Rand(-3,3), Rnd(0, 20))
DrawImage(mixMap, 0, 0)
Text 128, 5, "Press a key", True
Flip()
WaitKey()
startMS% = MilliSecs()
EndIf
DrawSlowFading(frame And 255, img2, mixMap)
Flip(vsync)
frame = frame + 1
If (frame And 255) = 255
Cls
Print "Duration : " + (MilliSecs() - startMS) + " ms"
EndIf
Wend
Case 3
Color 0,0,255
While Not KeyHit(1)
If (frame And 255) = 0 Then
If mixMap <> 0 Then FreeImage(mixMap)
mixMap% = CreateTestFadingImage(2*Rand(-3,3), Rnd(0, 20))
fadingPattern% = CreateFastFadingPattern(mixMap)
DrawImage(mixMap, 0, 0)
Text 128, 5, "Press a key", True
Flip()
WaitKey()
DrawImage(img1, 0, 0)
startMS% = MilliSecs()
EndIf
DrawFastFading(frame And 255, img2, fadingPattern)
Flip(vsync)
frame = frame + 1
If (frame And 255) = 255
Cls
Print "Duration : " + (MilliSecs() - startMS) + " ms"
EndIf
Wend
FreeBank(fadingPattern)
Default Print "Invalid option, quiting..."
Delay(2000)
End
End Select
End
Function CreateTestFadingImage%(coeff#, swirlStrength#)
coeff = coeff*255.0/360.0
img% = CreateImage(256,256)
imgBuf% = ImageBuffer(img)
LockBuffer(imgBuf)
For i = 0 To 255
For j = 0 To 255
c% = ((ATan((i-128)/(j-128.5))*coeff) + swirlStrength*Sqr((i-128)*(i-128)+(j-128)*(j-128))) And 255
WritePixelFast(i, j, c * $010101, imgBuf)
Next
Next
UnlockBuffer(imgBuf)
Return img
End Function |
Comments
None.
Code Archives Forum