PureBasic Forum
http://forums.purebasic.com/english/

Gaussian blur in real time?
http://forums.purebasic.com/english/viewtopic.php?f=16&t=73777
Page 2 of 4

Author:  Mijikai [ Mon Oct 14, 2019 7:51 am ]
Post subject:  Re: Gaussian blur in real time?

I just messed around maybe its useful somehow :)

example 1:
Image

example 2:
Image

Code (whats needed):
Code:

Structure RGBA_STRUCT
    code.l
EndStructure

Global *p1.RGBA_STRUCT
Global *p2.RGBA_STRUCT
Global *p3.RGBA_STRUCT

;Coordinates:
;bx = X
;by = Y
;bw = Width
;bh = Height

  bh = by + bh - 1
  bw = bx + bw - 1
 
    If StartDrawing(ScreenOutput())
      *buffer = DrawingBuffer()
      buffer_pitch = DrawingBufferPitch()
     
      For bb = 1 To 2;<- change this to get one of the effects above! (bb = 2 To 3)
        For iy = by To bh Step 1
          For ix =  bx To bw Step 2
            *p1 = *buffer + (ix * 4) + (iy * buffer_pitch)
            *p2 = *buffer + (ix * 4) + ((iy + bb) * buffer_pitch) + 4
            *p3 = *buffer + ((ix - bb) * 4) + (iy * buffer_pitch)
            *p1\code = *p2\code
            *p2\code = *p3\code
          Next
        Next
      Next
     
      DrawingMode(#PB_2DDrawing_Outlined)
      Box(bx,by,300,300)
     
      StopDrawing()
 

Author:  Joubarbe [ Mon Oct 14, 2019 8:08 am ]
Post subject:  Re: Gaussian blur in real time?

Uuuhhh, sorry but that's not a blur :)
In the video STARGÅTE linked, you can see a perfect example of what I'm looking for.

My idea of "pre-bluring" elements that are likely to get behind the GUI is really not great... It would require a lot of clipping to blur one part but not the other, and a lot of pixel collisions calculation. And it's ugly.

Author:  Mijikai [ Mon Oct 14, 2019 8:52 am ]
Post subject:  Re: Gaussian blur in real time?

I thought it might help to get a nice blur :)
So i dont think its wrong that i posted it.

Here is a very fast and nice blur done with what i posted before:
Code:
Procedure.i BlurSurface(X.i,Y.i,Width.i,Height.i,BorderColor.i)
  Protected ix.i
  Protected iy.i
  Protected bw.i
  Protected bh.i
  Protected offset.i
  Protected *buffer
  Protected buffer_pitch.i
  Protected scanline.i
  Protected Dim *pixel.Long(2)
  If StartDrawing(ScreenOutput())
    *buffer = DrawingBuffer()
    buffer_pitch = DrawingBufferPitch()
    bh = Y + Height - 2
    bw = X + Width - 1
    offset = buffer_pitch + 4
    For iy = Y To bh
      scanline = *buffer + (iy * buffer_pitch)
      For ix = X To bw
        *pixel(0) = scanline + (ix * 4)
        *pixel(1) = *pixel(0) + offset
        *pixel(2) = *pixel(0) - 4
        *pixel(0)\l = *pixel(1)\l
        *pixel(1)\l = *pixel(2)\l
        ix + 1
      Next
      Gaussian1D(scanline,bw)
    Next
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(X,Y,Width,Height,BorderColor)
    StopDrawing()
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure


I added the function provided by Michael Vogel some posts before.

Result:
Image

Author:  STARGÅTE [ Mon Oct 14, 2019 7:48 pm ]
Post subject:  Re: Gaussian blur in real time?

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

After the scene rendering (on a texture) this texture is will reduced in resolution (scaled down).
The scaled texture of the screen is then pixel by pixel used in a shader to blend the GUI with the background.
Therefore a GUI window under an other window is not blured.

Author:  wilbert [ Tue Oct 15, 2019 1:20 pm ]
Post subject:  Re: Gaussian blur in real time?

@Joubarbe,
Do the objects you want to blur have 24 or 32 bits internally ?

Author:  Joubarbe [ Tue Oct 15, 2019 3:51 pm ]
Post subject:  Re: Gaussian blur in real time?

I only use alpha channel drawing, so 32.

Author:  wilbert [ Wed Oct 16, 2019 8:27 am ]
Post subject:  Re: Gaussian blur in real time?

Joubarbe wrote:
I only use alpha channel drawing, so 32.

