Gaussian blur in real time?

Advanced game related topics
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Gaussian blur in real time?

Post by Mijikai »

I just messed around maybe its useful somehow :)

example 1:
Image

example 2:
Image

Code (whats needed):

Code: Select all


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()
 
Last edited by Mijikai on Mon Oct 14, 2019 8:11 am, edited 1 time in total.
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

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.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Gaussian blur in real time?

Post by Mijikai »

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

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
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Gaussian blur in real time?

Post by STARGÅTE »

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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Gaussian blur in real time?

Post by wilbert »

@Joubarbe,
Do the objects you want to blur have 24 or 32 bits internally ?
Windows (x64)
Raspberry Pi OS (Arm64)
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

I only use alpha channel drawing, so 32.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Gaussian blur in real time?

Post by wilbert »

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.
Windows (x64)
Raspberry Pi OS (Arm64)
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

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

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.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Gaussian blur in real time?

Post by wilbert »

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.
Windows (x64)
Raspberry Pi OS (Arm64)
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

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 :)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Gaussian blur in real time?

Post by wilbert »

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.
Windows (x64)
Raspberry Pi OS (Arm64)
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

Pretty slow :)
From my experience, ScreenOutput() is really something to avoid when dealing in real time.
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Gaussian blur in real time?

Post by #NULL »

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).
Joubarbe
Enthusiast
Enthusiast
Posts: 555
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Gaussian blur in real time?

Post by Joubarbe »

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".
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Gaussian blur in real time?

Post by wilbert »

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. :?
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply