QWidget绘图与QOpenGLWidget绘图

QWidget支持CPU绘图,使用paintEvent绘制图像。
优点:快速便捷,易懂
缺点:非常耗资源。
QOpenGLWidget使用GPU绘图,基于OpenGl。
优点:减少cpu端开销,Qt集成度高,只需要专注于着色器代码的编写
缺点:不易理解。
CPU版本代码:

void DisplayWgt::paintEvent(QPaintEvent* event) {
	QStyleOption opt;
	opt.init(this);
	QPainter p(this);
	style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
	p.setRenderHint(QPainter::Antialiasing, true);
	QRect target(0, 0, this->width(), this->height());
	uchar* m_img8bit = BllData::getImg8bit();
	quint16* img = BllData::getSingleImg();
	BllData::converToGray(img, m_img8bit, m_width, m_center);
	QImage image(m_img8bit, Detector::ImageSizeColumn, Detector::ImageSizeRow, QImage::Format_Grayscale8);
	p.drawImage(target, image);
}
void DisplayWgt::updateImgSlot() {
	quint16* img = BllData::getSingleImg();
	int min, max;
	BllData::getMinMaxData(img, min, max);
	m_width = max - min;
	m_center = (min + max) / 2;
	m_paintEnable = true;
	update();
}

GPU版本代码:
顶点着色器:

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCord;
out vec3 ourColor;
out vec2 TexCord;
void main(){
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);
    ourColor=aColor;
    TexCord=aTexCord;
}

片段着色器:

#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCord;
uniform sampler2D textureWall;
void main(){
    FragColor = texture(textureWall,TexCord);
}

坐标:

float vertices[] = {
    // positions      // colors        // texture coords
    1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
    1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
    -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
    -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
     0, 1, 3, // first triangle
     1, 2, 3 // second triangle
};

初始化,绘图等函数:

void DisplayGlWgt::initializeGL() {
    initializeOpenGLFunctions();
    //创建VBO和VAO对象,并赋予ID
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    //绑定VBO和VAO对象
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    //为当前绑定到target的缓冲区对象创建一个新的数据存储。
    //如果data不是NULL,则使用来自此指针的数据初始化数据存储
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    //告知显卡如何解析缓冲里的属性值
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    //开启VAO管理的第一个属性值
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    bool success;
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/shapes.vert");
    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/shapes.frag");
    success = shaderProgram.link();
    if (!success)
        qDebug() << "ERR:" << shaderProgram.log();
    // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
    GLuint m_texture;
    glGenTextures(1, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glBindVertexArray(0);
}
void DisplayGlWgt::paintGL() {
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    shaderProgram.bind();
    glBindVertexArray(VAO);
    if (m_paintEnable) {
        uchar* m_img8bit = BllData::getImg8bit();
        quint16* img = BllData::getSingleImg();
        BllData::converToGray(img, m_img8bit, m_width, m_center);
        QImage image(m_img8bit, Detector::ImageSizeColumn, Detector::ImageSizeRow, QImage::Format_Grayscale8);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, image.width(), image.height(),
            0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, image.bits());
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
}
void DisplayGlWgt::resizeGL(int w, int h) {
    Q_UNUSED(w); Q_UNUSED(h);
}
void DisplayGlWgt::updateImgSlot() {
    quint16* img = BllData::getSingleImg();
    int min, max;
    BllData::getMinMaxData(img, min, max);
    m_width = max - min;
    m_center = (min + max) / 2;
    m_paintEnable = true;
    update();
}
DisplayGlWgt::~DisplayGlWgt()
{
    makeCurrent();
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteVertexArrays(1, &VAO);
    doneCurrent();
}

CPU版本演示:

GPU版本演示:

如上所示,cpu10用于数据交换的消耗,cpu2为实际绘图消耗,cpu版本中,paintevent绘图机制占用cpu资源引起较大的消耗,gpu版本中,cpu2消耗下降至原来的三分之一,同时gpu消耗增加。

你可能感兴趣的:(OpenGl,qt,OpenGL)