It is currently Wed Oct 21, 2020 2:11 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 48 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Gaussian blur in real time?
PostPosted: Thu Oct 10, 2019 11:39 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
Hey,

I'd like to know if there's a library somewhere that makes it possible to blur a part of a (2D) screen in real time. The goal would be to have a GUI over the game world, and have this game world blurred as a GUI background. I think the best way would be to capture an area of the screen, then turn it into a blurred sprite.

I saw two libraries that blur images, but they are extremely slow (500ms for 3 passes on a 512x512 image). I fear the answer contains the word "shader", and I know nothing about them :)

(the effect is pretty cool in 3D)


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Fri Oct 11, 2019 2:49 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2011 10:06 am
Posts: 870
Location: Denmark
Most 2D games, unless very old school, use 3D too.
Glow effect can be achieved in PureBasic's Ogre3D using CreateCompositorEffect().
See this one: http://wiki.ogre3d.org/Glow
You need the scripts and a suitable material to go with it.
Do a search for 'compositor' here and that should lead you to relevant and nice examples.

_________________
“Tell me and I forget. Teach me and I remember. Involve me and I learn.”
— Benjamin Franklin
Current configurations: Windows 10, Intel 6800K, GeForce Gtx 1060, 32 gb ram.


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Fri Oct 11, 2019 7:21 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 1264
Location: right here
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.
Code:
mode 1: empty drawing block                  time: 11ms
mode 2: base                                 time: 11ms
mode 3: 4 direct neighbors                   time: 15ms
mode 4: 8 neighbors with greater distance    time: 16ms
mode 5: test only CopyMemory()               time: 12ms
mode 6: CopyMemory() and more neighbors      time: 110ms
mode 7: CopyMemory() and weighted neighbors  time: 175ms
mode 8: 4 neighbors with multiple distances  time: 25ms

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



Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Fri Oct 11, 2019 7:59 pm 
Offline
User
User

Joined: Thu Jan 31, 2019 12:59 am
Posts: 99
Hello,
you may be able to try the following:
Take the sprite for the background and copy it to a number of SpriteID . For example, 4 sprites.
You change the transparency and output the sprites slightly (randomly) offset and overlapping on the screen.
It is possible that this will achieve the desired effect.




download:
https://www.dropbox.com/s/fjizfurnprr70a3/BLUREXAMPLE_DEMO.zip?dl=0


Code:
;small and dirty example for "blur"

InitKeyboard()
InitSprite()
InitMouse()
InitSound()
UsePNGImageDecoder()


EnableExplicit




Structure _gfx
 
  id.i
  x.f
  y.f
  t.l
 
EndStructure

Global NewList _gfx._gfx()
Global _gfx_work_id.i=0
Global _key_id.l=0
Global _ok.l=0
Global _win_id.i=0
Global _x.f=0
Global _y.f=0
Global _w.f=1024
Global _h.f=512
Global _win_id.i=0
Global _screen_id.i=0
Global _event.i=0
Global _i.b=0
Global _bx.b=0
Global _by.b=6
;load the gfx:

 
_win_id.i=OpenWindow(#PB_Any,_x.f,_y.f,_w.f,_h.f," *BLUR* ?")
_screen_id.i=OpenWindowedScreen(WindowID(_win_id.i),0,0,_w.f,_h.f)
_gfx_work_id.i=LoadSprite(#PB_Any,GetCurrentDirectory()+"blur.png",#PB_Sprite_AlphaBlending )

If IsSprite(_gfx_work_id.i)
 
  ResetList(_gfx())
 
  For _i.b=0 To 3
   
   
    If AddElement(_gfx())
      CopySprite(_gfx_work_id,_gfx()\id)
      _bx.b+1
      _by.b-1
      _gfx()\x=_bx.b
      _gfx()\y=_by.b
    EndIf
 
  Next
 
 
 
  If ListSize(_gfx())>0
   
    Repeat
      _event.i=WaitWindowEvent(1)
     
     
      ResetList(_gfx())
     
       
     
      While NextElement(_gfx())
;         _gfx()\x=Random(4)
;         _gfx()\y=Random(-4)
        DisplayTransparentSprite(_gfx()\id,_gfx()\x,_gfx()\y,50)
       
      Wend
     
      FlipBuffers()
     
     
    Until _event.i=#PB_Event_CloseWindow
   
  EndIf
 
 
 
Else
 
  _ok.l=MessageRequester("ERROR","Can not load gfx",#PB_MessageRequester_Ok )
 
 
EndIf

End


Last edited by darius676 on Mon Oct 14, 2019 8:59 pm, edited 4 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sat Oct 12, 2019 7:39 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
Thank you for your answers! Those pieces of code will be useful!


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sat Oct 12, 2019 4:46 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Feb 09, 2006 11:27 pm
Posts: 2549
Not sure if the following routines are from Wilbert or someone else, but they are quite fast - do quick check by loading an image of your preference...

Code:
Procedure Gaussian1D(*PixelBuf32,NumPixels,NextPixelOffset=4)

   !mov ecx, [p.v_NumPixels]
   !sub ecx, 3
   !js gaussian1d_exit
   !mov eax, [p.v_NextPixelOffset]

   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !mov rdx, [p.p_PixelBuf32]
      !movd mm1, [rdx]
      !movd mm4, [rdx + rax]
   CompilerElse
      !mov edx, [p.p_PixelBuf32]
      !movd mm1, [edx]
      !movd mm4, [edx + eax]
   CompilerEndIf
   !punpcklbw mm1, mm1
   !punpcklbw mm4, mm4
   !psrlw mm1, 4
   !psrlw mm4, 4
   !movq mm2, mm1
   !movq mm3, mm1

   ; loop
   !gaussian1d_loop0:
   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !movd mm5, [rdx + rax * 2]
   CompilerElse
      !movd mm5, [edx + eax * 2]
   CompilerEndIf
   !punpcklbw mm5, mm5
   !psrlw mm5, 4
   !gaussian1d_loop1:
   !movq mm0, mm2
   !paddw mm0, mm3
   !paddw mm0, mm4
   !psllw mm0, 2
   !paddw mm0, mm1
   !paddw mm0, mm3
   !paddw mm0, mm3
   !paddw mm0, mm5
   !psrlw mm0, 8
   !packuswb mm0, mm0
   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !movd [rdx], mm0
      !add rdx, rax
   CompilerElse
      !movd [edx], mm0
      !add edx, eax
   CompilerEndIf
   !movq mm1, mm2
   !movq mm2, mm3
   !movq mm3, mm4
   !movq mm4, mm5
   !dec ecx
   !jns gaussian1d_loop0
   !cmp ecx, -3
   !jne gaussian1d_loop1
   !gaussian1d_exit:
   !emms

EndProcedure
Procedure Gaussian2D(*PixelBuf32,Width,Height,BufferPitch=0)

   If BufferPitch=0
      BufferPitch=Width<<2
   EndIf

   Protected i.i=0
   While i<Height
      Gaussian1D(*PixelBuf32 + BufferPitch * i, Width)
      i+1
   Wend

   i=0
   While i<Width
      Gaussian1D(*PixelBuf32+i<<2,Height,BufferPitch)
      i+1
   Wend

EndProcedure
Procedure GaussianBlur(Image,Strength=2)

   Protected.i i,w,h,x,y,max_x,max_y

   ;If CheckCompilerInformation()


   If StartDrawing(ImageOutput(image))
      w=OutputWidth()
      h=OutputHeight()

      If DrawingBufferPixelFormat() & $60
         For i=0 To Strength
            Gaussian2D(DrawingBuffer(),w,h,DrawingBufferPitch())
         Next

      Else
         max_x=w-1
         max_y=h-1

         Dim Buffer.l(max_y, max_x)
         DrawingMode(#PB_2DDrawing_AllChannels)

         For y=0 To max_y
            For x=0 To max_x
               Buffer(y,x)=Point(x,y)
            Next
         Next

         For i=0 To Strength
            Gaussian2D(@Buffer(),w,h)
         Next

         For y=0 To max_y
            For x=0 To max_x
               Plot(x,y,Buffer(y,x))
            Next
         Next
      EndIf
      StopDrawing()
   EndIf
   ;EndIf

EndProcedure

#ScreenWidth  = 400
#ScreenHeight = 400


win = OpenWindow(0, 0, 0, #ScreenWidth, #ScreenHeight, "window")
ImageGadget(0,0,0,#ScreenWidth, #ScreenHeight,0)
UsePNGImageDecoder()
LoadImage(1,"c:\...\....png")
AddWindowTimer(0,0,100)

strength=200
Repeat

   Select WaitWindowEvent()
   Case #PB_Event_CloseWindow
      quit = #True
   EndSelect

   t=ElapsedMilliseconds()
   CopyImage(1,0)
   GaussianBlur(0,strength)
   t=ElapsedMilliseconds()-t

   SetGadgetState(0,ImageID(0))
   SetWindowTitle(0,Str(t)+" @"+Str(strength))

   If strength
      strength-2
   EndIf

Until quit


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sat Oct 12, 2019 5:12 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
Yeah that one I know. Not fast enough in my opinion :)


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sat Oct 12, 2019 8:14 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 1264
Location: right here
It can blur an 800x600 screen with 3 passes in ~40ms on my system.
Code:
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
;#ScreenWidth  = 1680
;#ScreenHeight = 1050

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 = 3

Procedure Gaussian1D(*PixelBuf32,NumPixels,NextPixelOffset=4)

   !mov ecx, [p.v_NumPixels]
   !sub ecx, 3
   !js gaussian1d_exit
   !mov eax, [p.v_NextPixelOffset]

   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !mov rdx, [p.p_PixelBuf32]
      !movd mm1, [rdx]
      !movd mm4, [rdx + rax]
   CompilerElse
      !mov edx, [p.p_PixelBuf32]
      !movd mm1, [edx]
      !movd mm4, [edx + eax]
   CompilerEndIf
   !punpcklbw mm1, mm1
   !punpcklbw mm4, mm4
   !psrlw mm1, 4
   !psrlw mm4, 4
   !movq mm2, mm1
   !movq mm3, mm1

   ; loop
   !gaussian1d_loop0:
   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !movd mm5, [rdx + rax * 2]
   CompilerElse
      !movd mm5, [edx + eax * 2]
   CompilerEndIf
   !punpcklbw mm5, mm5
   !psrlw mm5, 4
   !gaussian1d_loop1:
   !movq mm0, mm2
   !paddw mm0, mm3
   !paddw mm0, mm4
   !psllw mm0, 2
   !paddw mm0, mm1
   !paddw mm0, mm3
   !paddw mm0, mm3
   !paddw mm0, mm5
   !psrlw mm0, 8
   !packuswb mm0, mm0
   CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !movd [rdx], mm0
      !add rdx, rax
   CompilerElse
      !movd [edx], mm0
      !add edx, eax
   CompilerEndIf
   !movq mm1, mm2
   !movq mm2, mm3
   !movq mm3, mm4
   !movq mm4, mm5
   !dec ecx
   !jns gaussian1d_loop0
   !cmp ecx, -3
   !jne gaussian1d_loop1
   !gaussian1d_exit:
   !emms

EndProcedure
Procedure Gaussian2D(*PixelBuf32,Width,Height,BufferPitch=0)

   If BufferPitch=0
      BufferPitch=Width<<2
   EndIf

   Protected i.i=0
   While i<Height
      Gaussian1D(*PixelBuf32 + BufferPitch * i, Width)
      i+1
   Wend

   i=0
   While i<Width
      Gaussian1D(*PixelBuf32+i<<2,Height,BufferPitch)
      i+1
   Wend

EndProcedure
Procedure GaussianBlur(Image,Strength=2)

   Protected.i i,w,h,x,y,max_x,max_y

   ;If CheckCompilerInformation()


   ;If StartDrawing(ImageOutput(image))
      w=OutputWidth()
      h=OutputHeight()
     
      If DrawingBufferPixelFormat() & $60
         For i=0 To Strength
            Gaussian2D(DrawingBuffer(),w,h,DrawingBufferPitch())
         Next

       Else
         max_x=w-1
         max_y=h-1

         Dim Buffer.l(max_y, max_x)
         DrawingMode(#PB_2DDrawing_AllChannels)

         For y=0 To max_y
            For x=0 To max_x
               Buffer(y,x)=Point(x,y)
            Next
         Next
         
         For i=0 To Strength
            Gaussian2D(@Buffer(),w,h)
         Next

         For y=0 To max_y
            For x=0 To max_x
               Plot(x,y,Buffer(y,x))
            Next
         Next
      EndIf
      ;StopDrawing()
   ;EndIf
   ;EndIf

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
 
  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$ = "asm gauss"
    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
              Define strength = 3
              GaussianBlur(1, strength)
          EndSelect
         
        EndIf
      EndIf
    EndIf
   
    StopDrawing()
  EndIf
 
  time = time + (ElapsedMilliseconds() - timeTmp)
 
  DisplaySprite(sprFR, MouseX(), MouseY() + 80)
 
  FlipBuffers()
 
Until quit


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 5:10 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3678
Location: Netherlands
Joubarbe wrote:
Yeah that one I know. Not fast enough in my opinion :)

How much faster do you need it to be ?
You can also think the other way around. First decide how much time the blur is allowed to take and then see what you can accomplish in that time.
A one directional blur (only horizontal or vertical) would be faster and if you have an example image of how much blur you want, it might also be possible to blur more in one pass so you don't need 3 passes.

_________________
macOS 10.15 Catalina, Windows 10


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 7:27 am 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
The look I'd like to obtain is in my first post, the link to Everspace 2. That's pretty blurry. 40ms in a real time game is out of the question, but I'm trying some stuff right now, "pre-blurring" the elements that have a chance to go behind the UI. I don't have a choice anyway, that's either that, or shaders (or give up on this idea).

"blur more in one pass" you said, how so? (I know nothing about ASM)

(and thanks for your code anyway wilbert, it's been useful to me in the past :) )


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 11:53 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3678
Location: Netherlands
Joubarbe wrote:
The look I'd like to obtain is in my first post, the link to Everspace 2. That's pretty blurry. 40ms in a real time game is out of the question, but I'm trying some stuff right now, "pre-blurring" the elements that have a chance to go behind the UI. I don't have a choice anyway, that's either that, or shaders (or give up on this idea).

The link you posted seems to freeze the background image when the menu appears.
In that case you only have to blur it once.

Joubarbe wrote:
"blur more in one pass" you said, how so? (I know nothing about ASM)

If you take another approach (like a low pass filter), you can make the strength of the blur independent of the running time of the procedure.
It would require different code but you would be able to create a highly blurred image without a lot of extra time.

_________________
macOS 10.15 Catalina, Windows 10


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 2:22 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
Is there such code in PB somewhere?


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 8:32 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jan 10, 2008 1:30 pm
Posts: 1301
Location: Germany, Glienicke
You can try our UB2D - 2D Physically Based Rendering Engine.
In this video you can actually see the blurred scene behind the GUI: https://youtu.be/_luehiIpetU?t=182

_________________
ImageImage


Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Sun Oct 13, 2019 8:55 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 403
Location: France
Wow I forgot about this one. Seeing that it's still pre-alpha, is it safe to use?
A shame this seems... discontinued? It's by far the most promising 2D engine I've seen on PB.

(32bits only, hmm... No way to have the source code of the blur part I suppose? - really don't feel good using a whole alpha engine for just one library)
(I'm also of the opinion of Artus about Godot. Would have been easier to play with predefined shaders)

EDIT: Could you explain briefly what is the method you used for this blur behind the GUI?


Last edited by Joubarbe on Mon Oct 14, 2019 7:24 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Gaussian blur in real time?
PostPosted: Mon Oct 14, 2019 6:31 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3678
Location: Netherlands
Joubarbe wrote:
Is there such code in PB somewhere?

I could try to create it if you wish; it might benefit others as well.
I believe I can make it have a strong blur and at the same time be faster as my gaussian blur procedure at its lowest strength.
The only thing is that the code will be longer and a bit more complicated for me to code so it might take a few days to get it right.

You could also check out thenOpenCV examples by JHPJHP.
OpenCV is also capable of blurring.

_________________
macOS 10.15 Catalina, Windows 10


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 48 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye