Эффект размытия изображения в шейдерах

Я хочу сделать эффекты изображения, такие как размытие экрана, в моей игре, но у меня проблема в том, что он слегка затемняет экран.

Вот класс для FBO

GLuint m_fbo;
GLuint m_fboTexture;
GLuint m_fboDepthBuffer;

void FBO::Initialize(float width, float height)
{
glGenFramebuffersEXT(1, &m_fbo);
glGenTextures(1, &m_fboTexture);
glGenRenderbuffersEXT(1, &m_fboDepthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_fboTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmapEXT(GL_TEXTURE_2D);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLuint)width, (GLuint)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_fboTexture, 0);

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_fboDepthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, (GLuint)width, (GLuint)height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_fboDepthBuffer);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glDisable(GL_TEXTURE_2D);
}

void FBO::Bind()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
}

void FBO::UnBind()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

void FBO::Clear()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

Вот как я настроил это в моем основном классе.

FBO m_fbo;//create an object

//initialize size
m_fbo.Initiliazie(screen_width, screen_height);

В моей функции рендеринга я делаю это

void Render()
{
SetShaderProgram();//start shader program

m_fbo.Bind();

SetShaderImageSampler("texture", 0, m_fbo.m_fboTexture);
SetShaderUniformVec2("size", (float)SCREEN_WIDTH, (float)SCREEN_HEIGHT);
SetShaderUniformInt("kernel_size", ksize);

//draws my texture
m_spriteBatch->Draw(RecTangle(0, 0, (float)SCREEN_WIDTH, (float)SCREEN_HEIGHT));

m_fbo.UnBind();

EndShaderProgram();//end shader program
}

Вот что делает функция SetShaderImageSampler:

void SetShaderImageSampler(char *sSamplerName, U32 nSlot, GLuint nHandle)
{
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0 + nSlot);
glBindTexture(GL_TEXTURE_2D, nHandle);
U32 nSamplerLoc = glGetUniformLocation(m_shaderProgram, sSamplerName);
glUniform1iARB(nSamplerLoc, nSlot);
}

Это мой розыгрыш

void SpriteBatch::Draw(RecTangle rect)
{
//draws it depending on its center
float left = -(rect.right/2.0f);
float right = left + (rect.right);
float top = -(rect.bottom/2.0f);
float bottom = top + (rect.bottom);

//vertices: Vertex(x, y, z, u, v) coordinates
m_vertex[0] = Vertex(left,  top,    0, 0, 0);
m_vertex[1] = Vertex(right, top,    0, 1, 0);
m_vertex[2] = Vertex(right, bottom, 0, 1, 1);
m_vertex[3] = Vertex(left,  bottom, 0, 0, 1);

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &m_vertex[0].m_fX);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &m_vertex[0].m_fU);

glDrawArrays(GL_QUADS, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
}

Это мой фраг шейдер

uniform sampler2D texture;
uniform vec2 size;
uniform int kernel_size;

void main (void)
{
vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
vec2 st = gl_TexCoord[0].st;
vec2 texel = 1.0/size;

int sum = 0;
for(int i=-kernel_size; i <= kernel_size; i++)
{
vec4 value = texture2D(texture, st + vec2(0.0, texel.y * i));
int factor = kernel_size+1 - abs((float)i);
color += value * factor;
sum += factor;
}
color /= sum;

gl_FragColor = color;
gl_FragColor.a = 1.0;
}

Это не работает слишком хорошо. Я попытался изменить шейдер, чтобы сделать что-то еще, но он просто слегка затемняет его, несмотря ни на что.

3

Решение

Unbind должен быть

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2

Другие решения

Может быть, вы не включили достаточно кода, но я не вижу, чтобы вы на самом деле что-то отображали в вашем методе Render.

У вас есть несколько вызовов, первый из которых, как я полагаю, активирует контекст, затем вы связываете буфер кадра и связываете переменные шейдера, но затем я бы ожидал, что вызов каким-то образом отобразит квад / сетку (то есть с разделом glBegin / glEnd или привязка и рендеринг буфера вершин.)

0

Хорошо, обычно для выполнения эффектов постобработки вы должны визуализировать сцену с активным буфером кадров. Затем визуализируйте полноэкранный четырехугольник с активным шейдером постобработки (размытие) и текстурами кадрового буфера, связанными как сэмплеры.

0

Nevenmind У меня это работает сейчас. Я звонил Bind и UnBind не в том месте.

0