51 #include <ACG/GL/ShaderCache.hh> 52 #include <ACG/GL/ScreenQuad.hh> 53 #include <ACG/GL/GLFormatInfo.hh> 54 #include <ACG/ShaderUtils/GLSLShader.hh> 56 #include <ACG/GL/FBO.hh> 58 #include "FilterKernels.hh" 69 BaseSeparableFilterKernel::BaseSeparableFilterKernel(
int _texWidth,
int _texHeight, GLenum _internalfmt )
70 : texWidth_(_texWidth),
71 texHeight_(_texHeight),
72 internalfmt_(_internalfmt),
73 externalfmt_(_internalfmt),
77 texelSize_ =
ACG::Vec2f(1.0f /
float(_texWidth), 1.0f /
float(_texHeight));
87 bool BaseSeparableFilterKernel::execute( GLuint _srcTexture,
ACG::FBO* _dstFBO, GLuint _dstColorAttachment, GLuint _tempColorAttachment )
91 GLuint tempTexture = 0;
92 if (!_dstFBO || !_tempColorAttachment)
94 tempTexture = tempRT_->getAttachment(GL_COLOR_ATTACHMENT0);
98 tempRT_->attachTexture2D(GL_COLOR_ATTACHMENT0, texWidth_, texHeight_, internalfmt_, externalfmt_, GL_CLAMP, GL_LINEAR, GL_LINEAR);
100 tempTexture = tempRT_->getAttachment(GL_COLOR_ATTACHMENT0);
112 glGetIntegerv(GL_VIEWPORT, vp);
113 glViewport(0, 0, texWidth_, texHeight_);
118 if (_tempColorAttachment && _dstFBO)
121 glDrawBuffer(_tempColorAttachment);
127 glDrawBuffer(GL_COLOR_ATTACHMENT0);
145 if (_dstFBO && _dstColorAttachment)
148 glDrawBuffer(_dstColorAttachment);
158 passShader = setupPass(1, tempTexture);
168 glViewport(vp[0], vp[1], vp[2], vp[3]);
173 void BaseSeparableFilterKernel::resizeInput(
int _texWidth,
int _texHeight )
175 if ( (texWidth_ != _texWidth || texHeight_ != _texHeight) )
177 texWidth_ = _texWidth;
178 texHeight_ = _texHeight;
179 texelSize_ =
ACG::Vec2f(1.0f /
float(_texWidth), 1.0f /
float(_texHeight));
181 if (tempRT_->width())
182 tempRT_->resize(_texWidth, _texHeight);
191 GaussianBlurFilter::GaussianBlurFilter(
int _texWidth,
195 GLenum _internalfmt )
197 radius_(_blurRadius),
210 void GaussianBlurFilter::updateKernel()
221 weights_[radius_] = 1.0f;
223 float weightSum = 1.0f;
226 for (
int i = 0; i < radius_; ++i)
231 offsetsX_[radius_ + i + 1] =
ACG::Vec2f(v[0], 0.0f);
234 offsetsY_[radius_ + i + 1] =
ACG::Vec2f(0.0f, v[1]);
237 float w = expf(-
float((i+1)*(i+1)) / (sigma_ * sigma_));
238 weights_[radius_ + i + 1] = weights_[i] = w;
239 weightSum += 2.0f * w;
245 weights_[i] /= weightSum;
247 QString blurSamplesMacro;
248 blurSamplesMacro.sprintf(
"#define BLUR_SAMPLES %i", samples_);
250 macros_.push_back(blurSamplesMacro);
255 void GaussianBlurFilter::setKernel(
int _blurRadius,
float _blurSigma )
257 radius_ = _blurRadius;
262 GLSL::Program* GaussianBlurFilter::setupPass(
int _pass, GLuint _srcTex)
276 glActiveTexture(GL_TEXTURE0);
277 glBindTexture(GL_TEXTURE_2D, _srcTex);
285 glBindTexture(GL_TEXTURE_2D, _srcTex);
295 BilateralBlurFilter::BilateralBlurFilter(
int _texWidth,
int _texHeight,
301 radius_(_blurRadius),
303 sigma_(_blurSigmaS, _blurSigmaR),
315 void BilateralBlurFilter::updateKernel()
319 sigma2Rcp_ =
ACG::Vec2f(-1.0f / (2.0f * sigma_[0] * sigma_[0]),
320 -1.0f / (2.0f * sigma_[1] * sigma_[1]));
333 spatialKernel_[radius_] = 0.0f;
336 for (
int i = 0; i < radius_; ++i)
341 offsetsX_[radius_ + i + 1] =
ACG::Vec2f(v[0], 0.0f);
344 offsetsY_[radius_ + i + 1] =
ACG::Vec2f(0.0f, v[1]);
347 float r2 = float((i+1)*(i+1));
348 spatialKernel_[radius_ + i + 1] = spatialKernel_[i] = r2 * sigma2Rcp_[0];
355 radiusMacro.sprintf(
"#define BLUR_SAMPLES %i",
samples_);
357 int numChannels =
GLFormatInfo(internalFormat()).channelCount();
358 numChannels = std::max(std::min(numChannels, 4), 1);
360 const char* blurChannels[4] =
368 QString channelMacro;
369 channelMacro.sprintf(
"#define BLUR_CHANNELS %s", blurChannels[numChannels - 1]);
371 macros_.push_back(radiusMacro);
372 macros_.push_back(channelMacro);
375 void BilateralBlurFilter::setKernel(
int _blurRadius,
float _blurSigmaS,
float _blurSigmaR )
377 radius_ = _blurRadius;
378 sigma_ =
ACG::Vec2f(_blurSigmaS, _blurSigmaR);
382 GLSL::Program* BilateralBlurFilter::setupPass(
int _pass, GLuint _srcTex)
396 blurShader->
setUniform(
"g_BlurSigmaRcp2", sigma2Rcp_[1]);
400 glActiveTexture(GL_TEXTURE1);
401 glBindTexture(GL_TEXTURE_2D, depthTex_);
403 glActiveTexture(GL_TEXTURE0);
404 glBindTexture(GL_TEXTURE_2D, _srcTex);
412 glBindTexture(GL_TEXTURE_2D, _srcTex);
422 RadialBlurFilter::RadialBlurFilter(
int _numSamples )
425 setKernel(_numSamples);
428 bool RadialBlurFilter::execute( GLuint _srcTexture,
float _blurRadius,
float _blurIntensity,
const ACG::Vec2f& _blurCenter )
434 glActiveTexture(GL_TEXTURE0);
435 glBindTexture(GL_TEXTURE_2D, _srcTexture);
441 blurShader->
setUniform(
"g_BlurCenter", _blurCenter);
442 blurShader->
setUniform(
"g_BlurRadiusRcp2", 1.0f / (_blurRadius * _blurRadius));
443 blurShader->
setUniform(
"g_BlurIntensity", _blurIntensity);
453 void RadialBlurFilter::setKernel(
int _numSamples )
459 sampleMacro.sprintf(
"#define BLUR_SAMPLES %i", _numSamples);
460 macros_.push_back(sampleMacro);
467 PoissonBlurFilter::PoissonBlurFilter(
float _radius,
float _sampleDistance,
int _numTris )
468 : radius_(_radius), sampleDistance_(_sampleDistance), numTries_(_numTris)
481 float cellSize = _sampleDistance / sqrtf(2.0f);
483 int gridSize = int(2.0f * _radius / cellSize) + 1;
485 std::vector<int> grid(gridSize * gridSize, -1);
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);
499 x0 = x0 * 2.0f * _radius;
501 std::list<int> activeList;
505 activeList.push_back(0);
508 ACG::Vec2i gridPos0(
int(x0[0] / cellSize),
int(x0[1] / cellSize));
510 grid[gridPos0[1] * gridSize + gridPos0[0]] = 0;
515 float sampleDistance2 = _sampleDistance * _sampleDistance;
517 while (!activeList.empty())
519 int listSize = activeList.size();
521 int i = int((
float(rand()) /
float(RAND_MAX)) *
float(listSize) + 0.5f);
523 i = std::min(i, listSize - 1);
527 std::list<int>::iterator it_i = activeList.begin();
528 for (
int counter = 0; it_i != activeList.end(); ++it_i, ++counter)
539 ACG::Vec2i gridPos_i(
int(x_i[0] / cellSize),
int(x_i[1] / cellSize));
541 bool foundNextSample_i =
false;
544 for (
int s = 0; s < _numTris; ++s)
546 float u = float(rand()) / float(RAND_MAX);
547 float v = float(rand()) / float(RAND_MAX);
549 float alpha = float(M_PI) * 2.0f * u;
553 x_s *= _sampleDistance + 2.0f * _sampleDistance * v;
558 ACG::Vec2i gridPos_s(
int(x_s[0] / cellSize),
int(x_s[1] / cellSize));
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)
565 if ( (x_s -
ACG::Vec2f(_radius, _radius)).sqrnorm() > _radius*_radius)
570 bool tooClose =
false;
572 for (
int x = -1; x <= 1 && !tooClose; ++x)
574 for (
int y = -1; y <= 1 && !tooClose; ++y)
579 if (gridPos_t[0] < 0 || gridPos_t[0] >= gridSize || gridPos_t[1] < 0 || gridPos_t[1] >= gridSize)
582 int gridValue = grid[gridPos_t[1] * gridSize + gridPos_t[0]];
587 float d2 = delta_t | delta_t;
589 if (d2 < sampleDistance2)
598 foundNextSample_i =
true;
600 grid[gridPos_s[1] * gridSize + gridPos_s[0]] = numSamples;
603 activeList.push_back(numSamples);
609 if (!foundNextSample_i)
612 activeList.erase(it_i);
618 for (
int i = 0; i < numSamples; ++i)
624 QString samplesMacro;
625 samplesMacro.sprintf(
"#define BLUR_SAMPLES %i", numSamples);
626 macros_.push_back(samplesMacro);
637 std::fstream f(_filename, std::ios_base::out);
641 for (
size_t i = 0; i <
samples_.size(); ++i)
648 bool PoissonBlurFilter::execute( GLuint _srcTex,
float _kernelScale )
651 int n = numSamples();
652 for (
int i = 0; i < n; ++i)
653 samplesScaled_[i] =
samples_[i] * _kernelScale;
661 blurShader->
setUniform(
"g_SampleOffsets", &samplesScaled_[0], n);
663 glActiveTexture(GL_TEXTURE0);
664 glBindTexture(GL_TEXTURE_2D, _srcTex);
677 const int crossRadius = 2;
681 int w = _image->width(),
682 h = _image->height();
684 _image->fill(qRgb(255,255,255));
688 plotter.begin(_image);
689 plotter.setPen(QPen(qRgb(0,0,0)));
690 plotter.drawEllipse(0, 0, _image->width()-1, _image->height()-1);
694 for (
int i = 0; i < numSamples(); ++i)
699 s = s * 0.5f +
Vec2f(0.5f, 0.5f);
705 Vec2i pc(s[0] + 0.5f, s[1] + 0.5f);
707 for (
int k = -crossRadius; k <= crossRadius; ++k)
709 for (
int mirror = 0; mirror < 2; ++mirror)
711 Vec2i p = pc +
Vec2i(k * (mirror ? -1 : 1),k);
714 p[0] = std::min(std::max(p[0], 0), w-1);
715 p[1] = std::min(std::max(p[1], 0), h-1);
717 _image->setPixel(p[0], p[1], qRgb(255, 0, 0));
VectorT< float, 2 > Vec2f
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
GLsizei samples_
sample count if multisampling
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
bool bind()
bind the fbo and sets it as rendertarget
void dumpSamples(const char *_filename)
dump samples as point cloud in obj format
GLuint getAttachment(GLenum _attachment)
return attached texture id
virtual ~PoissonBlurFilter()
Class destructor.
void use()
Enables the program object for using.
VectorT< signed int, 2 > Vec2i
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Namespace providing different geometric functions concerning angles.
virtual ~BilateralBlurFilter()
Class destructor.
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
void unbind()
unbind fbo, go to normal rendering mode
virtual ~GaussianBlurFilter()
Class destructor.
void plotSamples(QImage *_image)
plot samples on qt image
virtual ~BaseSeparableFilterKernel()
Class destructor.