Задать вопрос
@Dogrtt
Qt/Python разработчик

Почему в QOpenGLWidget не используется заданный по умолчанию QSurfaceFormat?

Я пытаюсь вывести на экран изображение в формате RGB30.
  • Система: Windows 10 x64
  • Версия Qt: 5.12.1 msvc2017_64
  • Видеокарта: Quadro P400
  • Монитор: NEC MD211C2 (Проверял бэнчмарком от NEC - 10-бит отрабатывает)


При создании приложения Qt, задаю формат поверхности:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QSurfaceFormat>

int main(int argc, char *argv[])
{
    QSurfaceFormat format;
    format.setDepthBufferSize(32);
    format.setRedBufferSize (10);
    format.setGreenBufferSize (10);
    format.setBlueBufferSize (10);
    format.setAlphaBufferSize(0);
    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setVersion(4, 6);
    QSurfaceFormat::setDefaultFormat(format);

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}


Затем вручную создаю виджет унаследованный от QOpenGLWidget и размещаю в лэйауте, передавая в конструкторе виджета сгенерированный QByteArray, представляющий собой данные изображения в формате RGB30 (10-10-10-x).
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBuffer>
#include <QtEndian>


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    width = 2048;
    height = 600;

    QByteArray *arr = gen30bitImgArr(width, height);
    ogl10 = new MyOGL(this, arr);
    ui->vLout->addWidget(ogl10);
}

MainWindow::~MainWindow()
{
    delete ui;
}

QByteArray *MainWindow::gen30bitImgArr(int width, int height)
{
    QByteArray *arr = new QByteArray();
    QBuffer buffer(arr);
    buffer.open (QIODevice::WriteOnly);
    QDataStream out(&buffer);

    uint32_t rgb30color = 0;
    for (int row = 0; row < height; ++row) {
        for (uint32_t pixel = 0; static_cast<int>(pixel)< 1024; ++pixel) {
            for (int chanel = 0; chanel < 3; ++chanel) {
                rgb30color |= pixel;
                chanel == 2? 0 : rgb30color <<= 10;
            }
            rgb30color = qToBigEndian(rgb30color);
            out << rgb30color;
            out << rgb30color;
            rgb30color = 0;
        }
    }
    return arr;
}


В самом MyOGL-виджете (основанном на примере qopenglwidget), я создаю прямоугольник и пытаюсь на нем отобразить QOpenGLTexture в формате GL_RGB10_A2. Вот тут и начинаются проблемы, если я настраиваю текстуру под 8-битный массив (его я исключил из примера), то все корректно отображается (не факт, мне показалось, что не доводятся до максимума на краях прямоугольника черный и белый цвета), но стоит все перевести в режим отображения 10-бит, как тут-же вместо прямоугольника отображается черный цвет. Я долго мучился перебирая все возможные комбинации параметров подходящих под мою задачу, а потом решил посмотреть что у меня в this->format();. Оказывается, что в конструкторе MyOGL в качестве QSurfaceFormat выступает тот формат, что я указал в качестве дефолтного, с 10'тью битами на каждый канал, однако, уже в initializeGL(), он сменяется на какой-то неведомый, с 8'мью битами на канал... В какой момент происходит замена, я не понимаю. В документации, сколько ни копался, я не нашел объяснения. Привожу MyOGL:
myogl.h
#ifndef MYOGL_H
#define MYOGL_H

#include <QObject>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLTexture>
#include <QOpenGLBuffer>


class MyOGL : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    MyOGL(QWidget *parent = nullptr, const QByteArray *imgArr = nullptr);
    ~MyOGL() override;

protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;

private:
    void makeObject();

    const QByteArray *imgData;

    qreal m_fAngle;
    qreal m_fScale;
    QVector<QVector3D> m_vertices;
    QOpenGLShader *m_vshader;
    QOpenGLShader *m_fshader;
    QOpenGLShaderProgram *m_program;
    QOpenGLTexture *m_texture;
    QOpenGLBuffer m_vbo;
    int m_vertexAttr;
    int m_texCoordAttr;
    int m_textureUniform;
    QColor m_background = QColor(30, 30, 30);

};

#endif // MYOGL_H

myogl.cpp
#include "myogl.h"
#include "qdebug.h"


MyOGL::MyOGL(QWidget *parent, const QByteArray *imgArr)
    : QOpenGLWidget(parent),
      m_program(nullptr),
      m_texture(nullptr)
{
    qDebug()<<"------------Start constructor-----------";
    this->setTextureFormat (GL_RGB10_A2);
    imgData = imgArr;

    qDebug()<<this->format()<<"\n";
    qDebug()<<this->format().renderableType()<<"\n";
    qDebug()<<this->textureFormat()<<"\n";
    qDebug()<<QSurfaceFormat::defaultFormat()<<"\n";
    qDebug()<<"------------END constructor-----------\n";

}

MyOGL::~MyOGL()
{
    makeCurrent();
    delete m_texture;
    delete m_program;
    delete m_vshader;
    delete m_fshader;
    m_vbo.destroy();
    doneCurrent();
}

