Пинг-понг OpenGL с двумя текстурами в одном и том же фреймбуфере

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

Обе текстуры привязаны к одному и тому же FBO, и я переключаю их через glDrawBuffer(GL_COLOR_ATTACHMENT_i)

Вот мой код инициализации:

void GlWidget::initializeGL() {
    glewInit();
    src = true;
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    //glEnable(GL_CULL_FACE);

// Generate the texture to be drawn
    tex = new float[256*256*4];
    for(int i = 0; i < 256*256*4; i++){
        if (i % 4 == 0){
            tex[i] = 0.5;
        }else if (i % 4 == 1){
            tex[i] = 0.3;
        }else if (i % 4 == 2){
            tex[i] = 0.5;
        }else if (i % 4 == 3){
            tex[i] = 0;
        }
    }



    glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, 256, 0,  GL_RGBA, GL_FLOAT, tex);

    glGenTextures(1, &targetTex);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, targetTex);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, 256, 0,  GL_RGBA, GL_FLOAT, NULL);

    glGenFramebuffers(1, &fb);
    glBindFramebuffer(GL_FRAMEBUFFER, fb);
    //Attach 2D texture to this FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, targetTex, 0);
    glDrawBuffer (GL_COLOR_ATTACHMENT1);
    //-------------------------
    glGenRenderbuffers(1, &depth_rb);
    glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_rb);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 256, 256);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, depth_rb);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
    shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
    shaderProgram.link();
    vertices << QVector3D(-1, -1, -2) << QVector3D(-1, 1, -2) << QVector3D(1, 1, -2) << QVector3D(1, -1, -2);
    texCoords << QVector2D(0, 0) << QVector2D(0, 1) <<  QVector2D(1, 1) << QVector2D(1, 0);
}

И вот мой код рисования:

void GlWidget::render_to_screen () {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    qglClearColor(QColor(Qt::blue));
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    if(src){
        glActiveTexture(GL_TEXTURE0);
    }else{
        glActiveTexture(GL_TEXTURE1);
    }

    shaderProgram.enableAttributeArray("textureCoordinates");
    shaderProgram.enableAttributeArray("vertex");

    glDrawArrays(GL_QUADS, 0, vertices.size());
    shaderProgram.disableAttributeArray("vertex");
    shaderProgram.disableAttributeArray("textureCoordinates");
}

void GlWidget::paintGL()
{
    qDebug() << "Updating";
    glBindFramebuffer(GL_FRAMEBUFFER, fb);
    if(src) {
        glDrawBuffer(GL_COLOR_ATTACHMENT1);
        glActiveTexture(GL_TEXTURE0);
    }else {
        glDrawBuffer(GL_COLOR_ATTACHMENT0);
        glActiveTexture(GL_TEXTURE1);
    }
    src = !src;
    qglClearColor(QColor(Qt::white));
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 mMatrix;
    QMatrix4x4 vMatrix;


    shaderProgram.bind();

    shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
    shaderProgram.setAttributeArray ("textureCoordinates", texCoords.constData ());
    shaderProgram.enableAttributeArray("textureCoordinates");
    shaderProgram.setAttributeArray("vertex", vertices.constData());
    shaderProgram.enableAttributeArray("vertex");

    glDrawArrays(GL_QUADS, 0, vertices.size());

    shaderProgram.disableAttributeArray("vertex");
    shaderProgram.disableAttributeArray("textureCoordinates");
    render_to_screen ();
    shaderProgram.release();
}

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


person user978817    schedule 05.05.2013    source источник


Ответы (1)


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

Или еще лучше, просто привяжите другую текстуру к контексту. Нет необходимости устанавливать активную единицу изображения текстуры; просто привяжите текстуру, из которой вы хотите взять образец. Действительно, нет смысла ни в одном из ваших glActiveTexture звонков.

person Nicol Bolas    schedule 05.05.2013