Qt文档阅读笔记-OpenGL Window Example的解析笔记

目录

OpenGLWindow Super Class

Example OpenGL Rendering Sub Class


 

注意:
这是一个辣鸡用法他是在QWindow中使用OpenGL,在以后的练习中要使用QOpenGLWindows类

 

OpenGLWindow Super Class

子类化QOpenGLFunctions后可以重写render()或render(QPainter*)进行渲染,其中后者是使用QPainter进行渲染。

  class OpenGLWindow : public QWindow, protected QOpenGLFunctions
  {
      Q_OBJECT
  public:
      explicit OpenGLWindow(QWindow *parent = 0);
      ~OpenGLWindow();

      virtual void render(QPainter *painter);
      virtual void render();

      virtual void initialize();

      void setAnimating(bool animating);

  public slots:
      void renderLater();
      void renderNow();

  protected:
      bool event(QEvent *event) override;

      void exposeEvent(QExposeEvent *event) override;

  private:
      bool m_animating;

      QOpenGLContext *m_context;
      QOpenGLPaintDevice *m_device;
  };

构造函数里面要调用QSurface::OpenGLSurface让窗口知道要用OpenGL渲染了。

  OpenGLWindow::OpenGLWindow(QWindow *parent)
      : QWindow(parent)
      , m_animating(false)
      , m_context(0)
      , m_device(0)
  {
      setSurfaceType(QWindow::OpenGLSurface);
  }

所有的OpenGL都要初始化,所以要重写initialize(),这个函数只会在渲染前调用一次。

 void OpenGLWindow::render(QPainter *painter)
  {
      Q_UNUSED(painter);
  }

  void OpenGLWindow::initialize()
  {
  }

  void OpenGLWindow::render()
  {
      if (!m_device)
          m_device = new QOpenGLPaintDevice;

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

      m_device->setSize(size());

      QPainter painter(m_device);
      render(&painter);
  }

当系统想重新绘制的时候就会调用renderLater()函数,而renderLater()函数就简单调用了QWindow::requestUpdate()函数。
当发出一个时间时,要调用renderNow()这个函数。exposeEvent()函数通知窗口,我要渲染了。当通知结束后可以调用QWindow::isExposed()判断他是否被通知。如果没有得到曝光的消息,就不要去渲染或者调用QOpenGLContext::swapBuffers()


  void OpenGLWindow::renderLater()
  {
      requestUpdate();
  }

  bool OpenGLWindow::event(QEvent *event)
  {
      switch (event->type()) {
      case QEvent::UpdateRequest:
          renderNow();
          return true;
      default:
          return QWindow::event(event);
      }
  }

  void OpenGLWindow::exposeEvent(QExposeEvent *event)
  {
      Q_UNUSED(event);

      if (isExposed())
          renderNow();
  }

在renderNow()这个函数中,如果未曝光,则直接返回,只有曝光后,他才会正常运行。如果不曝光,那么就要创建QOpenGLContext类去设置OpenGLWindow,然后子类调用initialize()这个函数,再调用initializeOpenGLFunctions()使得OpenGL的超类与QOpenGLContext正常关联。
如果OpenGLWindow::setAnimating(true)启动了动画,那么将调用renderLater()来更新一次请求。

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();
      }

      render();

      m_context->swapBuffers(this);

      if (m_animating)
          renderLater();
  }

下面的代码是启动动画安排的请求

void OpenGLWindow::setAnimating(bool animating)
  {
      m_animating = animating;

      if (animating)
          renderLater();
  }

Example OpenGL Rendering Sub Class

TriangleWindow这个类为OpenGLWindow的子类,用于旋转事件的触发。

class TriangleWindow : public OpenGLWindow
  {
  public:
      TriangleWindow();

      void initialize() override;
      void render() override;

  private:
      GLuint m_posAttr;
      GLuint m_colAttr;
      GLuint m_matrixUniform;

      QOpenGLShaderProgram *m_program;
      int m_frame;
  };

  TriangleWindow::TriangleWindow()
      : m_program(0)
      , m_frame(0)
  {
  }

main函数中相关的代码!主要是设置反锯齿与设置动画效果等

  int main(int argc, char **argv)
  {
      QGuiApplication app(argc, argv);

      QSurfaceFormat format;
      format.setSamples(16);

      TriangleWindow window;
      window.setFormat(format);
      window.resize(640, 480);
      window.show();

      window.setAnimating(true);

      return app.exec();
  }

下面这个代码是着色器的代码,顶点着色器与片段着色器。

  static const char *vertexShaderSource =
      "attribute highp vec4 posAttr;\n"
      "attribute lowp vec4 colAttr;\n"
      "varying lowp vec4 col;\n"
      "uniform highp mat4 matrix;\n"
      "void main() {\n"
      "   col = colAttr;\n"
      "   gl_Position = matrix * posAttr;\n"
      "}\n";

  static const char *fragmentShaderSource =
      "varying lowp vec4 col;\n"
      "void main() {\n"
      "   gl_FragColor = col;\n"
      "}\n";

这里使用 QOpenGLShaderProgram去代替原始的OpenGL。

  void TriangleWindow::initialize()
  {
      m_program = new QOpenGLShaderProgram(this);
      m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
      m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
      m_program->link();
      m_posAttr = m_program->attributeLocation("posAttr");
      m_colAttr = m_program->attributeLocation("colAttr");
      m_matrixUniform = m_program->uniformLocation("matrix");
  }

render()函数,设置视口,清空背景,以及旋转的触发

  void TriangleWindow::render()
  {
      const qreal retinaScale = devicePixelRatio();
      glViewport(0, 0, width() * retinaScale, height() * retinaScale);

      glClear(GL_COLOR_BUFFER_BIT);

      m_program->bind();

      QMatrix4x4 matrix;
      matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
      matrix.translate(0, 0, -2);
      matrix.rotate(100.0f * m_frame / screen()->refreshRate(), 0, 1, 0);

      m_program->setUniformValue(m_matrixUniform, matrix);

      GLfloat vertices[] = {
          0.0f, 0.707f,
          -0.5f, -0.5f,
          0.5f, -0.5f
      };

      GLfloat colors[] = {
          1.0f, 0.0f, 0.0f,
          0.0f, 1.0f, 0.0f,
          0.0f, 0.0f, 1.0f
      };

      glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
      glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);

      glEnableVertexAttribArray(0);
      glEnableVertexAttribArray(1);

      glDrawArrays(GL_TRIANGLES, 0, 3);

      glDisableVertexAttribArray(1);
      glDisableVertexAttribArray(0);

      m_program->release();

      ++m_frame;
  }

 

你可能感兴趣的:(C/C++,Qt,OpenGL,文档阅读笔记,Qt,官方实例)