该方法不存在普遍性。别按照此方法了
我用的是OpenGL 3.3 ,Qt 5.4.0
先说QWindow 和 QPainter 结合,这个Qt有现成的例子。就是 那个openglWindow那个例子。
这个基本直接照搬代码:
.h
#include
#include
#include
#include
class OpenGLWindow : public QWindow,protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
OpenGLWindow(QWindow *parent = 0);
~OpenGLWindow();
virtual void render();
virtual void initialize();
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE;
private:
bool m_update_pending;
bool m_animating;
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
QOpenGLBuffer * vbo;
QOpenGLVertexArrayObject * vao;
QOpenGLShaderProgram *m_program;
QTimer * timer;
float frame;
};
#endif // OPENGLWINDOW_H
#include "openglwindow.h"
#include
#include
static const char *vertexShaderSource =
"#version 330 core \n"
"in vec4 posAttr;\n"
"uniform mat4 matrix;\n"
"void main() {\n"
" gl_Position = matrix * posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"#version 330 core \n"
"out vec4 col;\n"
"void main() {\n"
" col = vec4(1.0f,0.0f,0.0f,1.0f);\n"
"}\n";
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent), m_update_pending(false)
, m_context(0)
, m_device(0)
{
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(24);
//format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
timer = new QTimer;
connect(timer,SIGNAL(timeout()),this,SLOT(renderNow()));
timer->start(50);
frame =0 ;
// m_context = new QOpenGLContext;
// m_context->setFormat(format);
// m_context->create();
}
OpenGLWindow::~OpenGLWindow()
{
}
void OpenGLWindow::initialize()
{
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
}
void OpenGLWindow::render()
{
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60.0f, float(width())/float(height()), 0.1f, 100.0f);
matrix.rotate(frame, 0, 1, 0);
GLfloat vertices[] = {
0.0f, 0.707f,-1.0f,1.0f,
-0.5f, -0.5f,-1.0f,1.0f,
0.5f, -0.5f,-1.0f,1.0f
};
glClearColor(0.5f,0.5f,0.5f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
QOpenGLVertexArrayObject vao;
vao.create();
vao.bind();
QOpenGLBuffer vertex;
vertex.create();
vertex.bind();
vertex .setUsagePattern(QOpenGLBuffer::StaticDraw);
vertex.allocate(vertices,sizeof(vertices));
m_program->enableAttributeArray(0);
m_program->setAttributeBuffer(0,GL_FLOAT,0,4,0);
m_program->setUniformValue("matrix",matrix);
glDrawArrays(GL_TRIANGLES, 0, 3);
frame++;
}
void OpenGLWindow::renderLater()
{
if (!m_update_pending) {
m_update_pending = true;
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
}
bool OpenGLWindow::event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
m_update_pending = false;
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
if (isExposed())
renderNow();
}
void OpenGLWindow::renderNow()
{
if (!isExposed())
return;
bool needsInitialize = false;
if (!m_context) {
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
needsInitialize = true;
}
m_context->makeCurrent(this);
if (needsInitialize) {
initializeOpenGLFunctions();
initialize();
}
if (!m_device)
m_device = new QOpenGLPaintDevice;
m_device->setSize(size());
QPainter painter(m_device);
painter.beginNativePainting();
render();
painter.endNativePainting();
QPen pen;
pen.setColor(Qt::green);
painter.setPen(pen);
painter.setFont(QFont("微软雅黑"));
painter.drawText(20,50,"frame:"+QString::number(frame));
painter.drawEllipse(100,100,50,80);
painter.end();
m_context->swapBuffers(this);
QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
}
2 QOpenGLWidget 和 QOpenGLWindow
这个我原来按照一篇博客 叫“
结果总是不成功,多方发帖询问未果。
后来自己研究了下,基本实现了混合渲染,但是有个缺点就是只能在OpenGL上面绘制图形。具体做法:
那个Qt博客中说,只要在虚函数paintGL()中写上QPainter,然后就可以混合渲染了,但是我按照他的做法没有成功过。我的做法是不再重写 paintGL(),而是重写paintEvent()。
原来的paintEvent()是会自动调用paintGL()的,重写以后的paintEvent如下代码:
void Render::paintEvent(QPaintEvent *e)
{
makeCurrent();
paintGL();
QPainter pter(this);
QImage pic;
pic.load("../Select/timg.jpg");
pter.setPen(Qt::blue);
pter.drawText(20,50,"This is a Text!");
pter.drawEllipse(80,100,40,50);
pter.drawImage(200,40,pic);
pter.end();
update();
}
其次还要注意的时,在类中构造函数中要设置好 format,我试着加入format的版本信息
format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
但是这样会导致QPainter不起作用。我是在main函数中设置的全局format。
QOpenGLWindow 和 QOpenGLWidget 实现是一样的,就是继承的时候换一下就可以。具体代码在下面的连接可以下载。
我只是初步探索一下,肯定很多不足的地方,如果有更好的方法,记得分享呀。
QOpenGLWindow QPainter混合代码