void MyOGL::initializeGL()
{
    qDebug()<<"----------Start Initalization-----------";
    qDebug()<<this->format()<<"\n";
    qDebug()<<this->format().renderableType()<<"\n";
    qDebug()<<this->textureFormat()<<"\n";
    qDebug()<<QSurfaceFormat::defaultFormat()<<"\n";

    initializeOpenGLFunctions();

    m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_texture->setFormat(QOpenGLTexture::RGB10A2);
    m_texture->setSize(2048, 600);
    m_texture->setMipLevels(1);
    m_texture->allocateStorage(QOpenGLTexture::RGBA,
                               QOpenGLTexture::UInt32_RGB10A2);
    m_texture->setData(0,
                       QOpenGLTexture::RGBA,
                       QOpenGLTexture::UInt32_RGB10A2,
                       imgData->constData());

    m_vshader = new QOpenGLShader(QOpenGLShader::Vertex);
    const char *vsrc2 =
        "attribute highp vec4 vertex;\n"
        "attribute mediump vec4 texCoord;\n"
        "varying mediump vec4 texc;\n"
        "void main(void)\n"
        "{\n"
        "    gl_Position = vertex;\n"
        "    texc = texCoord;\n"
        "}\n";
    m_vshader->compileSourceCode(vsrc2);

    m_fshader = new QOpenGLShader(QOpenGLShader::Fragment);
    const char *fsrc2 =
        "uniform sampler2D tex;\n"
        "varying mediump vec4 texc;\n"
        "void main(void)\n"
        "{\n"
        "    gl_FragColor = texture2D(tex, texc.st);\n"
        "}\n";
    m_fshader->compileSourceCode(fsrc2);

    m_program = new QOpenGLShaderProgram;
    m_program->addShader(m_vshader);
    m_program->addShader(m_fshader);
    m_program->link();

    m_vertexAttr = m_program->attributeLocation("vertex");
    m_texCoordAttr = m_program->attributeLocation("texCoord");
    m_textureUniform = m_program->uniformLocation("tex");

    m_fAngle = 0;
    m_fScale = 1;

    const int vertexCount = m_vertices.count();
    QVector<GLfloat> buf;
    buf.resize(vertexCount * 3 * 2);
    GLfloat *p = buf.data();
    for (int i = 0; i < vertexCount; ++i) {
        *p++ = m_vertices[i].x();
        *p++ = m_vertices[i].y();
        *p++ = m_vertices[i].z();
    }
}

void MyOGL::paintGL()
{
    glClearColor(m_background.redF(),
                 m_background.greenF(),
                 m_background.blueF(),
                 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glFrontFace(GL_CW);
    //glCullFace(GL_FRONT);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);

    m_program->bind();
    makeObject();
    m_program->release();


    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);


    update();
}

void MyOGL::resizeGL(int w, int h)
{

}

void MyOGL::makeObject()
{
    m_texture->bind();
    if (!m_vbo.isCreated()) {
        static GLfloat afVertices[] = {

            -0.5f, -0.5f, 0.0f,
            -0.5f,  0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,

            0.5f,  0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            -0.5f,  0.5f, 0.0f

        };

        static GLfloat afTexCoord[] = {
            0.25f, 0.25f,
            0.25f, 0.75f,
            0.75f, 0.25f,

            0.75f, 0.75f,
            0.75f, 0.25f,
            0.25f, 0.75f

        };

        m_vbo.create();
        m_vbo.bind();
        m_vbo.allocate(30 * sizeof(GLfloat));
        m_vbo.write(0, afVertices, sizeof(afVertices));
        m_vbo.write(sizeof(afVertices), afTexCoord, sizeof(afTexCoord));
        m_vbo.release();
    }

    m_program->setUniformValue(m_textureUniform, 0); // use texture unit 0

    m_program->enableAttributeArray(m_vertexAttr);
    m_program->enableAttributeArray(m_texCoordAttr);

    m_vbo.bind();
    m_program->setAttributeBuffer(m_vertexAttr, GL_FLOAT, 0, 3);
    m_program->setAttributeBuffer(m_texCoordAttr, GL_FLOAT,
                                  6 * 3 * sizeof(GLfloat), 2);
    m_vbo.release();

    glDrawArrays(GL_TRIANGLES, 0, 6);

    m_program->disableAttributeArray(m_vertexAttr);
    m_program->disableAttributeArray(m_texCoordAttr);
}


Так же, прилагаю вывод в консоль и результат вызова qtdiag.exe, хочу обратить ваше внимание на Buffer Size (RGBA) 8,8,8,8. Почему так, ведь карта поддерживает 10,10,10,2 , а монитор переведен в режим 10-bit?
Содержимое вывода qtdiag.exe оставлю в комментарии, так как лимит исчерпан.
  • Вопрос задан
  • 391 просмотр
Подписаться 1 Сложный 2 комментария
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы