Я пытаюсь вывести на экран изображение в формате 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 оставлю в комментарии, так как лимит исчерпан.