[Qt和GLSL的笔记2] QGLShaderProgram类

来源:互联网 发布:美发软件哪个好 编辑:程序博客网 时间:2024/06/06 03:38

时间:2017年4月21日(大三下学期)

作者:RyuZhihao123 (Northwest A&F University,985/211)


第一篇教程链接:Qt和GLSL开发1 - 程序的基本结构

                   http://blog.csdn.net/mahabharata_/article/details/70312938

写在前面:

       上一篇文章,介绍了Qt开发GLSL的程序基本框架,并给了一个简单的demo。这里想进一步介绍一下前面使用到的QGLShaderProgram类,虽然说大家完全可以在Qt Reference Documentation中查找到该类的介绍和所有成员,但是文档毕竟比较大,这里摘选出我认为最常用也最有利于理解的几点并做一下简单的介绍。当然,不会太过全面,主要目的是帮助大家理解在上一篇教程中遇到的关于QGLShaderProgram的部分。关于这个类的更多用法,将会随着深入,再做介绍。

       这里,我们没有介绍新的东西,所以代码可以从上一篇博客中找到,或者通过下面的链接下载:

                 http://download.csdn.net/detail/mahabharata_/9821155

              


QGLShaderProgram:Qt的着色器程序类(Since QT4.6)

       使用过Qt做固定管线opengl开发的同学应该都知道QGLWidget类(在Qt5.4版本之后,被QOpenGLWidget取代),这个类的作用大致相当于在vs下开发opengl常用的辅助库:glut、glew,主要帮助我们建立一个opengl视窗。方便的是,在Qt中,QGLWidget可以作为其他容器类的一个附属组件,这样子也很方便的让我们用其他组件和其进行交互。

       首先,我们需要理解两个概念:

             着色器(shader):就是着色器的代码(包括顶点着色器、片段着色器等)

             着色器程序(shader program):负责执行shader的引擎(程序)。用于执行前面shader代码指定的操作。

       在使用shader的情况下,QGLShaderProgram通常作为QGLWidget的一个成员。在下面的代码中,便表示了他们之间的关系:QGLShaderProgram的一个实例program作为QGLWidget的一个member存在。

class Widget : public QGLWidget{    Q_OBJECTpublic:    explicit Widget(QWidget *parent = 0);    ~Widget();protected:    void initializeGL();    void resizeGL(int w, int h);    void paintGL();private:    // 着色器程序 shader program;    QGLShaderProgram program;    // 初始化着色器 init shader;    void makeShader();};
       那么之后,我们便可以通过这个program,来使用shader。

      

     在Qt Reference Documentation中,我们可以查到QGLShaderProgram的所有信息。这里列出几个我们比较关注的函数:

1. QGLShaderProgram::addShader() 系列

    相当于glAttachShader();

      这一系列函数,提供了三种将着色器(shader)添加到该着色器程序(shader program)的方法。

       Include: 

                  bool  addShader(QGLShader * shader) 

                             -- 从已编译好的着色器(compiled shaders)中直接添加。
                  bool addShaderFromSourceCode(QGLShader::ShaderType type, const QString & source)

                             -- 在代码中,用字符串QString等存储shader的代码,并用该函数直接添加。
                  bool addShaderFromSourceFile(QGLShader::ShaderType type, const QString & fileName)

                             -- 将shader写好在文件中,并为该函数指明文件的路径,实现添加着色器。

      这里出现的参数QGLShader::ShaderType type可以取不同的值,以说明是何种着色器(顶点着色器/片段着色器)


2. QGLShaderProgram::link()

      相当于glLinkProgram();

        Description: Link together the shaders that were added to this program with addShader(). If the shader program was already linked, calling this function again will force it to be re-linked.

       描述:将通过addShader()添加到该shader program的shaders链接起来(把原本分离的顶点着色器和片段着色器连接起来)。如果shader program已经被连接过,那么这个函数的再次调用,会强制让这个shader program重新连接一次。


3. QGLShaderProgram::bind()

       相当于glUseProgram();

        Description:Bind this shader program to the active QGLContext and makes it the current shader program. Any preivously bound shader program is released. 

        描述:将这个shader program与当前处于活动状态下的opengl上下文绑定,并让他成为当前活动的shader program. 任何先前绑定的shader program都会被释放。

       我的理解: 

       通过bind()的调用,使得该shader program成为当前opengl的唯一绘制标准。之后进行的所有绘制操作,都是使用该shader program指定的着色方案。至于,这里提到的opengl上下文(QGLContext),其实是opengl的当前活动的状态(当前的投影、模型、视图变换等等)。我们知道opengl是一个状态机。在Qt下,我们甚至可以为opengl程序指定不同的opengl上下文(当然,很少这么做)。

        另外,我们也可以在同一个程序中,使用多个shader program,实现多种着色方案。


4. QGLShaderProgram::release()

      Description: Releases the active shader program from  the current QGLContext.

      描述:是该shader program从当前opengl上下文中释放。之后的绘制不再经过该shader program,可以理解为恢复到传统的固定管线的绘制模式。


    那么,现在应该能理解上一篇文章中代码widget.cpp中的关键函数makeShader()了。这里重新给一下这段代码:

#include "widget.h"Widget::Widget(QWidget *parent) :    QGLWidget(parent){}void Widget::initializeGL(){    glClearColor(0.0,0.0,0.0,1.0);    glShadeModel(GL_SMOOTH);    glEnable(GL_DEPTH_TEST);    glEnable(GL_COLOR_MATERIAL);    makeShader();   // 初始化shader}void Widget::resizeGL(int w, int h){    glViewport(0,0,(GLsizei)w,(GLsizei)h);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(45.0,(GLdouble)w/(GLdouble)h,0.0001,1000.0);}void Widget::paintGL(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    gluLookAt(0.0,50.0,100.0,0.0,0.0,0.0,0.0,1.0,0.0);    // 利用二次曲面绘制一个球    static GLUquadric* qobj = NULL;    if(qobj == NULL)        qobj = gluNewQuadric();    gluSphere(qobj,15.0,30.0,30.0);}void Widget::makeShader(){    // shader文件的路径(路径自行修改)    static const QString vertFile = "C:/Qt/Qt5.2.0/Tools/QtCreator/bin/untitled/vsrc.vert";    static const QString fragFile = "C:/Qt/Qt5.2.0/Tools/QtCreator/bin/untitled/fsrc.frag";    // shader program加载两个shader    program.addShaderFromSourceFile(QGLShader::Vertex,vertFile);    program.addShaderFromSourceFile(QGLShader::Fragment,fragFile);    program.link();  // 链接通过addShader添加的着色器    program.bind();  // 使该shader真正启动(绑定到当前的opengl上下文中)}Widget::~Widget(){}



3 0
原创粉丝点击