Зачем всегда создавать 4 картинки в моей программе qt opengl?

#c #qt #opengl #qml #shader

Вопрос:

Вот мой код: изменить из примера qt: ПримерыQt-5.14.2quickscenegraphopenglunderqml

 void SquircleRenderer::init()
{
    unsigned char* data = (unsigned char*)malloc(1200*4);
    for(int i=0;i<600;i  )
    {
        data[i*4] = 0;
        data[i*4 1] = 255;
        data[i*4 2] = 0;
        data[i*4 3] = 255;
    }
    for(int i=600;i<1200;i  )
    {
        data[i*4] = 0;
        data[i*4 1] = 0;
        data[i*4 2] = 255;
        data[i*4 3] = 255;
    }

    if (!m_program) {
        QSGRendererInterface *rif = m_window->rendererInterface();
        Q_ASSERT(rif->graphicsApi() == QSGRendererInterface::OpenGL || rif->graphicsApi() == QSGRendererInterface::OpenGLRhi);

        initializeOpenGLFunctions();
        if (texs[0])
        {
            glDeleteTextures(1, texs);
        }
        glGenTextures(1, texs);

        glBindTexture(GL_TEXTURE_2D, texs[0]);

        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_RGBA, 30, 40, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);


        m_program = new QOpenGLShaderProgram();
        m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,
                                                    "attribute highp vec4 vertices;"
                                                    "varying highp vec2 coords;"
                                                    "void main() {"
                                                    "    gl_Position = vertices;"
                                                    "    coords = vertices.xy;"
                                                    "}");
        m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,
                                                    "varying highp vec2 coords;"
                                                    "uniform sampler2D inputImageTexture;"
                                                    "void main() {"
                                                    "    gl_FragColor = texture2D(inputImageTexture, coords);"
                                                    "}");

        m_program->bindAttributeLocation("vertices", 0);
        m_program->link();

        arrUni[0] = m_program->uniformLocation("inputImageTexture");
    }
}

//! [4] //! [5]
void SquircleRenderer::paint()
{
    // Play nice with the RHI. Not strictly needed when the scenegraph uses
    // OpenGL directly.
    m_window->beginExternalCommands();

    m_program->bind();

    m_program->enableAttributeArray(0);

    float values[] = {
        -1, 1,
        1, 1,
        -1, -1,
        1, -1
    };

    // This example relies on (deprecated) client-side pointers for the vertex
    // input. Therefore, we have to make sure no vertex buffer is bound.
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    m_program->setAttributeArray(0, GL_FLOAT, values, 2);//values
    //m_program->setUniformValue("t", (float) m_t);

    qDebug()<<m_viewportSize.width()<<m_viewportSize.height()<<"n";
    glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());

    glDisable(GL_DEPTH_TEST);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texs[0]);

    glUniform1i(arrUni[0], 0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    m_program->disableAttributeArray(0);
    m_program->release();

    m_window->endExternalCommands();
}
 

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

Ответ №1:

Текстуры отображаются по [0, 1] всему диапазону, а значения за пределами этого диапазона по модулю зацикливаются обратно в него, что создает повторяющийся шаблон. Интерпретация текстуры по [-1, 1] диапазону приводит к тому, что вы видите, так как вы отображаете ровно в два раза ультрафиолетовый диапазон в обеих осях.

Есть несколько способов исправить это. Но я лично предпочитаю, чтобы при таком прохождении полного буфера кадров атрибут был нормализован, а затем преобразован в ожидаемый [-1, 1] диапазон для координаты пространства клипов в шейдере вершин:

 float values[] = {
  0.f, 1.f,
  1.f, 1.f,
  0.f, 0.f,
  1.f, 0.f
};
 
 gl_Position = vertices * 2.0 - vec4(1.0, 1.0,0.0,1.0);
 

Другой распространенный метод-полностью отказаться от буфера атрибутов и использовать gl_VertexID его для непосредственного создания как UV, так и координат.

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

1. Спасибо! Это работает, gl_Position = вершины * 2.0 — vec4(1.0, 1.0,0.0,1.0);