由于本人对 opengl 不甚了解,所以,opengl 各版本的差异也不太懂,上次上这个老哥的博客http://blog.csdn.net/su_vast/article/details/52214642,用他的代码一直渲染不了,我感觉我的运气跟狗屎一样臭,试了不知道 多少遍,一直不行,真的跟吃了屎一样难受!直到今天在交叉编译的时候才意识到opengl 从 ver2.1 之后就不再维护 glBegin(), glEnd(),所以ver2.1之后就不能用来绘制图形了!所以又跑回来试了上面那位老哥的程序,哎呀,居然行了!!心中好多只草泥马奔腾而过!!
刚接触 opengl,而且对 qt 不熟悉,又有任务在身,只想以最快的速度完成,但是找了那么多天CSDN博客找到我心力憔悴,找的我连未来都失去了希望,都没找到能让我在机子上跑起来的,真的好能痛苦啊。所以在此,写下这篇博客,希望以后,有这个需求的童鞋能够第一时间跑起来看看运行效果,再去学习就有信心了!在此感谢 github,真的很感谢。废话不多说,上代码!
/* gl_widget.h */
#ifndef GL_WIDGET_H
#define GL_WIDGET_H
#include
#include
#include
#include
#include
class Gl_widget: public QGLWidget
{
Q_OBJECT
public:
Gl_widget(int width, int height, const QString& path, QWidget *parent = 0);
~Gl_widget();
protected:
void paintGL();
void initializeGL();
void resizeGL(int width, int height);
protected slots:
void on_timeout();
private:
int video_width;
int video_height;
GLuint y_texture;
GLuint uv_texture;
unsigned char* y_data;
unsigned char* uv_data;
QFile file;
QTimer timer;
QGLShaderProgram program;
};
#endif
/* gl_widget.cpp */
#include
#include
#include
Gl_widget::Gl_widget(int width, int height, const QString& path, QWidget* parent)
:QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
, video_width(width)
, video_height(height)
, y_texture(0)
, uv_texture(0)
, y_data(0)
, uv_data(0)
, file(path)
, timer(this)
, program(this)
{
setFocusPolicy(Qt::StrongFocus);
y_data = new unsigned char[(width*height*3)>>1];
uv_data = y_data+(width*height);
file.open(QIODevice::ReadOnly);
}
Gl_widget::~Gl_widget()
{
file.close();
glDeleteTextures(1, &y_texture);
glDeleteTextures(1, &uv_texture);
uv_data = 0;
delete [] y_data;
y_data = 0;
}
void Gl_widget::initializeGL()
{
qDebug() << program.addShaderFromSourceCode(QGLShader::Fragment,
"uniform sampler2D y_texture;\n"
"uniform sampler2D uv_texture;\n"
"void main(void)\n"
"{\n"
" float y, u, v, red, green, blue;\n"
" y = texture2D(y_texture, gl_TexCoord[0].st).r ;\n"
" y = 1.1643 * (y - 0.0625);\n"
" u = texture2D(uv_texture, gl_TexCoord[0].st).r - 0.5;\n"
" v = texture2D(uv_texture, gl_TexCoord[0].st).a - 0.5;\n"
" red = y+1.5958*v;\n"
" green = y-0.39173*u-0.81290*v;\n"
" blue = y+2.017*u;\n"
" gl_FragColor = vec4(red, green, blue, 1.0);\n"
"}");
qDebug() << program.link();
qDebug() << program.bind();
glGenTextures(1, &y_texture);
glGenTextures(1, &uv_texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, y_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, video_width, video_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_data);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, uv_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, video_width>>1, video_height>>1, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, uv_data);
program.setUniformValue("y_texture", 0);
program.setUniformValue("uv_texture", 1);
connect(&timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer.setInterval(25);
timer.start();
}
void Gl_widget::paintGL()
{
file.read((char*)y_data, (video_width*video_height*3)>>1);
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width, video_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_data);
glActiveTexture(GL_TEXTURE1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width>>1, video_height>>1, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, uv_data);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);
}
void Gl_widget::resizeGL(int width, int height)
{
glViewport(0, 0, width, height);
}
void Gl_widget::on_timeout()
{
updateGL();
}
/* yuv_window.h */
#ifndef _YUV_WINDOW_H
#define _YUV_WINDOW_H
#include
#include "gl_widget.h"
class Yuv_window: public QWidget
{
Q_OBJECT
public:
Yuv_window(int width, int height, const QString& path, QWidget* parent = 0);
~Yuv_window();
protected:
void resizeEvent(QResizeEvent* event);
private:
Gl_widget gl_widget;
};
#endif
/* yuv_window.cpp */
#include "yuv_window.h"
Yuv_window::Yuv_window(int width, int height, const QString& path, QWidget* parent)
:QWidget(parent)
, gl_widget(width, height, path, this)
{
}
Yuv_window::~Yuv_window()
{
}
void Yuv_window::resizeEvent(QResizeEvent* event)
{
gl_widget.setGeometry(0, 0, width(), height());
}
/* main.cpp */
#include
#include "yuv_window.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
Yuv_window window(1920, 1080, "videotestsrc_1920x1080.nv12");//最好是绝对路径
window.resize(960, 540);
window.show();
return app.exec();
}
注意:除了gl_widget.cpp 和 gl_widget.h 跟 NV12 不太一样之外,其他都相同。
/* gl_widget.h */
#ifndef GL_WIDGET_H
#define GL_WIDGET_H
#include
#include
#include
#include
#include
class Gl_widget: public QGLWidget
{
Q_OBJECT
public:
Gl_widget(int width, int height, const QString& path, QWidget *parent = 0);
~Gl_widget();
protected:
void paintGL();
void initializeGL();
void resizeGL(int width, int height);
protected slots:
void on_timeout();
private:
int video_width;
int video_height;
GLuint y_texture;
GLuint u_texture;
GLuint v_texture;
unsigned char* y_data;
unsigned char* u_data;
unsigned char* v_data;
QFile file;
QTimer timer;
//QGLShader shader;
QGLShaderProgram program;
};
#endif
/* gl_widget.cpp */
#include
#include
#include
Gl_widget::Gl_widget(int width, int height, const QString& path, QWidget* parent)
:QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
, video_width(width)
, video_height(height)
, y_texture(0)
, u_texture(0)
, v_texture(0)
, y_data(0)
, u_data(0)
, v_data(0)
, file(path)
, timer(this)
, program(this)
{
setFocusPolicy(Qt::StrongFocus);
y_data = new unsigned char[(width*height*3)>>1];
u_data = y_data+(width*height);
v_data = u_data+((width*height)>>2);
file.open(QIODevice::ReadOnly);
}
Gl_widget::~Gl_widget()
{
file.close();
glDeleteTextures(1, &y_texture);
glDeleteTextures(1, &u_texture);
glDeleteTextures(1, &v_texture);
u_data = 0;
v_data = 0;
delete [] y_data;
y_data = 0;
}
void Gl_widget::initializeGL()
{
qDebug() << program.addShaderFromSourceCode(QGLShader::Fragment,
"uniform sampler2D y_texture;\n"
"uniform sampler2D u_texture;\n"
"uniform sampler2D v_texture;\n"
"void main(void)\n"
"{\n"
" float y, u, v, red, green, blue;\n"
" y = texture2D(y_texture, gl_TexCoord[0].st).r;\n"
" y = 1.1643 * (y - 0.0625);\n"
" u = texture2D(u_texture, gl_TexCoord[0].st).r - 0.5;\n"
" v = texture2D(v_texture, gl_TexCoord[0].st).r - 0.5;\n"
" red = y+1.5958*v;\n"
" green = y-0.39173*u-0.81290*v;\n"
" blue = y+2.017*u;\n"
" gl_FragColor = vec4(red, green, blue, 1.0);\n"
"}");
qDebug() << program.link();
qDebug() << program.bind();
glGenTextures(1, &y_texture);
glGenTextures(1, &u_texture);
glGenTextures(1, &v_texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, y_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, video_width, video_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_data);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, u_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, video_width>>1, video_height>>1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u_data);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, v_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, video_width>>1, video_height>>1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, v_data);
program.setUniformValue("y_texture", 0);
program.setUniformValue("u_texture", 1);
program.setUniformValue("v_texture", 2);
connect(&timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
timer.setInterval(25);
timer.start();
}
void Gl_widget::paintGL()
{
file.read((char*)y_data, (video_width*video_height*3)>>1);
glActiveTexture(GL_TEXTURE0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width, video_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, y_data);
glActiveTexture(GL_TEXTURE1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width>>1, video_height>>1, GL_LUMINANCE, GL_UNSIGNED_BYTE, u_data);
glActiveTexture(GL_TEXTURE2);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width>>1, video_height>>1, GL_LUMINANCE, GL_UNSIGNED_BYTE, v_data);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glTexCoord2f(0.0f,1.0f); glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);
}
void Gl_widget::resizeGL(int width, int height)
{
glViewport(0, 0, width, height);
/*glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);*/
}
void Gl_widget::on_timeout()
{
updateGL();
}
这是我自己参考的一些资料:
http://colabug.com/174582.html
http://m.blog.csdn.net/jxw167/article/details/75501637
http://download.csdn.net/download/sinat_36684217/9994260
http://download.csdn.net/download/sinat_36684217/9994316
http://download.csdn.net/download/sinat_36684217/9998124