I don't know how to do it with shaders unfortunately.
I tried with direct DrawingBuffer() access what it could do but I don't know how to make it fast enough (and good). You can change the test case with number keys 1-8. The mouse moves the sprite and it should blur in some way in the center of the screen in case 3,4,6,7,8.
Please disable the debugger.
Here are the times the drawing block takes on my Linux machine. On my windows machine the times are way to long, over a second in some cases, but I do not have a real graphics card in there at the moment, maybe that's why.
It doesn't blur very much (would be more expensive) and it blurs only 1/4 of a 800x600 screen, so not sure it could ever be done fast enough for a whole large screen, so FWIW
Code: Select all
CompilerIf #PB_Compiler_Debugger
If MessageRequester("debugger?", "the debugger is enabled. run anyway?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
End
EndIf
CompilerEndIf
EnableExplicit
#ScreenWidth = 800
#ScreenHeight = 600
InitSprite()
InitKeyboard()
InitMouse()
ElapsedMilliseconds()
Structure Pixel
r.a
g.a
b.a
EndStructure
Define win, quit, mode, mode$
Define spr, i
Define sprFR, FR, FRt, FR$
Define time, timeTmp
win = OpenWindow(#PB_Any, 0, 0, #ScreenWidth, #ScreenHeight, "window")
OpenWindowedScreen(WindowID(win), 0, 0, #ScreenWidth, #ScreenHeight)
UsePNGImageDecoder()
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Define spr = LoadSprite(#PB_Any, #PB_Compiler_Home + "examples/3D/Data/PureBasic3DLogo.png") ; windows
CompilerElse
Define spr = LoadSprite(#PB_Any, #PB_Compiler_Home + "examples/3d/Data/PureBasic3DLogo.png") ; linux
CompilerEndIf
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Define font = LoadFont(#PB_Any, "courier new", 10)
CompilerElse
Define font = LoadFont(#PB_Any, "monospace", 10)
CompilerEndIf
sprFR = CreateSprite(#PB_Any, 400, 60)
mode = 6
Procedure mode3(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize)
Protected x, y
Protected *pixel1.Pixel
Protected *pixel2lef.Pixel
Protected *pixel2rig.Pixel
Protected *pixel2top.Pixel
Protected *pixel2bot.Pixel
For y = yStart To yEnd
For x = xStart To xEnd
*pixel1 = buffer + ((y ) * pitch) + ((x ) * pixelSize)
*pixel2lef = buffer + ((y ) * pitch) + ((x-1) * pixelSize)
*pixel2rig = buffer + ((y ) * pitch) + ((x+1) * pixelSize)
*pixel2top = buffer + ((y-1) * pitch) + ((x ) * pixelSize)
*pixel2bot = buffer + ((y+1) * pitch) + ((x ) * pixelSize)
*pixel1\r = (*pixel1\r + *pixel2lef\r + *pixel2rig\r + *pixel2top\r + *pixel2bot\r) / 5.0
*pixel1\g = (*pixel1\g + *pixel2lef\g + *pixel2rig\g + *pixel2top\g + *pixel2bot\g) / 5.0
*pixel1\b = (*pixel1\b + *pixel2lef\b + *pixel2rig\b + *pixel2top\b + *pixel2bot\b) / 5.0
Next
Next
EndProcedure
Procedure mode4(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize)
Protected x, y
Protected *pixel1.Pixel
Protected *pixel2_1.Pixel
Protected *pixel2_2.Pixel
Protected *pixel2_3.Pixel
Protected *pixel2_4.Pixel
Protected *pixel2_5.Pixel
Protected *pixel2_6.Pixel
Protected *pixel2_7.Pixel
Protected *pixel2_8.Pixel
For y = yStart To yEnd
For x = xStart To xEnd
*pixel1 = buffer + ((y ) * pitch) + ((x ) * pixelSize)
*pixel2_1 = buffer + ((y-3) * pitch) + ((x+1) * pixelSize)
*pixel2_2 = buffer + ((y-1) * pitch) + ((x+3) * pixelSize)
*pixel2_3 = buffer + ((y+1) * pitch) + ((x+3) * pixelSize)
*pixel2_4 = buffer + ((y+3) * pitch) + ((x+1) * pixelSize)
*pixel2_5 = buffer + ((y+3) * pitch) + ((x-1) * pixelSize)
*pixel2_6 = buffer + ((y+1) * pitch) + ((x-3) * pixelSize)
*pixel2_7 = buffer + ((y-1) * pitch) + ((x-3) * pixelSize)
*pixel2_8 = buffer + ((y-3) * pitch) + ((x-1) * pixelSize)
*pixel1\r = (*pixel2_1\r + *pixel2_2\r + *pixel2_3\r + *pixel2_4\r + *pixel2_5\r + *pixel2_6\r + *pixel2_7\r + *pixel2_8\r) / 8.0
*pixel1\g = (*pixel2_1\g + *pixel2_2\g + *pixel2_3\g + *pixel2_4\g + *pixel2_5\g + *pixel2_6\g + *pixel2_7\g + *pixel2_8\g) / 8.0
*pixel1\b = (*pixel2_1\b + *pixel2_2\b + *pixel2_3\b + *pixel2_4\b + *pixel2_5\b + *pixel2_6\b + *pixel2_7\b + *pixel2_8\b) / 8.0
Next
Next
EndProcedure
Procedure mode5(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Protected x, y
CopyMemory(buffer, buffer2, OutputHeight() * pitch)
EndProcedure
Procedure mode6(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Protected x, y, i, k
Protected r, g, b, cnt
Protected *pixelTmp.Pixel
Protected *pixel1.Pixel
CopyMemory(buffer, buffer2, OutputHeight() * pitch)
For y = yStart To yEnd
For x = xStart To xEnd
r = 0
g = 0
b = 0
cnt = 0
For k=-4 To 4
For i=-4 To 4
*pixelTmp = buffer2 + ((y+k) * pitch) + ((x+i) * pixelSize)
r + *pixelTmp\r
g + *pixelTmp\g
b + *pixelTmp\b
cnt + 1
Next
Next
*pixel1 = buffer + (y * pitch) + (x * pixelSize)
*pixel1\r = r / cnt
*pixel1\g = g / cnt
*pixel1\b = b / cnt
Next
Next
EndProcedure
Procedure mode7(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Protected x, y, i, k
Protected r.f, g.f, b.f, cnt.f
Protected *pixelTmp.Pixel
Protected *pixel1.Pixel
CopyMemory(buffer, buffer2, OutputHeight() * pitch)
#d = 3
Protected initWeights
Protected Dim weights.f(1, 1) ; use .d ?
Protected rMax.f
If Not initWeights
initWeights = #True
Dim weights( (2 * #d + 1), (2 * #d + 1) )
rMax = Sqr((#d * #d) + (#d * #d))
For k=-#d To #d
For i=-#d To #d
weights(#d + k, #d + i) = 1.0 - Sqr((i * i) + (k * k)) / rMax
Debug "" + i + " " + k + " " + weights(#d + k, #d + i)
Next
Next
;End
EndIf
; test weights()
; DrawingMode(#PB_2DDrawing_AllChannels)
; Box(10-2, 10-2, 90+4, 90+4, $ff006600)
; For k=-4 To 4
; For i=-4 To 4
; Circle(10+5+(4+k)*10, 10+5+(4+i)*10, 3, RGBA(255.0 * weights(4+k, 4+i), 0, 0, 255))
; Next
; Next
For y = yStart To yEnd
For x = xStart To xEnd
r = 0
g = 0
b = 0
cnt = 0
For k=-#d To #d
For i=-#d To #d
*pixelTmp = buffer2 + ((y+k) * pitch) + ((x+i) * pixelSize)
r + *pixelTmp\r * weights(#d+k, #d+i)
g + *pixelTmp\g * weights(#d+k, #d+i)
b + *pixelTmp\b * weights(#d+k, #d+i)
cnt + weights(#d+k, #d+i)
Next
Next
*pixel1 = buffer + (y * pitch) + (x * pixelSize)
*pixel1\r = r / cnt
*pixel1\g = g / cnt
*pixel1\b = b / cnt
Next
Next
EndProcedure
Procedure mode8(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Protected x, y
Protected *pixel1.Pixel
Protected *pixel2lef.Pixel
Protected *pixel2rig.Pixel
Protected *pixel2top.Pixel
Protected *pixel2bot.Pixel
CopyMemory(buffer, buffer2, OutputHeight() * pitch)
Define n
For n = 1 To 4
For y = yStart To yEnd
For x = xStart To xEnd
*pixel1 = buffer + ((y ) * pitch) + ((x ) * pixelSize)
*pixel2lef = buffer2 + ((y ) * pitch) + ((x-n) * pixelSize)
*pixel2rig = buffer2 + ((y ) * pitch) + ((x+n) * pixelSize)
*pixel2top = buffer2 + ((y-n) * pitch) + ((x ) * pixelSize)
*pixel2bot = buffer2 + ((y+n) * pitch) + ((x ) * pixelSize)
*pixel1\r = (*pixel2lef\r + *pixel2rig\r + *pixel2top\r + *pixel2bot\r) / 4.0
*pixel1\g = (*pixel2lef\g + *pixel2rig\g + *pixel2top\g + *pixel2bot\g) / 4.0
*pixel1\b = (*pixel2lef\b + *pixel2rig\b + *pixel2top\b + *pixel2bot\b) / 4.0
Next
Next
Next
EndProcedure
Repeat
ExamineMouse()
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Escape) : quit = #True : EndIf
If KeyboardPushed(#PB_Key_1) : mode = 1 : EndIf
If KeyboardPushed(#PB_Key_2) : mode = 2 : EndIf
If KeyboardPushed(#PB_Key_3) : mode = 3 : EndIf
If KeyboardPushed(#PB_Key_4) : mode = 4 : EndIf
If KeyboardPushed(#PB_Key_5) : mode = 5 : EndIf
If KeyboardPushed(#PB_Key_6) : mode = 6 : EndIf
If KeyboardPushed(#PB_Key_7) : mode = 7 : EndIf
If KeyboardPushed(#PB_Key_8) : mode = 8 : EndIf
While WindowEvent()
Select Event()
Case #PB_Event_CloseWindow
quit = #True
EndSelect
Wend
FR + 1
If ElapsedMilliseconds() > FRt
time / FR
Select mode
Case 1 : mode$ = "empty drawing block"
Case 2 : mode$ = "base"
Case 3 : mode$ = "4 direct neighbors"
Case 4 : mode$ = "8 neighbors with greater distance"
Case 5 : mode$ = "test only CopyMemory()"
Case 6 : mode$ = "CopyMemory() and more neighbors"
Case 7 : mode$ = "CopyMemory() and weighted neighbors"
Case 8 : mode$ = "4 neighbors with multiple distances"
EndSelect
FRt = ElapsedMilliseconds() + 500
FR$ = "fps:" + Str(FR * 2)
FR = 0
StartDrawing(SpriteOutput(sprFR))
DrawingMode(#PB_2DDrawing_Transparent)
Box(0, 0, OutputWidth(), OutputHeight(), $0)
DrawingFont(FontID(font))
DrawText(0, 0, FR$)
DrawText(0, 20, "mode: " + mode + " (" + mode$ + ")")
DrawText(0, 40, "time: " + time + "ms")
StopDrawing()
EndIf
ClearScreen($333333)
DisplayTransparentSprite(spr, MouseX(), MouseY())
timeTmp = ElapsedMilliseconds()
If StartDrawing(ScreenOutput())
If mode >= 2
Define buffer = DrawingBuffer()
Define pitch = DrawingBufferPitch()
Define pixelFormat = DrawingBufferPixelFormat()
Define pixelSize
; Debug pixelFormat
; Debug pixelFormat!#PB_PixelFormat_ReversedY
; Debug #PB_PixelFormat_24Bits_RGB
; Debug #PB_PixelFormat_32Bits_BGR
; End
If pixelFormat & (#PB_PixelFormat_24Bits_BGR | #PB_PixelFormat_24Bits_RGB)
pixelSize = 3
ElseIf pixelFormat & (#PB_PixelFormat_32Bits_BGR | #PB_PixelFormat_32Bits_RGB)
pixelSize = 4
Else
CloseScreen()
CloseWindow(win)
MessageRequester("error", "pixel format not supported")
End
EndIf
If pixelSize
Define yStart = #ScreenHeight * 0.25
Define yEnd = #ScreenHeight * 0.75
Define xStart = #ScreenWidth * 0.25
Define xEnd = #ScreenWidth * 0.75
DrawingMode(#PB_2DDrawing_Outlined)
Box(xStart - 20, yStart - 20, xEnd - xStart + 40, yEnd - yStart + 40, $ff00ff00)
Define buffer2
If Not buffer2
buffer2 = AllocateMemory(pitch * OutputHeight())
EndIf
If mode >= 3
Select mode
Case 3 : mode3(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize)
Case 4 : mode4(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize)
Case 5 : mode5(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Case 6 : mode6(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Case 7 : mode7(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
Case 8 : mode8(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, buffer2)
EndSelect
EndIf
EndIf
EndIf
StopDrawing()
EndIf
time = time + (ElapsedMilliseconds() - timeTmp)
DisplaySprite(sprFR, MouseX(), MouseY() + 80)
FlipBuffers()
Until quit