Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FilterKernels.cc
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
51 #include <ACG/GL/ShaderCache.hh>
52 #include <ACG/GL/ScreenQuad.hh>
53 #include <ACG/GL/GLFormatInfo.hh>
54 #include <ACG/ShaderUtils/GLSLShader.hh>
55
56 #include <ACG/GL/FBO.hh>
57
58 #include "FilterKernels.hh"
59
60 #include <QPainter>
61
62 #include <fstream>
63
64
65 namespace ACG
66 {
67
68
69 BaseSeparableFilterKernel::BaseSeparableFilterKernel( int _texWidth, int _texHeight, GLenum _internalfmt )
70 : texWidth_(_texWidth),
71 texHeight_(_texHeight),
72 internalfmt_(_internalfmt),
73 externalfmt_(_internalfmt),
74 tempRT_(new FBO())
75 {
76 externalfmt_ = ACG::GLFormatInfo(internalfmt_).format();
77 texelSize_ = ACG::Vec2f(1.0f / float(_texWidth), 1.0f / float(_texHeight));
78 }
79
80
81 BaseSeparableFilterKernel::~BaseSeparableFilterKernel()
82 {
83 delete tempRT_;
84 }
85
86
87 bool BaseSeparableFilterKernel::execute( GLuint _srcTexture, ACG::FBO* _dstFBO, GLuint _dstColorAttachment, GLuint _tempColorAttachment )
88 {
89 bool success = true;
90
91 GLuint tempTexture = 0;
92 if (!_dstFBO || !_tempColorAttachment)
93 {
94 tempTexture = tempRT_->getAttachment(GL_COLOR_ATTACHMENT0);
95
96 if (!tempTexture)
97 {
98 tempRT_->attachTexture2D(GL_COLOR_ATTACHMENT0, texWidth_, texHeight_, internalfmt_, externalfmt_, GL_CLAMP, GL_LINEAR, GL_LINEAR);
99
100 tempTexture = tempRT_->getAttachment(GL_COLOR_ATTACHMENT0);
101 }
102 }
103 else
104 {
105 tempTexture = _dstFBO->getAttachment(tempTexture);
106
107 if (!tempTexture)
108 return false;
109 }
110
111 GLint vp[4];
112 glGetIntegerv(GL_VIEWPORT, vp);
113 glViewport(0, 0, texWidth_, texHeight_);
114
115 // temp target
116
117 ACG::FBO* passFBO = 0;
118 if (_tempColorAttachment && _dstFBO)
119 {
120 _dstFBO->bind();
121 glDrawBuffer(_tempColorAttachment);
122 passFBO = _dstFBO;
123 }
124 else
125 {
126 tempRT_->bind();
127 glDrawBuffer(GL_COLOR_ATTACHMENT0);
128 passFBO = tempRT_;
129 }
130
131
132 // 1. pass
133
134 GLSL::Program* passShader = setupPass(0, _srcTexture);
135
136 if (passShader)
137 ACG::ScreenQuad::draw(passShader);
138 else
139 success = false;
140
141 passFBO->unbind();
142
143 // 2. pass
144
145 if (_dstFBO && _dstColorAttachment)
146 {
147 _dstFBO->bind();
148 glDrawBuffer(_dstColorAttachment);
149 passFBO = _dstFBO;
150 }
151 else
152 {
153 // render to previously bound fbo
154 passFBO = 0;
155 }
156
157
158 passShader = setupPass(1, tempTexture);
159
160 if (passShader)
161 ACG::ScreenQuad::draw(passShader);
162 else
163 success = false;
164
165 // restore input fbo
166 if (passFBO)
167 passFBO->unbind();
168 glViewport(vp[0], vp[1], vp[2], vp[3]);
169
170 return success;
171 }
172
173 void BaseSeparableFilterKernel::resizeInput( int _texWidth, int _texHeight )
174 {
175 if ( (texWidth_ != _texWidth || texHeight_ != _texHeight) )
176 {
177 texWidth_ = _texWidth;
178 texHeight_ = _texHeight;
179 texelSize_ = ACG::Vec2f(1.0f / float(_texWidth), 1.0f / float(_texHeight));
180
181 if (tempRT_->width())
182 tempRT_->resize(_texWidth, _texHeight);
183
184 updateKernel();
185 }
186 }
187
188 // ----------------------------------------------------------------------------
189
190
191 GaussianBlurFilter::GaussianBlurFilter( int _texWidth,
192 int _texHeight,
193 int _blurRadius,
194 float _blurSigma,
195 GLenum _internalfmt )
196 : BaseSeparableFilterKernel(_texWidth, _texHeight, _internalfmt),
197 radius_(_blurRadius),
198 samples_(2 * _blurRadius + 1),
199 sigma_(_blurSigma)
200 {
201 updateKernel();
202 }
203
204 GaussianBlurFilter::~GaussianBlurFilter()
205 {
206
207 }
208
209
210 void GaussianBlurFilter::updateKernel()
211 {
212 samples_ = radius_ * 2 + 1;
213
214 offsetsX_.resize(samples_);
215 offsetsY_.resize(samples_);
216 weights_.resize(samples_);
217
218 // center sample
219 offsetsX_[radius_] = ACG::Vec2f(0.0f, 0.0f);
220 offsetsY_[radius_] = ACG::Vec2f(0.0f, 0.0f);
221 weights_[radius_] = 1.0f;
222
223 float weightSum = 1.0f; // 1.0 is the weight of the center sample
224
225 // left and right taps
226 for (int i = 0; i < radius_; ++i)
227 {
228 // offset
229 ACG::Vec2f v = texelSize() * float(i + 1);
230 offsetsX_[i] = ACG::Vec2f(-v[0], 0.0f);
231 offsetsX_[radius_ + i + 1] = ACG::Vec2f(v[0], 0.0f);
232
233 offsetsY_[i] = ACG::Vec2f(0.0f, -v[1]);
234 offsetsY_[radius_ + i + 1] = ACG::Vec2f(0.0f, v[1]);
235
236 // weight
237 float w = expf(-float((i+1)*(i+1)) / (sigma_ * sigma_));
238 weights_[radius_ + i + 1] = weights_[i] = w;
239 weightSum += 2.0f * w;
240 }
241
242
243 // normalize
244 for (int i = 0; i < samples_; ++i)
245 weights_[i] /= weightSum;
246
247 QString blurSamplesMacro;
248 blurSamplesMacro.sprintf("#define BLUR_SAMPLES %i", samples_);
249 macros_.clear();
250 macros_.push_back(blurSamplesMacro);
251 }
252
253
254
255 void GaussianBlurFilter::setKernel( int _blurRadius, float _blurSigma )
256 {
257 radius_ = _blurRadius;
258 sigma_ = _blurSigma;
259 updateKernel();
260 }
261
262 GLSL::Program* GaussianBlurFilter::setupPass(int _pass, GLuint _srcTex)
263 {
264 GLSL::Program* blurShader = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Blur/kernel.glsl", &macros_);
265
266 if (_pass == 0)
267 {
268 // 1. pass horizontal blur
269
270 blurShader->use();
271
272 blurShader->setUniform("g_InputTex", 0);
273 blurShader->setUniform("g_SampleOffsets", &offsetsX_[0], samples_);
274 blurShader->setUniform("g_SampleWeights", &weights_[0], samples_);
275
276 glActiveTexture(GL_TEXTURE0);
277 glBindTexture(GL_TEXTURE_2D, _srcTex);
278 }
279 else
280 {
281 // 2. pass vertical blur
282
283 blurShader->setUniform("g_SampleOffsets", &offsetsY_[0], samples_);
284
285 glBindTexture(GL_TEXTURE_2D, _srcTex);
286 }
287
288 return blurShader;
289 }
290
291
292 // ----------------------------------------------------------------------------
293
294
295 BilateralBlurFilter::BilateralBlurFilter(int _texWidth, int _texHeight,
296 int _blurRadius,
297 float _blurSigmaS,
298 float _blurSigmaR,
299 GLenum _internalfmt)
300 : BaseSeparableFilterKernel(_texWidth, _texHeight, _internalfmt),
301 radius_(_blurRadius),
302 samples_(2 * _blurRadius + 1),
303 sigma_(_blurSigmaS, _blurSigmaR),
304 depthTex_(0)
305 {
306 updateKernel();
307 }
308
309 BilateralBlurFilter::~BilateralBlurFilter()
310 {
311
312 }
313
314
315 void BilateralBlurFilter::updateKernel()
316 {
317 samples_ = radius_ * 2 + 1;
318
319 sigma2Rcp_ = ACG::Vec2f(-1.0f / (2.0f * sigma_[0] * sigma_[0]),
320 -1.0f / (2.0f * sigma_[1] * sigma_[1]));
321
322
323 // compute filter kernel
324
325 offsetsX_.resize(samples_);
326 offsetsY_.resize(samples_);
327 spatialKernel_.resize(samples_);
328
329
330 // center sample
331 offsetsX_[radius_] = ACG::Vec2f(0.0f, 0.0f);
332 offsetsY_[radius_] = ACG::Vec2f(0.0f, 0.0f);
333 spatialKernel_[radius_] = 0.0f;
334
335 // left and right taps
336 for (int i = 0; i < radius_; ++i)
337 {
338 // offset
339 ACG::Vec2f v = texelSize() * float(i + 1);
340 offsetsX_[i] = ACG::Vec2f(-v[0], 0.0f);
341 offsetsX_[radius_ + i + 1] = ACG::Vec2f(v[0], 0.0f);
342
343 offsetsY_[i] = ACG::Vec2f(0.0f, -v[1]);
344 offsetsY_[radius_ + i + 1] = ACG::Vec2f(0.0f, v[1]);
345
346 // spatial kernel
347 float r2 = float((i+1)*(i+1));
348 spatialKernel_[radius_ + i + 1] = spatialKernel_[i] = r2 * sigma2Rcp_[0];
349 }
350
351
352 macros_.clear();
353
354 QString radiusMacro;
355 radiusMacro.sprintf("#define BLUR_SAMPLES %i", samples_);
356
357 int numChannels = GLFormatInfo(internalFormat()).channelCount();
358 numChannels = std::max(std::min(numChannels, 4), 1);
359
360 const char* blurChannels[4] =
361 {
362 "BLUR_R",
363 "BLUR_RG",
364 "BLUR_RGB",
365 "BLUR_RGBA"
366 };
367
368 QString channelMacro;
369 channelMacro.sprintf("#define BLUR_CHANNELS %s", blurChannels[numChannels - 1]);
370
371 macros_.push_back(radiusMacro);
372 macros_.push_back(channelMacro);
373 }
374
375 void BilateralBlurFilter::setKernel( int _blurRadius, float _blurSigmaS, float _blurSigmaR )
376 {
377 radius_ = _blurRadius;
378 sigma_ = ACG::Vec2f(_blurSigmaS, _blurSigmaR);
379 updateKernel();
380 }
381
382 GLSL::Program* BilateralBlurFilter::setupPass(int _pass, GLuint _srcTex)
383 {
384 GLSL::Program* blurShader = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Blur/bilateral.glsl", &macros_);
385
386 if (_pass == 0)
387 {
388 // 1. pass horizontal blur
389
390 blurShader->use();
391
392 blurShader->setUniform("g_InputTex", 0);
393 blurShader->setUniform("g_DepthTex", 1);
394 blurShader->setUniform("g_P", proj_);
395
396 blurShader->setUniform("g_BlurSigmaRcp2", sigma2Rcp_[1]);
397 blurShader->setUniform("g_SampleOffsets", &offsetsX_[0], samples_);
398 blurShader->setUniform("g_SpatialKernel", &spatialKernel_[0], samples_);
399
400 glActiveTexture(GL_TEXTURE1);
401 glBindTexture(GL_TEXTURE_2D, depthTex_);
402
403 glActiveTexture(GL_TEXTURE0);
404 glBindTexture(GL_TEXTURE_2D, _srcTex);
405 }
406 else
407 {
408 // 2. pass vertical blur
409
410 blurShader->setUniform("g_SampleOffsets", &offsetsY_[0], samples_);
411
412 glBindTexture(GL_TEXTURE_2D, _srcTex);
413 }
414
415 return blurShader;
416 }
417
418
419 // ----------------------------------------------------------------------------
420
421
422 RadialBlurFilter::RadialBlurFilter( int _numSamples )
423 : samples_(0)
424 {
425 setKernel(_numSamples);
426 }
427
428 bool RadialBlurFilter::execute( GLuint _srcTexture, float _blurRadius, float _blurIntensity, const ACG::Vec2f& _blurCenter )
429 {
430 GLSL::Program* blurShader = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Blur/radial.glsl", &macros_);
431
432 if (blurShader)
433 {
434 glActiveTexture(GL_TEXTURE0);
435 glBindTexture(GL_TEXTURE_2D, _srcTexture);
436
437
438 blurShader->use();
439
440 blurShader->setUniform("g_InputTex", 0);
441 blurShader->setUniform("g_BlurCenter", _blurCenter);
442 blurShader->setUniform("g_BlurRadiusRcp2", 1.0f / (_blurRadius * _blurRadius));
443 blurShader->setUniform("g_BlurIntensity", _blurIntensity);
444
445 ACG::ScreenQuad::draw(blurShader);
446
447 return true;
448 }
449
450 return false;
451 }
452
453 void RadialBlurFilter::setKernel( int _numSamples )
454 {
455 samples_ = _numSamples;
456
457 macros_.clear();
458 QString sampleMacro;
459 sampleMacro.sprintf("#define BLUR_SAMPLES %i", _numSamples);
460 macros_.push_back(sampleMacro);
461 }
462
463
464 // ----------------------------------------------------------------------------
465
466
467 PoissonBlurFilter::PoissonBlurFilter( float _radius, float _sampleDistance, int _numTris /*= 30*/ )
468 : radius_(_radius), sampleDistance_(_sampleDistance), numTries_(_numTris)
469 {
470 // "Fast Poisson Disk Sampling in Arbitrary Dimensions"
471 // http://people.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf
472
473 // rejection test for disk domain
474
475 // domain during generation is [0, 2 * radius]
476 // this is mapped to [-radius, radius] afterwards
477
478 // step 0.
479
480 // r = sampleDistance, n = 2
481 float cellSize = _sampleDistance / sqrtf(2.0f);
482
483 int gridSize = int(2.0f * _radius / cellSize) + 1; // account for partially sized cell at the end
484
485 std::vector<int> grid(gridSize * gridSize, -1);
486
487
488
489 // step 1.
490
491 ACG::Vec2f x0(0.0f, 0.0f);
492
493 // initial uniform sample in disk
494 do
495 {
496 x0 = ACG::Vec2f(float(rand()) / float(RAND_MAX), float(rand()) / float(RAND_MAX));
497 } while ((x0 * 2.0f - ACG::Vec2f(1.0f, 1.0f)).sqrnorm() > _radius*_radius);
498
499 x0 = x0 * 2.0f * _radius;
500
501 std::list<int> activeList;
502
503 samples_.reserve(32);
504 samples_.push_back(x0);
505 activeList.push_back(0);
506 int numSamples = 1;
507
508 ACG::Vec2i gridPos0(int(x0[0] / cellSize), int(x0[1] / cellSize));
509
510 grid[gridPos0[1] * gridSize + gridPos0[0]] = 0;
511
512
513 // step 2.
514
515 float sampleDistance2 = _sampleDistance * _sampleDistance;
516
517 while (!activeList.empty())
518 {
519 int listSize = activeList.size();
520 // random index i
521 int i = int((float(rand()) / float(RAND_MAX)) * float(listSize) + 0.5f);
522
523 i = std::min(i, listSize - 1);
524
525 // int sample_i = activeList[i];
526 int sample_i = -1;
527 std::list<int>::iterator it_i = activeList.begin();
528 for (int counter = 0; it_i != activeList.end(); ++it_i, ++counter)
529 {
530 if (counter == i)
531 {
532 sample_i = *it_i;
533 break;
534 }
535 }
536
537 ACG::Vec2f x_i = samples_[sample_i];
538
539 ACG::Vec2i gridPos_i(int(x_i[0] / cellSize), int(x_i[1] / cellSize));
540
541 bool foundNextSample_i = false;
542
543 // k uniform point samples in circle around x_i
544 for (int s = 0; s < _numTris; ++s)
545 {
546 float u = float(rand()) / float(RAND_MAX);
547 float v = float(rand()) / float(RAND_MAX);
548
549 float alpha = float(M_PI) * 2.0f * u;
550 ACG::Vec2f x_s(cosf(alpha), sinf(alpha));
551
552 // between r and 2r, where r = sample distance
553 x_s *= _sampleDistance + 2.0f * _sampleDistance * v;
554
555 // centered around x_i
556 x_s += x_i;
557
558 ACG::Vec2i gridPos_s(int(x_s[0] / cellSize), int(x_s[1] / cellSize));
559
560 // oob check
561 if (x_s[0] < 0.0f || x_s[1] < 0.0f || gridPos_s[0] < 0 || gridPos_s[0] >= gridSize || gridPos_s[1] < 0 || gridPos_s[1] >= gridSize)
562 continue;
563
564 // disk check
565 if ( (x_s - ACG::Vec2f(_radius, _radius)).sqrnorm() > _radius*_radius)
566 continue;
567
568 // neighborhood check
569
570 bool tooClose = false;
571
572 for (int x = -1; x <= 1 && !tooClose; ++x)
573 {
574 for (int y = -1; y <= 1 && !tooClose; ++y)
575 {
576 ACG::Vec2i gridPos_t = gridPos_s + ACG::Vec2i(x,y);
577
578 // oob check
579 if (gridPos_t[0] < 0 || gridPos_t[0] >= gridSize || gridPos_t[1] < 0 || gridPos_t[1] >= gridSize)
580 continue;
581
582 int gridValue = grid[gridPos_t[1] * gridSize + gridPos_t[0]];
583
584 if (gridValue >= 0)
585 {
586 ACG::Vec2f delta_t = samples_[gridValue] - x_s;
587 float d2 = delta_t | delta_t;
588
589 if (d2 < sampleDistance2)
590 tooClose = true;
591 }
592 }
593 }
594
595 if (!tooClose)
596 {
597 // new sample found
598 foundNextSample_i = true;
599
600 grid[gridPos_s[1] * gridSize + gridPos_s[0]] = numSamples;
601 samples_.push_back(x_s);
602
603 activeList.push_back(numSamples);
604
605 ++numSamples;
606 }
607 }
608
609 if (!foundNextSample_i)
610 {
611 // remove from list
612 activeList.erase(it_i);
613 }
614
615 }
616
617 // map to [-radius, radius]
618 for (int i = 0; i < numSamples; ++i)
619 samples_[i] = samples_[i] - ACG::Vec2f(_radius, _radius);
620
621 samplesScaled_ = samples_;
622
623
624 QString samplesMacro;
625 samplesMacro.sprintf("#define BLUR_SAMPLES %i", numSamples);
626 macros_.push_back(samplesMacro);
627 }
628
629 PoissonBlurFilter::~PoissonBlurFilter()
630 {
631
632 }
633
634
635 void PoissonBlurFilter::dumpSamples( const char* _filename )
636 {
637 std::fstream f(_filename, std::ios_base::out);
638
639 if (f.is_open())
640 {
641 for (size_t i = 0; i < samples_.size(); ++i)
642 f << "v " << samples_[i][0] << " " << samples_[i][1] << " 0" << std::endl;
643
644 f.close();
645 }
646 }
647
648 bool PoissonBlurFilter::execute( GLuint _srcTex, float _kernelScale )
649 {
650 // scale kernel
651 int n = numSamples();
652 for (int i = 0; i < n; ++i)
653 samplesScaled_[i] = samples_[i] * _kernelScale;
654
655 GLSL::Program* blurShader = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Blur/poisson.glsl", &macros_);
656
657 if (blurShader)
658 {
659 blurShader->use();
660 blurShader->setUniform("g_InputTex", 0);
661 blurShader->setUniform("g_SampleOffsets", &samplesScaled_[0], n);
662
663 glActiveTexture(GL_TEXTURE0);
664 glBindTexture(GL_TEXTURE_2D, _srcTex);
665
666 ACG::ScreenQuad::draw(blurShader);
667
668 return true;
669 }
670
671 return false;
672 }
673
674 void PoissonBlurFilter::plotSamples( QImage* _image )
675 {
676 // cross radius of samples in image
677 const int crossRadius = 2;
678
679 if (_image)
680 {
681 int w = _image->width(),
682 h = _image->height();
683
684 _image->fill(qRgb(255,255,255));
685
686 // draw outer circle
687 QPainter plotter;
688 plotter.begin(_image);
689 plotter.setPen(QPen(qRgb(0,0,0)));
690 plotter.drawEllipse(0, 0, _image->width()-1, _image->height()-1);
691 plotter.end();
692
693 // draw samples
694 for (int i = 0; i < numSamples(); ++i)
695 {
696 // map sample pos to [0,1]
697 Vec2f s = samples_[i];
698 s /= radius_;
699 s = s * 0.5f + Vec2f(0.5f, 0.5f);
700
701 // map to [0, imageSize]
702 s *= Vec2f(w-1,h-1);
703
704 // draw cross for samples
705 Vec2i pc(s[0] + 0.5f, s[1] + 0.5f); // pixel center
706
707 for (int k = -crossRadius; k <= crossRadius; ++k)
708 {
709 for (int mirror = 0; mirror < 2; ++mirror)
710 {
711 Vec2i p = pc + Vec2i(k * (mirror ? -1 : 1),k);
712
713 // clamp to image size
714 p[0] = std::min(std::max(p[0], 0), w-1);
715 p[1] = std::min(std::max(p[1], 0), h-1);
716
717 _image->setPixel(p[0], p[1], qRgb(255, 0, 0));
718 }
719 }
720 }
721 }
722 }
723
724
725 }
ACG::BilateralBlurFilter::offsetsX_
std::vector< ACG::Vec2f > offsetsX_
filter taps
Definition: FilterKernels.hh:300
ACG::Vec2f
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
ACG
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
ACG::Vec2i
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:104
ACG::GaussianBlurFilter::sigma_
float sigma_
blur std
Definition: FilterKernels.hh:213
ACG::BaseSeparableFilterKernel::texelSize
const ACG::Vec2f & texelSize() const
texel size in uv space
Definition: FilterKernels.hh:120
ACG::BilateralBlurFilter::spatialKernel_
std::vector< float > spatialKernel_
precomputed sample -r^2 / (2 * sigma_s^2)
Definition: FilterKernels.hh:304
ACG::FBO::attachTexture2D
void attachTexture2D(GLenum _attachment, GLsizei _width, GLsizei _height, GLuint _internalFmt, GLenum _format, GLint _wrapMode=GL_CLAMP, GLint _minFilter=GL_NEAREST, GLint _magFilter=GL_NEAREST)
function to attach a texture to fbo
Definition: FBO.cc:200
ACG::FBO::width
GLsizei width() const
get width of fbo texture
Definition: FBO.hh:161
ACG::ScreenQuad::draw
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
ACG::GLFormatInfo
Definition: GLFormatInfo.hh:78
ACG::FBO
Definition: FBO.hh:83
ACG::PoissonBlurFilter::plotSamples
void plotSamples(QImage *_image)
plot samples on qt image
Definition: FilterKernels.cc:674
ACG::GaussianBlurFilter::~GaussianBlurFilter
virtual ~GaussianBlurFilter()
Class destructor.
Definition: FilterKernels.cc:204
ACG::BilateralBlurFilter::~BilateralBlurFilter
virtual ~BilateralBlurFilter()
Class destructor.
Definition: FilterKernels.cc:309
ACG::BaseSeparableFilterKernel::~BaseSeparableFilterKernel
virtual ~BaseSeparableFilterKernel()
Class destructor.
Definition: FilterKernels.cc:81
ACG::PoissonBlurFilter::numSamples
int numSamples() const
number of samples
Definition: FilterKernels.hh:386
ACG::ShaderCache::getProgram
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
GLSL::Program::use
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
ACG::FBO::resize
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
Definition: FBO.cc:543
ACG::FBO::getAttachment
GLuint getAttachment(GLenum _attachment)
return attached texture id
Definition: FBO.cc:529
ACG::GaussianBlurFilter::macros_
QStringList macros_
shader macros
Definition: FilterKernels.hh:216
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::BilateralBlurFilter::sigma_
ACG::Vec2f sigma_
(sigmaS, sigmaR)
Definition: FilterKernels.hh:294
ACG::ShaderCache::getInstance
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
ACG::BaseSeparableFilterKernel::internalFormat
GLenum internalFormat() const
internal format of the input texture
Definition: FilterKernels.hh:123
ACG::GaussianBlurFilter::weights_
std::vector< float > weights_
kernel weights
Definition: FilterKernels.hh:223
GLSL::Program::setUniform
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:217
ACG::GaussianBlurFilter::offsetsX_
std::vector< ACG::Vec2f > offsetsX_
filter taps
Definition: FilterKernels.hh:219
ACG::FBO::unbind
void unbind()
unbind fbo, go to normal rendering mode
Definition: FBO.cc:474
ACG::BilateralBlurFilter::macros_
QStringList macros_
shader macros
Definition: FilterKernels.hh:307
ACG::PoissonBlurFilter::dumpSamples
void dumpSamples(const char *_filename)
dump samples as point cloud in obj format
Definition: FilterKernels.cc:635
ACG::FBO::bind
bool bind()
bind the fbo and sets it as rendertarget
Definition: FBO.cc:451
ACG::PoissonBlurFilter::~PoissonBlurFilter
virtual ~PoissonBlurFilter()
Class destructor.
Definition: FilterKernels.cc:629
ACG::BilateralBlurFilter::sigma2Rcp_
ACG::Vec2f sigma2Rcp_
-1 / (2 * sigma^2)
Definition: FilterKernels.hh:297