`
jgsj
  • 浏览: 957525 次
文章分类
社区版块
存档分类
最新评论

基于Qt和GLSL的着色器例子

 
阅读更多

基于Qt和GLSL的着色器例子

我的计算机换成新的了,可以支持OpenGL2.0以及以上的规范,这样我开始正式涉足OpenGL高级的内容了。目前我的OpenGL基础库是Qt,它有完备的功能,以及对OpenGL一层好的封装,所以用它来开发基于OpenGL的应用程序非常合适。下面是我就来介绍一下如何开发基于Qt和GLSL的程序。

GLSL是在OpenGL2.0时开始引入的一种语言,它可以让开发者定制自己的着色方式,而不是像原来一样走固定渲染管线。我们知道如果要达到一些色彩的渲染效果,需要一大堆以gl开头的函数,如glLightfv()、glMaterialfv()、glFogv()等等,而使用GLSL,则可以很简单地使用OpenGL的着色语言来达到上述函数的效果,有时候使用上述函数无法达到的效果,GLSL都可以做到。使用GLSL还有一个好处就是如果需要在运行时改变渲染效果,那么使用GLSL是非常方便的,而OpenGL2.0以前的那些函数可能因为需要调换次序等原因无法做到这样的效果。综上所述,GLSL对于开发现代应用程序还是非常有用的。

演示程序下载地址:这里

源代码下载地址:这里

那么该如何制作一个简单的基于Qt和GLSL的程序呢?首先从我们熟悉的GLWidget开始。

class GLWidget: public QGLWidget,
        protected QOpenGLFunctions
{
    Q_OBJECT
public:
    GLWidget( QWidget* pParent = 0 );

    void initializeGL( void );
    void resizeGL( int width, int height );
    void paintGL( void );
public slots:
    void CompileAndLinkVertexShader( const QString& shaderText );
    void CompileAndLinkFragmentShader( const QString& shaderText );
protected:
    void mousePressEvent( QMouseEvent* pEvent );
    void mouseReleaseEvent( QMouseEvent* pEvent );
    void mouseMoveEvent( QMouseEvent* pEvent );
    void wheelEvent( QWheelEvent* pEvent );

private:
    void CubeVertices( GLfloat length );
    void CubeColors( void );
    void SetupShaders( void );

    // 摄像机
    Camera          m_Camera;

    // 鼠标事件需要
    QPoint          m_LastPos;

    // 顶点缓存和颜色缓存
    GLuint          m_VertexBuffer, m_ColorBuffer;

    // 着色器
    QOpenGLShader               *m_pVertexShader, *m_pFragmentShader;

    // 着色器程序
    QOpenGLShaderProgram        m_ShaderProgram;

    // 维持宽高比的参数
    qreal           m_AspectRatio;
};

为了保证OpenGL函数调用的正确性,我们需要让我们的GLWidget继承于QOpenGLFunctions,QOpenGLFunctions类的作用是用来提供有保证的OpenGL/ES2.0函数,通常使用OpenGL函数的类需要继承它。随后我们定义了两个着色器类(QOpenGLShader类)的指针m_pVertexShader和m_pFragmentShader。之所以定义为指针是有原因的,上面一篇文章讲述了这些原因。QOpenGLShaderProgram类可以为对象也可以为指针,这依大家的喜好而定。

随后是GLWidget类的实现,这里我截取了重要的SetupShaders()函数来给大家分享。

void GLWidget::SetupShaders( void )
{
    m_pVertexShader = new QOpenGLShader( QOpenGLShader::Vertex,
                                         &m_ShaderProgram );
    CHECK( m_pVertexShader->compileSourceCode( g_VertexShaderText ),
           m_pVertexShader->log( ) );

    m_pFragmentShader = new QOpenGLShader( QOpenGLShader::Fragment,
                                           &m_ShaderProgram );
    CHECK( m_pFragmentShader->compileSourceCode( g_FragmentShaderText ),
           m_pFragmentShader->log( ) );

    CHECK( m_ShaderProgram.addShader( m_pVertexShader ),
           m_ShaderProgram.log( ) );
    CHECK( m_ShaderProgram.addShader( m_pFragmentShader ),
           m_ShaderProgram.log( ) );

    CHECK( m_ShaderProgram.link( ),
           m_ShaderProgram.log( ) );

    m_ShaderProgram.bind( );
}

如代码所示,CHECK()宏是用来检测是否出错的。这段代码,简单地说其实需要五步。首先要通过new运算符在内存中创建空间,然后调用QOpenGLShader::compileSourceCode()函数来将源代码编译成二进制格式,再使用QOpenGLShaderProgram::addShader()函数来装入shader对象,第四步是使用QOpenGLShaderProgram::link()函数来进行链接,最后一步则是将使用QOpenGLShaderProgram::bind()函数将着色器程序绑定至当前的context()中。这样的话就可以在屏幕上呈现着色的效果了。

我制作的这个小例子还带了一个着色器编辑器,像这样:


支持即时编译链接着色器,支持在GLSL规定的语法高亮,有关语法高亮的内容,感兴趣的同学可以下载一下。

最后,如果大家有好的意见和建议,可以通过程序的反馈功能将自己想说的联系我,我会及时回复的。

演示程序下载地址:这里

源代码下载地址:这里

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics