Qt 3D教程(三)实现对模型材质参数的控制

来源:互联网 发布:天津大悦城it电话 编辑:程序博客网 时间:2024/04/26 17:59

Qt 3D教程(三)实现对模型材质参数的控制

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/47131841。欢迎同行前来探讨。

       上一篇教程介绍的是显示一个三维模型的基本步骤,接下来我们需要实现的是添加材质,并且希望我们通过按钮来控制材质的参数。这样的效果看起来很像一个3D模型材质编辑器的样子。那我们来尝试一下吧。

       首先我们对Settings这个类进行修改,给它增添一些属性,比如说环境光、漫反射、镜面反射以及反射系数。通过Q_PROPERTY宏以及一系列的setter和getter函数,我们就可以做到这一点。

class Settings: public QObject{    Q_OBJECT    Q_PROPERTY( bool showModel READ showModel WRITE setShowModel NOTIFY showModelChanged )    Q_PROPERTY( QColor ambient READ ambient WRITE setAmbient NOTIFY ambientChanged )    Q_PROPERTY( QColor diffuse READ diffuse WRITE setDiffuse NOTIFY diffuseChanged )    Q_PROPERTY( QColor specular READ specular WRITE setSpecular NOTIFY specularChanged )    Q_PROPERTY( float shininess READ shininess WRITE setShininess NOTIFY shininessChanged )public:    explicit Settings( QObject* parent = Q_NULLPTR );    bool showModel( void ) { return m_showModel; }    void setShowModel( bool showModel );    QColor ambient( void ) { return m_ambient; }    void setAmbient( const QColor& ambient );    QColor diffuse( void ) { return m_diffuse; }    void setDiffuse( const QColor& diffuse );    QColor specular( void ) { return m_specular; }    void setSpecular( const QColor& specular );    float shininess( void ) { return m_shininess; }    void setShininess( float shininess );signals:    void showModelChanged( void );    void ambientChanged( void );    void diffuseChanged( void );    void specularChanged( void );    void shininessChanged( void );protected:    bool            m_showModel;    QColor          m_ambient, m_diffuse, m_specular;    float           m_shininess;};

下面是Settings一些函数的实现:

Settings::Settings( QObject* parent ): QObject( parent ){    m_showModel = true;    m_ambient = QColor( 153, 51, 26 );    m_diffuse = QColor( 51, 153, 26 );    m_specular = QColor( 153, 230, 26 );    m_shininess = 0.6;}void Settings::setShowModel( bool showModel ){    if ( m_showModel == showModel ) return;    m_showModel = showModel;    emit showModelChanged( );}void Settings::setAmbient( const QColor& ambient ){    if ( m_ambient == ambient ) return;    m_ambient = ambient;    emit ambientChanged( );}void Settings::setDiffuse( const QColor& diffuse ){    if ( m_diffuse == diffuse ) return;    m_diffuse = diffuse;    emit diffuseChanged( );}void Settings::setSpecular( const QColor& specular ){    if ( m_specular == specular ) return;    m_specular = specular;    emit specularChanged( );}void Settings::setShininess( float shininess ){    if ( m_shininess == shininess ) return;    m_shininess = shininess;    emit shininessChanged( );}

       随后我们声明槽函数,点击环境光、漫反射和镜面反射的时候,它都会设置按钮的背景色,然后设置m_settings的相关成员。

 

void MainWindow::decorateButton( QPushButton* button, const QColor& color ){    QString styleSheetTemplate( "background: rgb( %1, %2, %3 )" );    QString styleSheet = styleSheetTemplate.                         arg( color.red( ) ).arg( color.green( ) ).                         arg( color.blue( ) );    button->setStyleSheet( styleSheet );}void MainWindow::on_ambientButton_clicked(){    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );    QColor color, prevColor;    prevColor = m_settings.ambient( );    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );    decorateButton( button, color );    m_settings.setAmbient( color );}void MainWindow::on_diffuseButton_clicked(){    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );    QColor color, prevColor;    prevColor = m_settings.diffuse( );    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );    decorateButton( button, color );    m_settings.setDiffuse( color );}void MainWindow::on_specularButton_clicked(){    QPushButton* button = qobject_cast<QPushButton*>( sender( ) );    QColor color, prevColor;    prevColor = m_settings.specular( );    color = QColorDialog::getColor( prevColor, this, "请选择一个颜色" );    decorateButton( button, color );    m_settings.setSpecular( color );}void MainWindow::on_shininessEdit_returnPressed( void ){    m_settings.setShininess( ui->shininessEdit->text( ).toFloat( ) );}

最后我们在QML中添加PhongMaterial这个类,这个类在C++中是Qt3D::Render::QPhongMaterial,它提供了基于Phong光照模型的这样的材质,提供了一种非常真实的显示效果。我们使用_settings这个上下文属性将上述的材质属性绑定到PhongMaterial中。添加了PhongMaterial的QML代码如下:

import Qt3D 2.0import Qt3D.Renderer 2.0Entity{    id: root    Camera    {        id: camera        position: Qt.vector3d( 0.0, 20.0, 100.0 )        projectionType: CameraLens.PerspectiveProjection        fieldOfView: 45        aspectRatio: 16.0 / 9.0        nearPlane : 0.1        farPlane : 1000.0        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )        viewCenter: Qt.vector3d( 0.0, 20.0, 0.0 )    }    components: FrameGraph    {        ForwardRenderer        {            clearColor: Qt.rgba( 0.2, 0, 0, 1 )            camera: camera        }    }    Entity    {        Mesh        {            id: chestMesh            source: "qrc:/assets/Chest.obj"            enabled: _settings.showModel        }        // 新添加的内容        PhongMaterial        {            id: phongMaterial            ambient: _settings.ambient            diffuse: _settings.diffuse            specular: _settings.specular            shininess: _settings.shininess        }        components: [ chestMesh, phongMaterial ]    }    Configuration    {        controlledCamera: camera    }}

         程序运行截图如下:

       本次教程的代码均在我的github中,感兴趣的同行们可以通过git clone或者是直接下载我的git项目来获取到本套教程的所有源代码。

 

1 0