That's good to know.
I'm working on some new blur code based on the idea I mentioned.
I probably try to support 24 bit also but it's good to know that it is not a priority.

Author:  Joubarbe [ Wed Oct 16, 2019 9:18 am ]
Post subject:  Re: Gaussian blur in real time?

Working without alpha is a problem when it comes to mixing sprites and the vector drawing library. 99% of the time now, when I draw a sprite in PB, I use the following function:

Code:
Procedure Convert(*sprite._sprite)
  StartDrawing(SpriteOutput(*sprite\hl_sprite))
  DrawingMode(#PB_2DDrawing_AllChannels)
  DrawImage(ImageID(*sprite\hl_image), 0, 0)
  StopDrawing()
EndProcedure

IMO, 24bits is obsolete; any serious project needs transparency, especially in games. Plus, managing an alpha channel is not that expensive.

Author:  wilbert [ Thu Oct 17, 2019 7:14 am ]
Post subject:  Re: Gaussian blur in real time?

I finally have something for you to test :)
viewtopic.php?f=12&t=73821

I tried hard to make it as fast as I could but it still might be not fast enough for you.
Just try and let me know how it performs.

Author:  Joubarbe [ Thu Oct 17, 2019 8:47 am ]
Post subject:  Re: Gaussian blur in real time?

Wow man, how much do I owe you? :)

Impressive results.

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

Author:  wilbert [ Thu Oct 17, 2019 9:05 am ]
Post subject:  Re: Gaussian blur in real time?

Thanks for the feedback :)

Joubarbe wrote:
I'm not sure how exactly the LineStride option works.

It is similar to DrawingBufferPitch()
Both stride and pitch are words that are used for this.
It's the amount of bytes a line occupies in memory. It's required if padding bytes are added to the end of a line.
For 32 bit images you can usually omit it or pass 0 since normally padding bytes are not used for 32 bit images.
If you pass 0 it will assume a line takes up 4 times the width (4 bytes for each pixel).

Joubarbe wrote:
However, GrabSprite() is a lot more expensive than I thought. 15 FPS in that case (800x800).

You could try StartDrawing(ScreenOutput()) together with BlurRect if you want to blur part of a screen.
The PB manual mentions ScreenOutput() is slow on macOS and Linux but doesn't mention Windows.
I don't know how fast or slow it will be on Windows.

Author:  Joubarbe [ Thu Oct 17, 2019 9:15 am ]
Post subject:  Re: Gaussian blur in real time?

Pretty slow :)
From my experience, ScreenOutput() is really something to avoid when dealing in real time.

Author:  #NULL [ Thu Oct 17, 2019 10:42 am ]
Post subject:  Re: Gaussian blur in real time?

On my Windows 10 with Onboard Graphics an empty Screen/Drawing Block takes only 0-2 ms, and ~3-6 ms including drawing a full circle r=100 and including Filpbuffers() and ClearScreen().

Since in the code of my previous posts the copying of the drawing buffer into another memory buffer wasn't that expensive I have another idea:
Copy the drawingbuffer from a screen drawing block. then the main loop can continue while a separate thread can blur the copied buffer (and possibly copy it into a sprite). The next frame can then use the blurred buffer and copy it back (or draw the sprite).

Author:  Joubarbe [ Thu Oct 17, 2019 11:01 am ]
Post subject:  Re: Gaussian blur in real time?

I'm pretty sure you're aware of that, but 60 FPS means you have a ~16ms frame to do all the things you need done. Wasting 3 to 6ms for a ScreenOutput() operation is out of the question for me (considering that GUI elements take more than 100 pixels of radius).

Copying the buffer into another thread seems a good idea. I'll run some tests with that. I'm a bit worried about the GPU this new DirectionalBlur takes though. I'm at 70% (if Win10 is not drunk), so I definitely need to find a way to not having to update that operation so often.
There's also the idea of grabbing a small part of the screen and zooming it widely. With a strong blur, it might be aesthetic as well.

At the end, it might be too expensive for just "a cool effect".

Author:  wilbert [ Thu Oct 17, 2019 11:19 am ]
Post subject:  Re: Gaussian blur in real time?

Joubarbe wrote:
I'm a bit worried about the GPU this new DirectionalBlur takes though. I'm at 70% (if Win10 is not drunk)

Do you really mean GPU or is that a typo and do you mean CPU ?
The blur computations from that module are all done by CPU, there's no GPU acceleration. :?

Page 2 of 4 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/