Странная проблема с GLSL Radial Blur

Используется шейдер: http://www.gamerendering.com/2008/12/20/radial-blur-filter/

Моя проблема заключается в следующем: вся сцена занимает только четверть пространства экрана (что является прямоугольником этих координат: ширина / 2,0 ширина, высота / 2), и кажется, что она была буквально обрезана (не масштабирована) , Он также отображал его с перевернутой буквой Y (но я смог это исправить, удалив - знак из строки 9 gl_Position.y).

я использовал этот урок выполнить постобработку, за исключением использования основных glBegin(GL_QUADS) вместо вершинных массивов.


РЕДАКТИРОВАТЬ 2: Я пробовал использовать другой шейдер (http://www.geeks3d.com/20110428/shader-library-swirl-post-processing-filter-in-glsl/), и он работал отлично. Нет отсечения.

РЕДАКТИРОВАТЬВот источник шейдеров (я сделал небольшие правки):

Фрагмент шейдера:

#version 140

// This texture should hold the image to blur.
// This can perhaps be a previous rendered scene.
uniform sampler2D tex;

// texture coordinates passed from the vertex shader
varying vec2 uv;

// some const, tweak for best look
const float sampleDist = 1.0;
const float sampleStrength = 20.2;

void main(void)
{
// some sample positions
float samples[10] =
float[](-0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08);

// 0.5,0.5 is the center of the screen
// so substracting uv from it will result in
// a vector pointing to the middle of the screen
vec2 dir = 0.5 - uv;

// calculate the distance to the center of the screen
float dist = sqrt(dir.x*dir.x + dir.y*dir.y);

// normalize the direction (reuse the distance)
//dir = dir/dist;
dir /= dist;

// this is the original colour of this fragment
// using only this would result in a nonblurred version
vec4 color = texture2D(tex,uv);

vec4 sum = color;

// take 10 additional blur samples in the direction towards
// the center of the screen
for (int i = 0; i < 10; i++)
{
sum += texture2D( tex, uv + dir * samples[i] * sampleDist );
}

// we have taken eleven samples
sum *= 1.0/11.0;

// weighten the blur effect with the distance to the
// center of the screen ( further out is blurred more)
float t = dist * sampleStrength;
t = clamp( t ,0.0,1.0); //0 <= t <= 1

//Blend the original color with the averaged pixels
gl_FragColor = mix( color, sum, t );
}

Вершинный шейдер:

#version 140

varying vec2  uv;
// this vertex shader is from AMD RenderMonkey
void main(void)
{
gl_Position = vec4( gl_Vertex.xy, 0.0, 1.0 );
gl_Position = sign( gl_Position );

// Texture coordinate for screen aligned (in correct range):
uv = (vec2( gl_Position.x, gl_Position.y ) + vec2(1.0 )) / vec2( 2.0 );
}

Пост-процессор:

#include "std/opengl.h"
#include "postprocess.h"
Post::Post(Pos2D res) {
this->res = res;
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &this->texture);
glBindTexture(GL_TEXTURE_2D, this->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res.x, res.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffers(1, &this->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, this->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, res.x, res.y);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenFramebuffers(1, &this->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, this->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, this->rbo);
GLenum status;
if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "Framebuffer error! %i", status);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

Post::~Post() {
glDeleteRenderbuffers(1, &this->rbo);
glDeleteTextures(1, &this->texture);
glDeleteFramebuffers(1, &this->fbo);
}

void Post::update(Pos2D res) {
this->res = res;
glBindTexture(GL_TEXTURE_2D, this->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res.x, res.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, this->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, res.x, res.y);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

void Post::bind() {
glBindFramebuffer(GL_FRAMEBUFFER, this->fbo);
}

void Post::unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void Post::render(Shader* shader) {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);

shader->run();
auto tex = glGetUniformLocation(shader->program_handle, "tex");
glBindTexture(GL_TEXTURE_2D, this->texture);
glUniform1i(tex, 0);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex2f(0, 0);
glTexCoord2f(0.0, 1.0);
glVertex2f(0, this->res.y);
glTexCoord2f(1.0, 1.0);
glVertex2f(this->res.x, this->res.y);
glTexCoord2f(1.0, 0.0);
glVertex2f(this->res.x, 0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
}

Снимок экрана с вопросом (как видите, он обрезан): багги размытие

Снимок экрана, когда я отключаю шейдер (как вы можете видеть, он может отображаться во всем окне, он не обрезается): нет размытия нет ошибки

1

Решение

проблема заключается в том, как вы определяете координаты своей вершины:

    glTexCoord2f(0.0, 0.0);
glVertex2f(0, 0);
glTexCoord2f(0.0, 1.0);
glVertex2f(0, this->res.y);
glTexCoord2f(1.0, 1.0);
glVertex2f(this->res.x, this->res.y);
glTexCoord2f(1.0, 0.0);
glVertex2f(this->res.x, 0);

вместо использования разрешения окна в качестве координат вершин, попробуйте нарисовать квад со следующими вершинами: (-1, -1), (-1, 1), (1, 1) и (1, -1) — это приведет к в полноэкранном квадре в родной системе координат opengl. в вашем вершинном шейдере мне кажется, что вы пытаетесь использовать функцию знака для преобразования координат вершин в эту систему координат:

   gl_Position = vec4( gl_Vertex.xy, 0.0, 1.0 );
gl_Position = sign( gl_Position );

но, конечно, тогда вы получите квад с угловыми точками (0, 0), (0, 1), (1, 1) и (1, 0), что объясняет, почему он заполняет только часть экрана.
И в результате, координаты текстуры, которые вы вычисляете в своем шейдере с помощью этой строки:

uv = (vec2( gl_Position.x, gl_Position.y ) + vec2(1.0 )) / vec2( 2.0 );

также неверны, что приводит к «обрезанному» виду, который вы испытываете — ваши texcoords варьируются от 0.5 до 1, а не от 0 до 1. Кстати, вы все равно явно определяете texcoords с помощью glTexCoord2f, и те являются правильными — поэтому нет необходимости снова вычислять их в шейдере, просто используйте встроенный gl_MultiTexcoord.

4

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

Других решений пока нет …