116 lines
3.6 KiB
C++
116 lines
3.6 KiB
C++
#include "textureblur.h"
|
|
#include "framebuffer.h"
|
|
#include "shader.h"
|
|
#include "shadersource.h"
|
|
#include "texture.h"
|
|
|
|
|
|
TextureBlur::TextureBlur(FrameBuffer* input, int downsampling, int textureId) :
|
|
m_input(input),
|
|
m_downsampling(downsampling),
|
|
horizontal(NULL),
|
|
vertical(NULL)
|
|
{
|
|
Texture* srcTexture = input->getTexture(textureId);
|
|
int nb_fbos = (downsampling+1)*2;
|
|
fbos = new FrameBuffer[nb_fbos];
|
|
Texture* tex = srcTexture;
|
|
for(int i=0; i<nb_fbos/2; ++i)
|
|
{
|
|
// ping FBOs
|
|
fbos[i].addTexture(tex, GL_COLOR_ATTACHMENT0);
|
|
fbos[i].initColorAttachments();
|
|
|
|
tex = new Texture(tex, false);
|
|
tex->setWrap(GL_CLAMP_TO_EDGE);
|
|
tex->setFiltering(GL_LINEAR);
|
|
// pong FBOs
|
|
fbos[i+nb_fbos/2].addTexture(tex, GL_COLOR_ATTACHMENT0);
|
|
fbos[i+nb_fbos/2].initColorAttachments();
|
|
|
|
if(i < nb_fbos-1)
|
|
{
|
|
tex = new Texture(tex, true);
|
|
tex->setWrap(GL_CLAMP_TO_EDGE);
|
|
tex->setFiltering(GL_LINEAR);
|
|
}
|
|
}
|
|
}
|
|
|
|
TextureBlur::~TextureBlur()
|
|
{
|
|
for(int i=1; i<(m_downsampling+1)*2; ++i)
|
|
delete(fbos[i].getTexture(0));
|
|
delete[](fbos);
|
|
}
|
|
|
|
void TextureBlur::setSource(ShaderSource* source)
|
|
{
|
|
std::vector<const char*> defines(1);
|
|
defines[0] = "HORIZONTAL_BLUR";
|
|
horizontal = source->compile(defines);
|
|
defines[0] = "VERTICAL_BLUR";
|
|
vertical = source->compile(defines);
|
|
uniformLocations[H_SAMPLER] = horizontal->getLocation("colorSampler");
|
|
uniformLocations[H_WIDTH] = horizontal->getLocation("width");
|
|
uniformLocations[H_HEIGHT] = horizontal->getLocation("height");
|
|
uniformLocations[V_SAMPLER] = vertical->getLocation("colorSampler");
|
|
uniformLocations[V_WIDTH] = vertical->getLocation("width");
|
|
uniformLocations[V_HEIGHT] = vertical->getLocation("height");
|
|
}
|
|
|
|
void TextureBlur::blur()
|
|
{
|
|
// downsampling
|
|
for(int i=0; i<m_downsampling; ++i)
|
|
{
|
|
FrameBuffer* src = fbos + i;
|
|
FrameBuffer* dst = fbos + (i + 1);
|
|
src->setTarget(GL_READ_FRAMEBUFFER);
|
|
src->bindFBO();
|
|
dst->setTarget(GL_DRAW_FRAMEBUFFER);
|
|
dst->bindFBO();
|
|
glBlitFramebuffer(0, 0,
|
|
src->getTexture(0)->getWidth(),
|
|
src->getTexture(0)->getHeight(),
|
|
0, 0,
|
|
dst->getTexture(0)->getWidth(),
|
|
dst->getTexture(0)->getHeight(),
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
|
}
|
|
|
|
// blurring
|
|
for(int i=0; i<m_downsampling+1; ++i)
|
|
{
|
|
FrameBuffer* ping = fbos + i;
|
|
FrameBuffer* pong = ping + (m_downsampling + 1);
|
|
Texture* tex = ping->getTexture(0);
|
|
glViewport(0, 0, tex->getWidth(), tex->getHeight());
|
|
|
|
// ping (horizontal blur)
|
|
horizontal->bind();
|
|
|
|
pong->bindFBO();
|
|
tex->bind(0);
|
|
horizontal->bindInteger(uniformLocations[H_SAMPLER], 0);
|
|
horizontal->bindInteger(uniformLocations[H_WIDTH], tex->getWidth());
|
|
horizontal->bindInteger(uniformLocations[H_HEIGHT], tex->getHeight());
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|
|
|
// pong (vertical blur)
|
|
vertical->bind();
|
|
ping->bindFBO();
|
|
tex = pong->getTexture(0);
|
|
tex->bind(0);
|
|
vertical->bindInteger(uniformLocations[V_SAMPLER], 0);
|
|
vertical->bindInteger(uniformLocations[V_WIDTH], tex->getWidth());
|
|
vertical->bindInteger(uniformLocations[V_HEIGHT], tex->getHeight());
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|
}
|
|
}
|
|
|
|
Texture* TextureBlur::getTexture(int downsamplingLevel)
|
|
{
|
|
return fbos[downsamplingLevel].getTexture(0);
|
|
}
|