一、实现效果
二、pro文件
Qt += widgets opengl
三、主要代码
#include "glwidget.h"
GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
connect(&m_timer, &QTimer::timeout, this,
[&]()
{
this->update();
});
m_timer.start(1000/33);
}
void GLWidget::initializeGL()
{
qDebug() << "初始化";
initializeOpenGLFunctions(); // 初始化opengl
qDebug() << "加载片元脚本:" <<program.addShaderFromSourceFile(QGLShader::Vertex, ":/res/shader.vert"); // 片元
qDebug() << "加载顶点脚本:" <<program.addShaderFromSourceFile(QGLShader::Fragment, ":/res/shader.frag"); // 顶点
qDebug() << "编译shader:" << program.link();
qDebug() << "绑定shader:" << program.bind();
int A_VER = -1;
int T_VER = -1;
// 设置顶点坐标的变量
A_VER = program.attributeLocation("vertexIn");//, A_VER
// 设置材质坐标
T_VER = program.attributeLocation("textureIn");//, T_VER
static const GLfloat ver[] = {
-1.0f, -1.0f, 0.0f, 1.0f,//0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 1.0f,//1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f,//0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f//1.0f, 1.0f
};
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(ver), ver, GL_STATIC_DRAW);
glVertexAttribPointer(A_VER, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(A_VER);
glVertexAttribPointer(T_VER, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2* sizeof(float)));
glEnableVertexAttribArray(T_VER);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 从shader获取材质
unis[0] = program.uniformLocation("tex_y");
unis[1] = program.uniformLocation("tex_u");
unis[2] = program.uniformLocation("tex_v");
// 创建材质
glGenTextures(3, texs);
// Y
glBindTexture(GL_TEXTURE_2D, texs[0]); // 绑定材质
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 设置纹理参数,放大过滤,线性插值 GL_NEAREST(效率高,效果差)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0); // 创建材质显卡空间
// U
glBindTexture(GL_TEXTURE_2D, texs[1]); // 绑定材质
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 设置纹理参数,放大过滤,线性插值
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height/ 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0); // 创建材质显卡空间
// 创建材质 V
glBindTexture(GL_TEXTURE_2D, texs[2]); // 绑定材质
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 设置纹理参数,放大过滤,线性插值
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0); // 创建材质显卡空间
m_file.setFileName(":/res/1.yuv");
if(!m_file.open(QIODevice::ReadOnly))
{
qDebug() << "打开失败!";
return;
}
}
void GLWidget::paintGL()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
program.bind();
//qDebug() << "绘制";
if(m_file.atEnd())
{
m_file.seek(0);
}
QByteArray buf;
buf = m_file.read(width * height);
glBindVertexArray(m_vao);
glActiveTexture(GL_TEXTURE0); // 激活第0层
glBindTexture(GL_TEXTURE_2D, texs[0]); // 0层绑定到y材质中
// 修改材质内容(复制内存内容)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[0], 0); // 与shader的uni变量关联
buf = m_file.read(width * height / 4);
glActiveTexture(GL_TEXTURE0 + 1); // 激活第1层
glBindTexture(GL_TEXTURE_2D, texs[1]); // 1层绑定到U材质中
// 修改材质内容(复制内存内容)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[1], 1); // 与shader的uni变量关联
buf = m_file.read(width * height / 4);
glActiveTexture(GL_TEXTURE0 + 2); // 激活第2层 V
glBindTexture(GL_TEXTURE_2D, texs[2]); // 2层绑定到v材质中
// 修改材质内容(复制内存内容)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[2], 2); // 与shader的uni变量关联
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // 开始绘制
glBindVertexArray(0);
}
void GLWidget::resizeGL(int w, int h)
{
//qDebug() << w <<" " << h;
glViewport(0, 0, w, h);
}
完整demo下载:点击跳转
觉得有帮助的话,打赏一下呗。。
需要商务合作(定制程序)的欢迎私信!!