source: trunk/Packages/bgrabitmap/bgrablurgl.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 5.3 KB
Line 
1unit BGRABlurGL;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses
8 Classes, BGRAOpenGL3D, BGRABitmapTypes, BGRACanvasGL, BGRAOpenGLType;
9
10type
11
12 { TBGLBlurShader }
13
14 TBGLBlurShader = class(TBGLShader3D)
15 private
16 function GetDirection: TPointF;
17 function GetImageIndex: integer;
18 function GetRadius: Single;
19 function GetTextureSize: TPoint;
20 procedure SetDirection(AValue: TPointF);
21 procedure SetImageIndex(AValue: integer);
22 procedure SetRadius(AValue: Single);
23 procedure SetTextureSize(AValue: TPoint);
24 protected
25 FTextureSize: TUniformVariablePoint;
26 FImageIndex: TUniformVariableInteger;
27 FDirection: TUniformVariablePointF;
28 FRadius: TUniformVariableSingle;
29 FBlurType: TRadialBlurType;
30 procedure StartUse; override;
31 public
32 constructor Create(ACanvas: TBGLCustomCanvas; ABlurType: TRadialBlurType);
33 function FilterBlurMotion(ATexture: IBGLTexture): IBGLTexture; overload;
34 function FilterBlurMotion(ATexture: IBGLTexture; ADirection: TPointF): IBGLTexture; overload;
35 function FilterBlurRadial(ATexture: IBGLTexture): IBGLTexture;
36 property ImageIndex: integer read GetImageIndex write SetImageIndex;
37 property TextureSize: TPoint read GetTextureSize write SetTextureSize;
38 property Direction: TPointF read GetDirection write SetDirection;
39 property Radius: Single read GetRadius write SetRadius;
40 property BlurType: TRadialBlurType read FBlurType;
41 end;
42
43implementation
44
45{ TBGLBlurShader }
46
47function TBGLBlurShader.GetDirection: TPointF;
48begin
49 result := FDirection.Value;
50end;
51
52function TBGLBlurShader.GetImageIndex: integer;
53begin
54 result := FImageIndex.Value;
55end;
56
57function TBGLBlurShader.GetRadius: Single;
58begin
59 result := FRadius.Value;
60 if FBlurType = rbPrecise then result *= 10;
61end;
62
63function TBGLBlurShader.GetTextureSize: TPoint;
64begin
65 result := FTextureSize.Value;
66end;
67
68procedure TBGLBlurShader.SetDirection(AValue: TPointF);
69begin
70 FDirection.Value := AValue;
71end;
72
73procedure TBGLBlurShader.SetImageIndex(AValue: integer);
74begin
75 FImageIndex.Value := AValue;
76end;
77
78procedure TBGLBlurShader.SetRadius(AValue: Single);
79begin
80 if FBlurType = rbPrecise then AValue /= 10;
81 FRadius.Value := AValue;
82end;
83
84procedure TBGLBlurShader.SetTextureSize(AValue: TPoint);
85begin
86 FTextureSize.Value:= AValue;
87end;
88
89constructor TBGLBlurShader.Create(ACanvas: TBGLCustomCanvas; ABlurType: TRadialBlurType);
90var weightFunc: string;
91begin
92 FBlurType:= ABlurType;
93 case ABlurType of
94 rbNormal,rbPrecise: weightFunc:=
95' float sigma = max(0.1,radius/1.8);'#10+
96' float normalized = x/sigma;'#10 +
97' return 1/(2.506628274631*sigma)*exp(-0.5*normalized*normalized);';
98 rbCorona: weightFunc := 'return max(0, 1-abs(x-radius));';
99 rbFast: weightFunc := 'return max(0,radius+1-x);';
100 else {rbBox,rbDisk}
101 weightFunc := 'if (x <= radius) return 1; else return max(0,radius+1-x);';
102 end;
103
104 inherited Create(ACanvas,
105'void main(void) {'#10 +
106' gl_Position = gl_ProjectionMatrix * gl_Vertex;'#10 +
107' texCoord = vec2(gl_MultiTexCoord0);'#10 +
108'}',
109
110'uniform sampler2D image;'#10 +
111'uniform ivec2 textureSize;'#10 +
112'uniform vec2 direction;'#10 +
113'uniform float radius;'#10 +
114'out vec4 FragmentColor;'#10 +
115
116'float computeWeight(float x)'#10 +
117'{'#10 +
118weightFunc + #10 +
119'}'#10 +
120
121'void main(void)'#10 +
122'{'#10 +
123' int range = int(radius+1.5);'#10 +
124
125' float weight = computeWeight(0);'#10 +
126' float totalWeight = weight;'#10 +
127' FragmentColor = texture2D( image, texCoord ) * weight;'#10 +
128
129' for (int i=1; i<=range; i++) {'#10 +
130' weight = computeWeight(i);'#10 +
131' FragmentColor += texture2D( image, texCoord + i*direction/textureSize ) * weight;'#10 +
132' FragmentColor += texture2D( image, texCoord - i*direction/textureSize ) * weight;'#10 +
133' totalWeight += 2*weight;'#10 +
134' }'#10 +
135
136' FragmentColor /= totalWeight;'#10 +
137'}',
138
139'varying vec2 texCoord;', '130');
140
141 FImageIndex := UniformInteger['image'];
142 FTextureSize := UniformPoint['textureSize'];
143 FDirection := UniformPointF['direction'];
144 FRadius := UniformSingle['radius'];
145
146 ImageIndex:= 0;
147 Direction := PointF(1,0);
148 TextureSize := Point(1,1);
149 Radius := 0;
150end;
151
152function TBGLBlurShader.FilterBlurRadial(ATexture: IBGLTexture): IBGLTexture;
153var horiz: IBGLTexture;
154begin
155 horiz := FilterBlurMotion(ATexture, PointF(1,0));
156 result := FilterBlurMotion(horiz, PointF(0,1));
157end;
158
159function TBGLBlurShader.FilterBlurMotion(ATexture: IBGLTexture): IBGLTexture;
160var previousBuf,buf: TBGLCustomFrameBuffer;
161 previousShader: TBGLCustomShader;
162begin
163 previousBuf := Canvas.ActiveFrameBuffer;
164 buf := Canvas.CreateFrameBuffer(ATexture.Width, ATexture.Height);
165 Canvas.ActiveFrameBuffer := buf;
166
167 TextureSize := Point(ATexture.Width,ATexture.Height);
168 previousShader := Canvas.Lighting.ActiveShader;
169 Canvas.Lighting.ActiveShader := self;
170
171 ATexture.Draw(0, 0); //perform horiz blur
172
173 Canvas.Lighting.ActiveShader := previousShader;
174 Canvas.ActiveFrameBuffer := previousBuf;
175 result := buf.MakeTextureAndFree;
176end;
177
178function TBGLBlurShader.FilterBlurMotion(ATexture: IBGLTexture;
179 ADirection: TPointF): IBGLTexture;
180var prevDir: TPointF;
181begin
182 prevDir := Direction;
183 Direction := ADirection;
184 result := FilterBlurMotion(ATexture);
185 Direction := prevDir;
186end;
187
188procedure TBGLBlurShader.StartUse;
189begin
190 inherited StartUse;
191 FImageIndex.Update;
192 FTextureSize.Update;
193 FDirection.Update;
194 FRadius.Update;
195end;
196
197end.
198
199
Note: See TracBrowser for help on using the repository browser.