Developer Documentation
FilterKernels.hh
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #pragma once
51 
52 
53 #include <ACG/Config/ACGDefines.hh>
54 #include <ACG/Math/GLMatrixT.hh>
55 #include <ACG/GL/gl.hh>
56 
57 #include <QStringList>
58 #include <QImage>
59 #include <vector>
60 
61 
62 namespace ACG
63 {
64 
65 // Forward Declaration
66 class FBO;
67 
68 
69 
70 class ACGDLLEXPORT BaseSeparableFilterKernel
71 {
72 public:
73 
74  /* \brief Create separable filter
75  *
76  * @param _texWidth width of input texture
77  * @param _texHeight height of input texture
78  * @param _internalfmt internal gl format of the texture
79  */
80  BaseSeparableFilterKernel(int _texWidth, int _texHeight, GLenum _internalfmt = GL_RGBA);
81 
83  virtual ~BaseSeparableFilterKernel();
84 
85 
86  /* \brief Execute filter
87  *
88  * Perform the two filter passes.
89  * If a custom fbo and a _tempColorAttachment is provided, the first pass is
90  * rendered into that temporary render texture.
91  * If a custom fbo and a _dstColorAttachment is provided, the second pass is
92  * rendered into that destination render texture.
93  *
94  * If _dstFBO or _tempColorAttachment is invalid, an internal fbo is created as target for the first pass.
95  * If _dstFBO or _dstColorAttachment is invalid, the second pass renders into whatever is currently bound as render target.
96  *
97  * @param _srcTexture 2d input texture
98  * @param _dstFBO custom target fbo (optional)
99  * @param _dstColorAttachment target attachment of the custom target fbo (optional)
100  * @param _tempColorAttachment temporary attachment of the custom fbo, that is different from _dstColorAttachment (optional)
101  * @return true on success, false otherwise
102  */
103  bool execute(GLuint _srcTexture, ACG::FBO* _dstFBO = 0, GLuint _dstColorAttachment = GL_COLOR_ATTACHMENT0, GLuint _tempColorAttachment = 0);
104 
105 
106  /* \brief Resize input texture
107  *
108  * @param _texWidth new input texture width
109  * @param _texHeight new input texture height
110  */
111  void resizeInput(int _texWidth, int _texHeight);
112 
114  int texWidth() const {return texWidth_;}
115 
117  int texHeight() const {return texHeight_;}
118 
120  const ACG::Vec2f& texelSize() const {return texelSize_;}
121 
123  GLenum internalFormat() const {return internalfmt_;}
124 
125 protected:
126 
127  /* \brief Setup shader with uniforms
128  *
129  * @param _pass pass number: 0 or 1
130  * @param _scrTex source texture for pass
131  * @return shader program for screen quad
132  */
133  virtual GLSL::Program* setupPass(int _pass, GLuint _srcTex) = 0;
134 
135 
136  /* \brief Update kernel after resizing
137  *
138  */
139  virtual void updateKernel() = 0;
140 
141 private:
142 
143  int texWidth_,
144  texHeight_;
145 
146  GLenum internalfmt_,
147  externalfmt_;
148 
149  // size of a texel in uv space
150  ACG::Vec2f texelSize_;
151 
152  // temp render targets if none supplied by user
153  // attachment0 : target for first axis pass
154  ACG::FBO* tempRT_;
155 };
156 
157 
158 // separable 2d gaussian blur
160 {
161 public:
162 
163  /* \brief Create separable gauss filter
164  *
165  * @param _texWidth width of input texture
166  * @param _texHeight height of input texture
167  * @param _blurRadius radius in pixel coords of the blur kernel
168  * @param _blurSigma blur smoothness, standard deviation of the gaussian function
169  * @param _internalfmt internal gl format of the texture
170  */
171  GaussianBlurFilter(int _texWidth, int _texHeight, int _blurRadius, float _blurSigma = 1.0f, GLenum _internalfmt = GL_RGBA);
172 
174  virtual ~GaussianBlurFilter();
175 
176  /* \brief Change kernel settings
177  *
178  * @param _blurRadius new radius
179  * @param _blurSigma new sigma
180  */
181  void setKernel(int _blurRadius, float _blurSigma);
182 
184  int radius() const {return radius_;}
185 
187  int samples() const {return samples_;}
188 
190  int sigma() const {return sigma_;}
191 
193  const std::vector<ACG::Vec2f>& offsetsX() const {return offsetsX_;}
194 
196  const std::vector<ACG::Vec2f>& offsetsY() const {return offsetsY_;}
197 
199  const std::vector<float>& weights() const {return weights_;}
200 
201 protected:
202 
203  virtual GLSL::Program* setupPass(int _pass, GLuint _srcTex);
204 
205  void updateKernel();
206 
207 private:
208 
209  int radius_,
210  samples_;
211 
213  float sigma_;
214 
216  QStringList macros_;
217 
219  std::vector<ACG::Vec2f> offsetsX_;
220  std::vector<ACG::Vec2f> offsetsY_;
221 
223  std::vector<float> weights_;
224 };
225 
226 
227 // bilateral blur: gaussian blur with silhouette preservation
229 {
230 public:
231 
232  /* \brief Create bilateral filter
233  *
234  * @param _texWidth width of input texture
235  * @param _texHeight height of input texture
236  * @param _blurRadius radius in pixel coords of the blur kernel
237  * @param _blurSigmaS blur smoothness in spatial distance (here distance in pixel coords)
238  * @param _blurSigmaR blur smoothness in range distance (here linear view space difference)
239  * @param _internalfmt internal gl format of the texture
240  */
241  BilateralBlurFilter(int _texWidth, int _texHeight, int _blurRadius, float _blurSigmaS = 1.0f, float blurSigmaR = 1.0f, GLenum _internalfmt = GL_RGBA);
242 
244  virtual ~BilateralBlurFilter();
245 
246 
247  /* \brief Set dynamic params before calling execute()
248  *
249  * @param _proj projection matrix
250  * @param _depthTex depthbuffer texture (nonlinear depths)
251  */
252  void setParams(const ACG::GLMatrixf& _proj, GLuint _depthTex)
253  {
254  proj_ = _proj;
255  depthTex_ = _depthTex;
256  }
257 
258 
259  /* \brief Change kernel settings
260  *
261  * @param _blurRadius new radius
262  * @param _blurSigmaS new spatial smoothness
263  * @param _blurSigmaR new range smoothness
264  */
265  void setKernel(int _blurRadius, float _blurSigmaS, float _blurSigmaR);
266 
267 
269  int radius() const {return radius_;}
270 
272  int samples() const {return samples_;}
273 
275  const ACG::Vec2f& sigma() const {return sigma_;}
276 
278  const std::vector<ACG::Vec2f>& offsetsX() const {return offsetsX_;}
279 
281  const std::vector<ACG::Vec2f>& offsetsY() const {return offsetsY_;}
282 
283 protected:
284  virtual GLSL::Program* setupPass(int _pass, GLuint _srcTex);
285 
286  void updateKernel();
287 
288 private:
289 
290  int radius_,
291  samples_;
292 
295 
298 
300  std::vector<ACG::Vec2f> offsetsX_;
301  std::vector<ACG::Vec2f> offsetsY_;
302 
304  std::vector<float> spatialKernel_;
305 
307  QStringList macros_;
308 
309  ACG::GLMatrixf proj_;
310  GLuint depthTex_;
311 };
312 
313 
314 class ACGDLLEXPORT RadialBlurFilter
315 {
316 public:
317 
318  /* \brief Create radial blur filter
319  *
320  * @param _numSamples number of kernel samples
321  */
322  RadialBlurFilter(int _numSamples);
323 
325  virtual ~RadialBlurFilter() {}
326 
327  /* \brief Perform radial blur
328  *
329  * Writes to currently bound render target.
330  * A good intensity range for light to very strong blur is [0.0025, 0.01].
331  *
332  * @param _srcTexture input 2d texture
333  * @param _blurRadius blur radius in uv space
334  * @param _blurIntensity intensity, quadratic distance factor
335  * @param _blurCenter center in uv space
336  */
337  bool execute(GLuint _srcTexture, float _blurRadius = 1.0f, float _blurIntensity = 0.0025f, const ACG::Vec2f& _blurCenter = ACG::Vec2f(0.5f, 0.5f));
338 
339 
340  /* \brief Change kernel settings
341  *
342  * @param _numSamples new sample count
343  */
344  void setKernel(int _numSamples);
345 
347  int samples() const {return samples_;}
348 
349 private:
350 
351  int samples_;
352 
353  QStringList macros_;
354 };
355 
356 
357 class ACGDLLEXPORT PoissonBlurFilter
358 {
359 public:
360 
361  /* \brief Create poisson blur filter
362  *
363  * @param _radius radius of poisson disk
364  * @param _sampleDistance min distance between two samples
365  * @param _numTries number of tries per sample to find the next sample
366  */
367  PoissonBlurFilter(float _radius, float _sampleDistance, int _numTries = 30);
368 
370  virtual ~PoissonBlurFilter();
371 
372  /* \brief Perform poisson blur
373  *
374  * Writes to currently bound render target.
375  *
376  * @param _srcTex input 2d texture
377  * @param _kernelScale kernel radius scaling factor
378  */
379  bool execute(GLuint _srcTex, float _kernelScale = 1.0f);
380 
381 
383  float radius() const {return radius_;}
384 
386  int numSamples() const {return int(samples_.size());}
387 
389  float sampleDistance() const {return sampleDistance_;}
390 
392  int numTries() const {return numTries_;}
393 
395  const std::vector<ACG::Vec2f>& samples() const {return samples_;}
396 
398  void dumpSamples(const char* _filename);
399 
401  void plotSamples(QImage* _image);
402 
403 private:
404 
405  // sampling settings
406  float radius_;
407  float sampleDistance_;
408  int numTries_;
409 
410  // poisson disk
411  std::vector<ACG::Vec2f> samples_;
412 
413  // scaled samples
414  std::vector<ACG::Vec2f> samplesScaled_;
415 
416  // shader macros
417  QStringList macros_;
418 };
419 
420 
421 
422 }
int samples() const
number of samples
const ACG::Vec2f & texelSize() const
texel size in uv space
int radius() const
radius
const std::vector< ACG::Vec2f > & samples() const
disk sample offsets
std::vector< ACG::Vec2f > offsetsX_
filter taps
int samples() const
number of samples
const std::vector< ACG::Vec2f > & offsetsX() const
sample offsets along x direction
std::vector< ACG::Vec2f > offsetsX_
filter taps
Definition: FBO.hh:83
GLenum internalFormat() const
internal format of the input texture
QStringList macros_
shader macros
std::vector< float > weights_
kernel weights
int numSamples() const
number of samples
float radius() const
radius
const std::vector< float > & weights() const
sample weights
const ACG::Vec2f & sigma() const
blur (sigmaS, sigmaR)
int sigma() const
blur sigma
virtual ~RadialBlurFilter()
Class destructor.
int numTries() const
number of iterations per sample
const std::vector< ACG::Vec2f > & offsetsX() const
sample offsets along x direction
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::Vec2f sigma_
(sigmaS, sigmaR)
int radius() const
radius
const std::vector< ACG::Vec2f > & offsetsY() const
sample offsets along y direction
ACG::Vec2f sigma2Rcp_
-1 / (2 * sigma^2)
float sampleDistance() const
min distance between two samples
std::vector< float > spatialKernel_
precomputed sample -r^2 / (2 * sigma_s^2)
QStringList macros_
shader macros
int texWidth() const
input texture width
GLSL program class.
Definition: GLSLShader.hh:217
int samples() const
number of samples
int texHeight() const
input texture height
const std::vector< ACG::Vec2f > & offsetsY() const
sample offsets along y direction