Recent

Author Topic: Fast hardware image blur  (Read 30397 times)

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #30 on: March 04, 2017, 04:20:11 pm »
I think I am getting somewhere. I have added a TBGLFrameBuffer class in the dev-bgrabitmap branch.

How it works: create a TBGLFrameBuffer class, then switch to it by using ActiveFrameBuffer property of BGLCanvas.

For example :
Code: Pascal  [Select]
  1. procedure TForm1.OpenGLControlPaint(Sender: TObject);
  2. var
  3.   mousePos: TPoint;
  4.   buf: TBGLFrameBuffer;
  5. begin
  6.   { Draw Background }
  7.   BGLViewPort(OpenGLControl.Width, OpenGLControl.Height, BGRAWhite);
  8.   { Create framebuffer }
  9.   buf := TBGLFrameBuffer.Create(256,256);
  10.   { Use it }
  11.   BGLCanvas.ActiveFrameBuffer := buf;
  12.  
  13.   BGLCanvas.Fill(CSSYellow);
  14.   BGLCanvas.Line(0,0,128,128, BGRABlack);
  15.   mousePos := ScreenToClient(Mouse.CursorPos);
  16.   BGLCanvas.FillRect(mousePos.x - 50, mousePos.y - 50, mousePos.x + 50, mousePos.y + 50, CSSRed, False);
  17.  
  18.   { Render framebuffer on the control }
  19.   BGLCanvas.ActiveFrameBuffer := nil;
  20.   BGLCanvas.PutImage(0,0, buf.Texture);
  21.   { Free framebuffer }
  22.   buf.Free;
  23.  
  24.   { Update }
  25.   OpenGLControl.SwapBuffers;
  26. end;
  27.  

In this example, a red square is drawn around the mouse cursor, but within the framebuffer (yellow background). So it gets clipped.
« Last Edit: March 04, 2017, 04:22:16 pm by circular »
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #31 on: March 05, 2017, 07:51:04 am »
Thank you so much Circular.
Now I can try the way of using two frames for implementing a fast blur using vertical and horizontal glsl blur codes.
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #32 on: March 05, 2017, 09:17:51 am »
You're welcome.

Good luck, and if there is something to fix, just tell me.
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #33 on: March 06, 2017, 01:20:50 pm »
I tested giving 2 TBGLFrameBuffer to a BGLCanvas, by changing ActiveFrameBuffer property, and I understand how it works now. But I am not sure how to use these frame buffers functionality in TBGLShader3D, for giving 2 shader and 2 fragments together to it. any advice or idea??

Any help appreciated prior
Regards
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #34 on: March 06, 2017, 06:53:18 pm »
I would suggest to use one shader with a vec2 parameter to indicate the direction.

Then you can have two framebuffers. In the first one, you draw the texture with the shader in one direction. In the second one, you draw the first frame buffer with the shader in a perpendical direction.
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #35 on: March 07, 2017, 10:47:53 am »
I created 2 shaders for vertical and horizontal blur directions, each one exists in a separate class, and wrote this code for testing what you suggested. any comment??
Below is my code, and I attached the whole test project too.

Any help appreciated prior
Regards

Code: Pascal  [Select]
  1.  
  2. procedure TForm1.FormShow(Sender: TObject);
  3. begin
  4.   tex := BGLTexture('Pics\Src.jpg');
  5.   DataHoriz.Shader := TMyShaderHoriz.Create(BGLCanvas);
  6.   DataVert.Shader := TMyShaderVert.Create(BGLCanvas);
  7.   TexLoaded := True;
  8. end;
  9.  
  10. procedure TForm1.OpenGLControlPaint(Sender: TObject);
  11. begin
  12.   if not TexLoaded then
  13.     Exit;
  14.   BGLViewPort(OpenGLControl.Width, OpenGLControl.Height, BGRAWhite);
  15.   Buf0 := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  16.   Buf1 := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  17.  
  18.   BGLCanvas.ActiveFrameBuffer := Buf0;
  19.   BGLCanvas.Lighting.ActiveShader := DataHoriz.Shader;
  20.   tex.Draw(0, 0);
  21.  
  22.   BGLCanvas.ActiveFrameBuffer := Buf1;
  23.   BGLCanvas.Lighting.ActiveShader := DataVert.Shader;
  24.   Buf0.Texture.Draw(0, 0);
  25.  
  26.   BGLCanvas.ActiveFrameBuffer := Buf0;
  27.   BGLCanvas.Lighting.ActiveShader := DataHoriz.Shader;
  28.   Buf1.Texture.Draw(0, 0);
  29.  
  30.  
  31.   BGLCanvas.ActiveFrameBuffer := nil;
  32.   BGLCanvas.Lighting.ActiveShader := DataVert.Shader;
  33.   Buf0.Texture.Draw(0, 0);
  34.   BGLCanvas.Lighting.ActiveShader := nil;
  35.  
  36.   Buf0.Free;
  37.   Buf1.Free;
  38.   OpenGLControl.SwapBuffers;
  39. end;      
  40.  
« Last Edit: March 07, 2017, 12:53:43 pm by simin_sh »
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #36 on: March 07, 2017, 11:46:34 pm »
Ok. This code uses OpenGL 3.3 shader language. In order to have the projection right, it would then be needed to pass the projection matrix as a parameter. So i've added support for that on dev-bgrabitmap branch. At the same time I realized I had made some mistake for multidimensional shader variables. So I fixed it as well.

Here I adapted your code accordingly and fixed a few things.

Still not perfect, because the shader does not really know the texture coordinates and assumes that they are the same as the render coordinates. That's not exactly the case as for some reason the frame buffer is vertically flipped, so one last FlipY is necessary when drawing the result.

Note : I replaced the icon to make the zip lighter.
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #37 on: March 08, 2017, 12:06:12 am »
I think it is possible from there to do a function that blurs a texture (returning a new texture that is blurred, the one from the second framebuffer). The only thing is that for now, if the framebuffer is freed, that frees the texture as well. So maybe one function to free the framebuffer but keep the texture would be handy.

Otherwise, to have the information about the vertex coordinate, the way to go with OpenGL 3 would be to use array buffers. I made some classes to use them, even if it is not much official yet.
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #38 on: March 08, 2017, 12:05:37 pm »
Thank you Circular
I checked the code and now its much better and understandable, I think my next step would be testing deeper blur functionality, and implement it in glsl code, and have Radius param to manage blur deep dependency in algorithm.

I was wondering is there a way for saving the blured image, I know we have glReadPixels in openGL, but I was wondering if there is such functionality in BGRABtimap?

Regards
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #39 on: March 08, 2017, 01:25:28 pm »
You're welcome.

Reading pixels is not implemented yet but that's of course something we can add.
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #40 on: March 08, 2017, 02:42:56 pm »
I tested a ping pong between buffers for a deeper blur, I think its the right way, but I have a problem in the size of texture coordinates and the control in draw, you can see it when draw the blured picture on control. any idea how to fix it??
Maybe it is because of the problem you said about flip, or the glsl code, I am not sure.

Here is my code
and I attached the test project with the sample pic I tested.

Any help appreciated prior
Regards


Code: Pascal  [Select]
  1.  
  2. procedure TForm1.scenePaint(Sender: TObject);
  3. var
  4.   n, i: integer;
  5. begin
  6.  
  7.   if not TexLoaded then
  8.     Exit;
  9.   BGLViewPort(scene.Width, scene.Height, BGRAWhite);
  10.   //allocate target for horizontal blur
  11.   //hb=horiz buffer, vb=vert buffer, hs=horiz shader, vs=vert shader
  12.   hb := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  13.   BGLCanvas.ActiveFrameBuffer := hb;
  14.  
  15.   //configure shader
  16.   hs.ProjectionMatrix := BGLCanvas.ProjectionMatrix;
  17.   hs.TextureSize := Point(tex.Width, tex.Height);
  18.   BGLCanvas.Lighting.ActiveShader := hs;
  19.  
  20.   tex.Draw(0, 0); //perform horiz blur
  21.  
  22.   //allocate target for vertical blur
  23.   vb := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  24.   BGLCanvas.ActiveFrameBuffer := vb;
  25.  
  26.   //configure shader
  27.   vs.ProjectionMatrix := BGLCanvas.ProjectionMatrix;
  28.   vs.TextureSize := Point(tex.Width, tex.Height);
  29.   BGLCanvas.Lighting.ActiveShader := vs;
  30.  
  31.   hb.Texture.Draw(0, 0); //perform vert blur on horizontally blurred image
  32.  
  33.   //Apply blur n times
  34.   n := 100;
  35.   for i := 0 to n - 1 do
  36.   begin
  37.     //allocate target for horizontal blur
  38.     BGLCanvas.ActiveFrameBuffer := hb;
  39.     //configure shader
  40.     BGLCanvas.Lighting.ActiveShader := hs;
  41.     vb.Texture.Draw(0, 0); //perform horiz blur
  42.     //allocate target for vertical blur
  43.     BGLCanvas.ActiveFrameBuffer := vb;
  44.     //configure shader
  45.     BGLCanvas.Lighting.ActiveShader := vs;
  46.     hb.Texture.Draw(0, 0); //perform vert blur on horizontally blurred image
  47.   end;
  48.  
  49.   //render result
  50.   BGLCanvas.ActiveFrameBuffer := nil;
  51.   BGLCanvas.Lighting.ActiveShader := nil;
  52.   vb.Texture.FlipY.Draw(0, 0); //draw on control
  53.  
  54.   vb.Free;
  55.   hb.Free;
  56.   scene.SwapBuffers;
  57. end;  
  58.  
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #41 on: March 08, 2017, 02:46:11 pm »
You're welcome.

Reading pixels is not implemented yet but that's of course something we can add.


Ok, so you think we can have it on BGRA in near future?? Or I need to to find another way?? because the speed and quality of blur is so important for me in this case, and I thought that implementing the save result functionality would help me analyze these items better.

Regards
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #42 on: March 08, 2017, 03:13:27 pm »
I tested a ping pong between buffers for a deeper blur, I think its the right way, but I have a problem in the size of texture coordinates and the control in draw, you can see it when draw the blured picture on control. any idea how to fix it??
Maybe it is because of the problem you said about flip, or the glsl code, I am not sure.

Here is my code
and I attached the test project with the sample pic I tested.

Any help appreciated prior
Regards


Code: Pascal  [Select]
  1.  
  2. procedure TForm1.scenePaint(Sender: TObject);
  3. var
  4.   n, i: integer;
  5. begin
  6.  
  7.   if not TexLoaded then
  8.     Exit;
  9.   BGLViewPort(scene.Width, scene.Height, BGRAWhite);
  10.   //allocate target for horizontal blur
  11.   //hb=horiz buffer, vb=vert buffer, hs=horiz shader, vs=vert shader
  12.   hb := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  13.   BGLCanvas.ActiveFrameBuffer := hb;
  14.  
  15.   //configure shader
  16.   hs.ProjectionMatrix := BGLCanvas.ProjectionMatrix;
  17.   hs.TextureSize := Point(tex.Width, tex.Height);
  18.   BGLCanvas.Lighting.ActiveShader := hs;
  19.  
  20.   tex.Draw(0, 0); //perform horiz blur
  21.  
  22.   //allocate target for vertical blur
  23.   vb := TBGLFrameBuffer.Create(tex.Width, tex.Height);
  24.   BGLCanvas.ActiveFrameBuffer := vb;
  25.  
  26.   //configure shader
  27.   vs.ProjectionMatrix := BGLCanvas.ProjectionMatrix;
  28.   vs.TextureSize := Point(tex.Width, tex.Height);
  29.   BGLCanvas.Lighting.ActiveShader := vs;
  30.  
  31.   hb.Texture.Draw(0, 0); //perform vert blur on horizontally blurred image
  32.  
  33.   //Apply blur n times
  34.   n := 100;
  35.   for i := 0 to n - 1 do
  36.   begin
  37.     //allocate target for horizontal blur
  38.     BGLCanvas.ActiveFrameBuffer := hb;
  39.     //configure shader
  40.     BGLCanvas.Lighting.ActiveShader := hs;
  41.     vb.Texture.Draw(0, 0); //perform horiz blur
  42.     //allocate target for vertical blur
  43.     BGLCanvas.ActiveFrameBuffer := vb;
  44.     //configure shader
  45.     BGLCanvas.Lighting.ActiveShader := vs;
  46.     hb.Texture.Draw(0, 0); //perform vert blur on horizontally blurred image
  47.   end;
  48.  
  49.   //render result
  50.   BGLCanvas.ActiveFrameBuffer := nil;
  51.   BGLCanvas.Lighting.ActiveShader := nil;
  52.   vb.Texture.FlipY.Draw(0, 0); //draw on control
  53.  
  54.   vb.Free;
  55.   hb.Free;
  56.   scene.SwapBuffers;
  57. end;  
  58.  



Here is the ScreenShot that shows what I mean of the size problem in control or texture, I set the form size exactly the size of picture but you can see in the picture that its not fit, and I do not know where is the problem.

Any help appreciated prior
Regards
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1

circular

  • Hero Member
  • *****
  • Posts: 3058
    • Personal webpage
Re: Fast hardware image blur
« Reply #43 on: March 09, 2017, 07:43:32 am »
Hmm did you set the size using ClientWidth/ClientHeight?

I will have a look at a save feature when I can.
Conscience is the debugger of the mind

simin_sh

  • Full Member
  • ***
  • Posts: 143
Re: Fast hardware image blur
« Reply #44 on: March 09, 2017, 07:55:30 am »
Thank you so I will be waiting for the news of save functionality.

Yes, it does not make any difference, all the sizes including TBGLFrameBuffer, BGLViewPort, BGLTexture and the Form in the program are 900*506 which is exactly the size of my source jpg picture.
And the blur image is still like the screenshot.
« Last Edit: March 09, 2017, 07:58:44 am by simin_sh »
OS Windows 10 - Lazarus 1.7 - FPC 3.1.1