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 #pragma once
45 
46 
47 #include <ACG/Config/ACGDefines.hh>
48 #include <ACG/Math/GLMatrixT.hh>
49 #include <ACG/GL/gl.hh>
50 
51 #include <QStringList>
52 #include <QImage>
53 #include <vector>
54 
55 
56 
57 // Forward Declaration
58 namespace GLSL
59 {
60  class Program;
61 }
62 
63 namespace ACG
64 {
65 
66 // Forward Declaration
67 class FBO;
68 
69 
70 
71 class ACGDLLEXPORT BaseSeparableFilterKernel
72 {
73 public:
74 
75  /* \brief Create separable filter
76  *
77  * @param _texWidth width of input texture
78  * @param _texHeight height of input texture
79  * @param _internalfmt internal gl format of the texture
80  */
81  BaseSeparableFilterKernel(int _texWidth, int _texHeight, GLenum _internalfmt = GL_RGBA);
82 
84  virtual ~BaseSeparableFilterKernel();
85 
86 
87  /* \brief Execute filter
88  *
89  * Perform the two filter passes.
90  * If a custom fbo and a _tempColorAttachment is provided, the first pass is
91  * rendered into that temporary render texture.
92  * If a custom fbo and a _dstColorAttachment is provided, the second pass is
93  * rendered into that destination render texture.
94  *
95  * If _dstFBO or _tempColorAttachment is invalid, an internal fbo is created as target for the first pass.
96  * If _dstFBO or _dstColorAttachment is invalid, the second pass renders into whatever is currently bound as render target.
97  *
98  * @param _srcTexture 2d input texture
99  * @param _dstFBO custom target fbo (optional)
100  * @param _dstColorAttachment target attachment of the custom target fbo (optional)
101  * @param _tempColorAttachment temporary attachment of the custom fbo, that is different from _dstColorAttachment (optional)
102  * @return true on success, false otherwise
103  */
104  bool execute(GLuint _srcTexture, ACG::FBO* _dstFBO = 0, GLuint _dstColorAttachment = GL_COLOR_ATTACHMENT0, GLuint _tempColorAttachment = 0);
105 
106 
107  /* \brief Resize input texture
108  *
109  * @param _texWidth new input texture width
110  * @param _texHeight new input texture height
111  */
112  void resizeInput(int _texWidth, int _texHeight);
113 
115  int texWidth() const {return texWidth_;}
116 
118  int texHeight() const {return texHeight_;}
119 
121  const ACG::Vec2f& texelSize() const {return texelSize_;}
122 
124  GLenum internalFormat() const {return internalfmt_;}
125 
126 protected:
127 
128  /* \brief Setup shader with uniforms
129  *
130  * @param _pass pass number: 0 or 1
131  * @param _scrTex source texture for pass
132  * @return shader program for screen quad
133  */
134  virtual GLSL::Program* setupPass(int _pass, GLuint _srcTex) = 0;
135 
136 
137  /* \brief Update kernel after resizing
138  *
139  */
140  virtual void updateKernel() = 0;
141 
142 private:
143 
144  int texWidth_,
145  texHeight_;
146 
147  GLenum internalfmt_,
148  externalfmt_;
149 
150  // size of a texel in uv space
151  ACG::Vec2f texelSize_;
152 
153  // temp render targets if none supplied by user
154  // attachment0 : target for first axis pass
155  ACG::FBO* tempRT_;
156 };
157 
158 
159 // separable 2d gaussian blur
161 {
162 public:
163 
164  /* \brief Create separable gauss filter
165  *
166  * @param _texWidth width of input texture
167  * @param _texHeight height of input texture
168  * @param _blurRadius radius in pixel coords of the blur kernel
169  * @param _blurSigma blur smoothness, standard deviation of the gaussian function
170  * @param _internalfmt internal gl format of the texture
171  */
172  GaussianBlurFilter(int _texWidth, int _texHeight, int _blurRadius, float _blurSigma = 1.0f, GLenum _internalfmt = GL_RGBA);
173 
175  virtual ~GaussianBlurFilter();
176 
177  /* \brief Change kernel settings
178  *
179  * @param _blurRadius new radius
180  * @param _blurSigma new sigma
181  */
182  void setKernel(int _blurRadius, float _blurSigma);
183 
185  int radius() const {return radius_;}
186 
188  int samples() const {return samples_;}
189 
191  int sigma() const {return sigma_;}
192 
194  const std::vector<ACG::Vec2f>& offsetsX() const {return offsetsX_;}
195 
197  const std::vector<ACG::Vec2f>& offsetsY() const {return offsetsY_;}
198 
200  const std::vector<float>& weights() const {return weights_;}
201 
202 protected:
203 
204  virtual GLSL::Program* setupPass(int _pass, GLuint _srcTex) override;
205 
206  void updateKernel() override;
207 
208 private:
209 
210  int radius_, 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) override;
285 
286  void updateKernel() override;
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  explicit 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  * @param _disk should samples lie inside a disk of radius r or inside square [-r/2, -r/2] x [r/2, r/2]
367  * @param _tilingCheck check min distance also across borders in a repeat-tiled kernel grid
368  */
369  PoissonBlurFilter(float _radius, float _sampleDistance, int _numTries = 30, bool _disk = true, bool _tilingCheck = false);
370 
372  virtual ~PoissonBlurFilter();
373 
374  /* \brief Perform poisson blur
375  *
376  * Writes to currently bound render target.
377  *
378  * @param _srcTex input 2d texture
379  * @param _kernelScale kernel radius scaling factor
380  */
381  bool execute(GLuint _srcTex, float _kernelScale = 1.0f);
382 
383 
385  float radius() const {return radius_;}
386 
388  int numSamples() const {return int(samples_.size());}
389 
391  float sampleDistance() const {return sampleDistance_;}
392 
394  int numTries() const {return numTries_;}
395 
397  bool disk() const { return disk_; }
398 
400  const std::vector<ACG::Vec2f>& samples() const {return samples_;}
401 
403  void dumpSamples(const char* _filename);
404 
406  void plotSamples(QImage* _image);
407 
408 private:
409 
410  // sampling settings
411  float radius_;
412  float sampleDistance_;
413  int numTries_;
414  bool disk_;
415 
416  // poisson disk
417  std::vector<ACG::Vec2f> samples_;
418 
419  // scaled samples
420  std::vector<ACG::Vec2f> samplesScaled_;
421 
422  // shader macros
423  QStringList macros_;
424 };
425 
426 
427 
428 }
const std::vector< float > & weights() const
sample weights
const std::vector< ACG::Vec2f > & offsetsY() const
sample offsets along y direction
int texWidth() const
input texture width
Definition: FBO.hh:71
const std::vector< ACG::Vec2f > & offsetsX() const
sample offsets along x direction
float sampleDistance() const
min distance between two samples
int numSamples() const
number of samples
Namespace providing different geometric functions concerning angles.
const std::vector< ACG::Vec2f > & offsetsY() const
sample offsets along y direction
const ACG::Vec2f & texelSize() const
texel size in uv space
GLenum internalFormat() const
internal format of the input texture
int texHeight() const
input texture height
virtual ~RadialBlurFilter()
Class destructor.
int sigma() const
blur sigma
QStringList macros_
shader macros
std::vector< float > weights_
kernel weights
const std::vector< ACG::Vec2f > & offsetsX() const
sample offsets along x direction
ACG::Vec2f sigma_
(sigmaS, sigmaR)
float radius() const
radius
std::vector< float > spatialKernel_
precomputed sample -r^2 / (2 * sigma_s^2)
GLSL program class.
Definition: GLSLShader.hh:211
int samples() const
number of samples
This namespace contains all the classes and functions for handling GLSL shader and program objects...
Definition: AntiAliasing.hh:66
bool disk() const
samples inside disk or square area
int radius() const
radius
int radius() const
radius
int samples() const
number of samples
std::vector< ACG::Vec2f > offsetsX_
filter taps
ACG::Vec2f sigma2Rcp_
-1 / (2 * sigma^2)
const std::vector< ACG::Vec2f > & samples() const
disk sample offsets
int numTries() const
number of iterations per sample
int samples() const
number of samples
const ACG::Vec2f & sigma() const
blur (sigmaS, sigmaR)
QStringList macros_
shader macros
std::vector< ACG::Vec2f > offsetsX_
filter taps