Page 3 of 4

Re: Gaussian blur in real time?

Posted: Thu Oct 17, 2019 12:39 pm
by Joubarbe
Confirm, GPU. Maybe it's just me then. Right now, I'm refactoring, I'll check that later (maybe it's the GrabSprite() part then?).

Re: Gaussian blur in real time?

Posted: Thu Oct 17, 2019 1:02 pm
by Mijikai
Joubarbe wrote:Wow man, how much do I owe you? :)

Impressive results.

Code: Select all

      Static sprite_tmp.i,
             *buffer
      If IsSprite(sprite_tmp) : FreeSprite(sprite_tmp) : EndIf
      sprite_tmp = GrabSprite(#PB_Any, 100, 100, 800, 800)
      StartDrawing(SpriteOutput(sprite_tmp))
      *buffer = DrawingBuffer()
      DirectionalBlur::BlurPixelBuf32(*buffer, OutputWidth(), OutputHeight(), 10, DirectionalBlur::#Blur_Full)
      StopDrawing()
      DisplaySprite(sprite_tmp, 100, 100)
At 800x800, your DirectionalBlur costs me 2 FPS with #Blur_Full, which is great. However, GrabSprite() is a lot more expensive than I thought. 15 FPS in that case (800x800).

The strength option doesn't seem to cost more at 30.
I'm not sure how exactly the LineStride option works. Putting random values is fun :)

But yeah, again, the following is the most expensive:

Code: Select all

      Static sprite_tmp.i,
             *buffer
      If IsSprite(sprite_tmp) : FreeSprite(sprite_tmp) : EndIf
      sprite_tmp = GrabSprite(#PB_Any, 100, 100, 800, 800)
      DisplaySprite(sprite_tmp, 100, 100)
I'm pretty sure that I should be doing something else :)
I dont get why you would use GrabSprite (in a loop) just to blur it - why cant you use the backbuffer directly?
Would be a lot faster.

Re: Gaussian blur in real time?

Posted: Thu Oct 17, 2019 1:18 pm
by Joubarbe
https://www.purebasic.com/documentation ... uffer.html
Once StopDrawing() has been called, the buffer is invalidated and can no more be used.
How do you mean? Am I not supposed to use a StartDrawing() block at some point? Meaning if I don't grab a sprite, I must use ScreenOutput(), and this is even slower.

EDIT: @wilbert: High GPU comes from GrabSprite(). My bad!

Re: Gaussian blur in real time?

Posted: Thu Oct 17, 2019 4:22 pm
by #NULL
I tried with threading.
Change mode by key 0-5.
Mode 0-4 only measures but doesn't blur. Mode 5 does blur by actually using the thread.
In proc() you can change manually what blur (or combination and repetition) is used.
GrabSprite() as well as CopyMemory() are very slow on my Windows 10 per default (DirectX9 I guess), ~160ms. But with subsystem OpenGL they are quite fast with ~8ms for GrabSprite() and ~1ms for 3 x CopyMemory().

The bottom line is that you have some overhead due to the screen drawing block and the CopyMemory but if you find a blur function that takes less time than you main loop (including the drawing block) then the thread won't drag the frame time any further. If the thread takes longer then the main loop has to wait, dragging the frame time to match the thread time.

The 2 semaphores manage that the main loop and the thread can run in parallel but don't overtake each other, i.e. they always alternate and wait for each other to finish. They also protect the data accessed by both main and thread.

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

CompilerIf Not #PB_Compiler_Thread
  CompilerError "please enable threadsafe compiler option."
CompilerEndIf


EnableExplicit

#ScreenWidth  = 800
#ScreenHeight = 600
;#ScreenWidth  = 1024
;#ScreenHeight = 768
;#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, 0, 0, 0, #PB_Screen_NoSynchronization)
SetFrameRate(999)

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, 80)

mode = 5

; ------------------------------------------------------------

Procedure blur_a(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, neighborDistance)
  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-neighborDistance) * pixelSize)
      *pixel2rig = buffer + ((y                 ) * pitch) + ((x+neighborDistance) * pixelSize)
      *pixel2top = buffer + ((y-neighborDistance) * pitch) + ((x                 ) * pixelSize)
      *pixel2bot = buffer + ((y+neighborDistance) * 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 blur_b(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 blur_c(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)
  Protected buffer2
  buffer2 = buffer
 
  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

Procedure blur_d(xStart, yStart, xEnd, yEnd, buffer, pitch, pixelSize, neighborDistance)
  Protected x, y
  Protected *pixel1.Pixel
  Protected *pixel2lef.Pixel
  Protected *pixel2rig.Pixel
 
  For y = yStart To yEnd
    For x = xStart To xEnd
     
      *pixel1    = buffer + ((y                 ) * pitch) + ((x                 ) * pixelSize)
     
      *pixel2lef = buffer + ((y                 ) * pitch) + ((x-neighborDistance) * pixelSize)
      *pixel2rig = buffer + ((y                 ) * pitch) + ((x+neighborDistance) * pixelSize)
     
;       *pixel1\r = (*pixel1\r + *pixel2lef\r + *pixel2rig\r) / 3.0
;       *pixel1\g = (*pixel1\g + *pixel2lef\g + *pixel2rig\g) / 3.0
;       *pixel1\b = (*pixel1\b + *pixel2lef\b + *pixel2rig\b) / 3.0
      *pixel1\r = (*pixel2lef\r + *pixel2rig\r) / 2.0
      *pixel1\g = (*pixel2lef\g + *pixel2rig\g) / 2.0
      *pixel1\b = (*pixel2lef\b + *pixel2rig\b) / 2.0
    Next
  Next
EndProcedure

; ------------------------------------------------------------

Define buffer2
Define bufferTmp

Define yStart
Define yEnd
Define xStart
Define xEnd

; ------------------------------------------------------------

Define semaphoreThread = CreateSemaphore()
Define semaphoreMain   = CreateSemaphore(1)

Enumeration #PB_Event_FirstCustomValue
  #eventThreadTimeNotify
EndEnumeration

Structure s_threadInfo
  buffer.i
  pitch.i
  pixelSize.i
  yStart.i
  yEnd.i
  xStart.i
  xEnd.i
  quitThread.i
EndStructure

Procedure proc(*threadInfo.s_threadInfo)
  Shared semaphoreThread
  Shared semaphoreMain
  Protected n
  Protected nMax
  Protected time
  Protected dist
  Protected quitThread
  Repeat
    WaitSemaphore(semaphoreThread) ;>
      
      time = ElapsedMilliseconds()
      
      If *threadInfo\buffer
        
        ; repeat
        nMax = 1
        
        For n=1 To nMax
          
          ; 4 neighbors of distance d
          dist = 2
          blur_a(*threadInfo\xStart, *threadInfo\yStart, *threadInfo\xEnd, *threadInfo\yEnd, *threadInfo\buffer, *threadInfo\pitch, *threadInfo\pixelSize, dist)
          
          ; 4 neighbors of distance d
          ;dist = 4
          ;blur_a(*threadInfo\xStart, *threadInfo\yStart, *threadInfo\xEnd, *threadInfo\yEnd, *threadInfo\buffer, *threadInfo\pitch, *threadInfo\pixelSize, dist)
          
          ; 8 neighbors
          ;blur_b(*threadInfo\xStart, *threadInfo\yStart, *threadInfo\xEnd, *threadInfo\yEnd, *threadInfo\buffer, *threadInfo\pitch, *threadInfo\pixelSize)
          
          ; 4 neighbors * multiple distance 1-4
          ;blur_c(*threadInfo\xStart, *threadInfo\yStart, *threadInfo\xEnd, *threadInfo\yEnd, *threadInfo\buffer, *threadInfo\pitch, *threadInfo\pixelSize)
          
          ; 2 neighbors of distance d
          ;dist = 3
          ;blur_d(*threadInfo\xStart, *threadInfo\yStart, *threadInfo\xEnd, *threadInfo\yEnd, *threadInfo\buffer, *threadInfo\pitch, *threadInfo\pixelSize, dist)          
        Next
        
      EndIf
      
      time = ElapsedMilliseconds() - time
      PostEvent(#eventThreadTimeNotify, 0, 0, 0, time)
      
      If *threadInfo\quitThread
        quitThread = #True
      EndIf
    SignalSemaphore(semaphoreMain) ;<
    
  Until quitThread
EndProcedure

Define threadInfo.s_threadInfo
Define thread = CreateThread(@proc(), @ threadInfo)
Define threadTime

; ------------------------------------------------------------


Repeat
  ExamineMouse()
  ExamineKeyboard()
 
  If KeyboardPushed(#PB_Key_Escape) : quit = #True : EndIf
  If KeyboardPushed(#PB_Key_0) : mode = 0 : 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
 
  While WindowEvent()
    Select Event()
      Case #PB_Event_CloseWindow
        quit = #True
      Case #eventThreadTimeNotify
        threadTime = EventData()
    EndSelect
  Wend
 
  FR + 1
  If ElapsedMilliseconds() > FRt
    time / FR
   
    Select mode
      Case 0 : mode$ = "no screen drawing block"
      Case 1 : mode$ = "only GrabSprite()"
      Case 2 : mode$ = "empty screen drawing block"
      Case 3 : mode$ = "base"
      Case 4 : mode$ = "base + copy"
      Case 5 : mode$ = "base + copy / thread"
    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, "frame time: " + time + "ms")
      If mode >= 5
        DrawText(0, 60, "thread time: " + threadTime + "ms")
      EndIf
    StopDrawing()
  EndIf
 
  ClearScreen($333333)
 
  DisplayTransparentSprite(spr, MouseX(), MouseY())
  
  
  If mode = 0
    
    ; no screen drawing block
    
  ElseIf mode = 1
    
    ; test GrabSprite()
    
    Define sprScreen
    If sprScreen
      FreeSprite(sprScreen)
      sprScreen = 0
    EndIf
    sprScreen = GrabSprite(#PB_Any, 0, 0, #ScreenWidth, #ScreenHeight, #PB_Sprite_AlphaBlending)
    ;GrabSprite(0, 0, 0, #ScreenWidth, #ScreenHeight, #PB_Sprite_AlphaBlending)
    
  ElseIf mode >= 2
    
    ; empty screen drawing block
    
    If StartDrawing(ScreenOutput())
     
      If mode >= 3
        
        ; base
        
        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
          WaitSemaphore(semaphoreMain) ;>
            threadInfo\quitThread = #True
          SignalSemaphore(semaphoreThread) ;<
          WaitThread(thread)
          CloseScreen()
          CloseWindow(win)
          MessageRequester("error", "pixel format not supported")
          End
        EndIf
        If pixelSize
         
          ;yStart = #ScreenHeight * 0.25
          ;yEnd   = #ScreenHeight * 0.75
          ;xStart = #ScreenWidth  * 0.25
          ;xEnd   = #ScreenWidth  * 0.75
          yStart = #ScreenHeight * 0.1
          yEnd   = #ScreenHeight * 0.9
          xStart = #ScreenWidth  * 0.1
          xEnd   = #ScreenWidth  * 0.9
         
          DrawingMode(#PB_2DDrawing_Outlined)
          Box(xStart - 20, yStart - 20, xEnd - xStart + 40, yEnd - yStart + 40, $ff00ff00)
         
          If Not buffer2
            buffer2 = AllocateMemory(pitch * OutputHeight())
          EndIf
          If Not bufferTmp
            bufferTmp = AllocateMemory(pitch * OutputHeight())
          EndIf
          
          If mode >= 4
            
            ; copy / thread
            
            WaitSemaphore(semaphoreMain) ;>
              
              CopyMemory(buffer, bufferTmp, OutputHeight() * pitch)
              
              CopyMemory(buffer2, buffer, OutputHeight() * pitch)
              
              CopyMemory(bufferTmp, buffer2, OutputHeight() * pitch)
              
              threadInfo\buffer = buffer2
              threadInfo\pitch = pitch
              threadInfo\pixelSize = pixelSize
              threadInfo\yStart = yStart
              threadInfo\yEnd   = yEnd
              threadInfo\xStart = xStart
              threadInfo\xEnd   = xEnd
              
            If mode >= 5
            SignalSemaphore(semaphoreThread) ;<
            Else
            SignalSemaphore(semaphoreMain) ;<
            EndIf
            
            ;Delay(6)
            
          EndIf
          
        EndIf
      EndIf
     
      StopDrawing()
    EndIf
  EndIf
 
  time = time + (ElapsedMilliseconds() - timeTmp)
  timeTmp = ElapsedMilliseconds()
 
  DisplaySprite(sprFR, MouseX(), MouseY() + 80)
 
  FlipBuffers()
 
Until quit

WaitSemaphore(semaphoreMain) ;>
  threadInfo\quitThread = #True
SignalSemaphore(semaphoreThread) ;<
WaitThread(thread)


Re: Gaussian blur in real time?

Posted: Fri Oct 18, 2019 9:13 am
by Mijikai
Drawing to the backbuffer is not slow (just access it once)!

I did some testing and used the excellent DirectionalBlur (BlurRect) from wilbert (i only modified it to have it as single function).
With a full hd screen blurring 3-4 areas (800x800) or the whole screen costs only 1-2 ms.

Thats rly fast imho.

Re: Gaussian blur in real time?

Posted: Fri Oct 18, 2019 11:29 am
by Joubarbe
Could you post your part of the code where you draw to the backbuffer? I'm not sure to follow. (Don't need the directional blur functions)

Re: Gaussian blur in real time?

Posted: Fri Oct 18, 2019 12:34 pm
by darius676

Re: Gaussian blur in real time?

Posted: Fri Oct 18, 2019 1:02 pm
by Joubarbe
Image

That's a blur :)
Your technique gives "fuzzy", not blur. And displaying multiple sprites is generally a thing you don't want to do if you need interaction with it.

Re: Gaussian blur in real time?

Posted: Fri Oct 18, 2019 8:33 pm
by darius676
:mrgreen: :mrgreen: :mrgreen: :mrgreen:

I see :oops:

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 6:49 am
by Mijikai
Joubarbe wrote:Could you post your part of the code where you draw to the backbuffer? I'm not sure to follow. (Don't need the directional blur functions)
I posted one of the functions in wilberts directional blur thread.

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 7:58 am
by #NULL
To my knowledge you always operate on the back buffer. DisplaySprite and screen drawing etc. always work on the back buffer. Flipbuffer() makes it the front buffer and the previous front buffer becomes the back buffer to work on.

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 8:38 am
by Joubarbe
To explain a bit better my question, I would have thought that in PB, it was possible to catch the buffer before the main loop:

Code: Select all

StartDrawing(ScreenOutput())
DrawingBuffer()
*screen_buffer = AllocateMemory(DrawingBufferPitch() * OutputHeight())
CopyMemory(DrawingBuffer(), *screen_buffer, DrawingBufferPitch() * OutputHeight())
StopDrawing()
; ... Or just "*screen_buffer = DrawingBuffer()", I guess.
Then, use the Blur function:

Code: Select all

Repeat
...
DirectionalBlur::BlurPixelBuf32(*screen_buffer, 200, 200, 10, DirectionalBlur::#Blur_Full)
...
FlipBuffer()
ForEver
But there must be something I don't get, because this obviously doesn't work. Nothing get blurred, even though the CPU is working.
And again, both StartDrawing(ScreenOutput()) and GrabSprite() are slow in real time. And the goal is to have an animated background blurred as a GUI background.

EDIT: The best I have right now is to blur a small part of the screen with GrabSprite() (inside the main loop):

Code: Select all

      If IsSprite(sprite_tmp) : FreeSprite(sprite_tmp) : EndIf
      sprite_tmp = GrabSprite(#PB_Any, 100, 100, 200, 200, #PB_Sprite_AlphaBlending)
      StartDrawing(SpriteOutput(sprite_tmp))
      DirectionalBlur::BlurPixelBuf32(DrawingBuffer(), OutputWidth(), OutputHeight(), 10, DirectionalBlur::#Blur_Full)
      StopDrawing()
      DisplayTransparentSprite(sprite_tmp, 100, 100)
At this size, GrabSprite() is not expensive.

EDIT2: Same with your code @Mijikai, why does the following doesn't work?

Code: Select all

DirectionalBlur::BlurSurface(*screen_buffer, *screen_buffer_pitch, 0, 0, 800, 800)
(main loop)

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 9:00 am
by Mijikai
Aquire access to the backbuffer once every frame and then do all the work you need.

Code: Select all

;...
    If StartDrawing(ScreenOutput())
      
      *pixel = DrawingBuffer()
      pitch = DrawingBufferPitch()
      
      ;       BlurSurface(*pixel,pitch,100,100,800,800,20)
      ;       BlurSurface(*pixel,pitch,300,300,800,800,20)
      ;       BlurSurface(*pixel,pitch,500,400,800,800,20)
      ;       BlurSurface(*pixel,pitch,000,000,800,800,20)
      
      
      BlurSurface(*pixel,pitch,0,0,1920,1080,10)
      StopDrawing()
    EndIf
;...

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 9:04 am
by Joubarbe
Then I need StartDrawing(ScreenOutput())?! That's my question, how do you "access the backbuffer" (which should be called "buffer" only, because as #NULL mentions, you can't draw to the front buffer anyway). DrawingBuffer() requires a StartDrawing() block!

EDIT: Yeah, well... It's extremely slow to do that, it costs me 25 FPS.

EDIT2: Again, to be clear:

Code: Select all

Repeat
...
StartDrawing(ScreenOutput())
DrawingBuffer()
StopDrawing()
...
ForEver
That is the expensive part. 25FPS for me. Just "doing nothing" :)

EDIT3: As I thought, the buffer is not "moving" at every frame, so I don't get why catching the buffer only once doesn't work. Would love to know why.

Re: Gaussian blur in real time?

Posted: Mon Oct 21, 2019 9:19 am
by Mijikai
Joubarbe wrote:Then I need StartDrawing(ScreenOutput())?!
Yes
Joubarbe wrote:EDIT: Yeah, well... It's extremely slow to do that, it costs me 25 FPS.
No, seems like something is going wrong.