glsl — фрагмент-шейдер (размытие) -> черный экран

#c #opengl #openframeworks #fragment-shader

#c #opengl #openframeworks #фрагмент-шейдер

Вопрос:

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

Что я пытался сделать:

  • визуализируйте сцену в формате FBO
  • размыть прикрепленную текстуру с помощью glsl-шейдеров
  • визуализируйте результирующую текстуру в квадрате, выровненном по экрану

Проблема:

Если я включу fragment-shader (размытие по горизонтали), я получу размытое изображение, отображаемое в моем квадрате в течение первого кадра или около того, после этого все будет черным.

Я подозреваю, что у меня что-то не так с тем, как я передаю текстуру своему шейдеру:

     horizontalBlurVertex.enable();

    horizontalBlurFragment.enable();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, fboTexture);
    glUniform1i(glGetUniformLocation(horizontalBlurFragment.program, "RTScene"), 0);
  

Редактировать:
Еще одна информация:
если я удалю glUniform1i(glGetUniformLocation(horizontalBlurFragment.program, «RTScene»), 0); я получу точно такой же результат. Что, я полагаю, указывает на то, что мой шейдер никогда не получает никаких текстурных данных вообще.

источники:

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

 varying vec2 vTexCoord;

void main(void)
{
   gl_FrontColor = gl_Color;
   gl_Position = ftransform();

   vec2 Pos;
   Pos = sign(gl_Vertex.xy);

   gl_Position = vec4(Pos, 0.0, 1.0);

   vTexCoord = Pos * 0.5   0.5;
}
  

фрагмент-шейдер:

 uniform sampler2D RTScene;
varying vec2 vTexCoord;

const float blurSize = 1.0/800.0;
const float weightSum = 70.0   2.0 * (1.0   8.0   28.0   56.0);

void main(void)
{
   vec4 sum = vec4(0.0);

   sum  = texture2D(RTScene, vec2(vTexCoord.x - 4.0*blurSize, vTexCoord.y)) * 1.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x - 3.0*blurSize, vTexCoord.y)) * 8.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x - 2.0*blurSize, vTexCoord.y)) * 28.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x - blurSize, vTexCoord.y)) * 56.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x, vTexCoord.y)) * 70.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x   blurSize, vTexCoord.y)) * 56.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x   2.0*blurSize, vTexCoord.y)) * 28.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x   3.0*blurSize, vTexCoord.y)) * 8.0 / weightSum;
   sum  = texture2D(RTScene, vec2(vTexCoord.x   4.0*blurSize, vTexCoord.y)) * 1.0 / weightSum;

   gl_FragColor = sum;
}
  

визуализация в fbo:

 //handels
    GLuint fbo, fboTexture, fboDepthbuffer;

    // generate namespace for the frame buffer, colorbuffer and depthbuffer
    glGenFramebuffersEXT(1, amp;fbo);
    glGenTextures(1, amp;fboTexture);
    glGenRenderbuffersEXT(1, amp;fboDepthbuffer);

    //switch to our fbo so we can bind stuff to it
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

    //create the colorbuffer texture and attach it to the frame buffer
    glGenTextures(1, amp;fboTexture);
    glBindTexture(GL_TEXTURE_2D, fboTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fboTexture, 0);

    // create a render buffer as our depthbuffer and attach it
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthbuffer);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fboDepthbuffer);

    // Go back to regular frame buffer rendering
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
        glPushAttrib(GL_VIEWPORT_BIT);
            glViewport(0, 0, width, height);
            glPushMatrix();
                glBegin(GL_QUADS);
                    glNormal3f(0.0, 0.0, 1.0);

                    glColor3f(1.0f, 1.0f, 0.0f);
                    glVertex3f(-0.1, 0.1, -1.0);

                    glColor3f(1.0f, 0.0f, 0.0f);
                    glVertex3f(0.1, 0.1, -1.0);

                    glColor3f(0.0f, 1.0f, 0.0f);
                    glVertex3f(0.1, -0.1, -1.0);

                    glColor3f(0.0f, 0.0f, 1.0f);
                    glVertex3f(-0.1, -0.1, -1.0);
                glEnd();
            glPopMatrix();
        glPopAttrib();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  

(не публикую здесь исходный код моего ShaderLoader, поскольку использование более простых шейдеров (переключение цветов и еще много чего) работает отлично)

Если вы считаете, что ошибка кроется где-то в другом месте, я буду рад опубликовать дополнительный код.

Комментарии:

1. Я не знаком с openFrameworks, но вам нужно вызвать glUseProgram перед вызовом glUniform *. Я не знаю, делает ли это enable ().

2. Да, это именно то, что он делает. Как я уже сказал, шейдеры без единообразных параметров работают просто отлично… Спасибо, хотя действительно ценю, что вы нашли время и прочитали все это.

3. Что довольно странно. Для привязки шейдера требуется программа, которая является результатом присоединения скомпилированных объектов шейдера и связывания его. Я не понимаю, как два, казалось бы, не связанных enable() вызова выполняют это.

4. Ну, конечно, есть функция load (), которая компилирует / связывает / генерирует программный объект и так далее… включить() просто вызывает glUseProgramObjectARB(программу);. Но опять же, сам загрузчик шейдеров, похоже, работает просто отлично. Я действительно получаю размытое изображение (для первого кадра), и я могу использовать все виды шейдеров, я просто пытаюсь передать текстуру своему шейдеру…

5. Ах, я думаю, вы не используете правильные координаты текстуры. Используйте glMultiTexCoord0 вместо координат вершины.

Ответ №1:

Проблема решена!

Оказывается, я по глупости создавал свой fbo для каждого кадра… теперь работает отлично.