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


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

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

           上一篇教程介绍的是显示一个三维模型的基本步骤,接下来我们须要实现的是加入材质,而且希望我们通过button来控制材质的參数。

    这种效果看起来非常像一个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( );
    }

           随后我们声明槽函数,点击环境光、漫反射和镜面反射的时候。它都会设置button的背景色,然后设置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.0
    import Qt3D.Renderer 2.0
    
    Entity
    {
        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项目来获取到本套教程的全部源码。

  • 相关阅读:
    一些你可能用到的代码
    iOS 键盘下去的方法
    iOS设计模式汇总
    随笔
    Spring cloud config 分布式配置中心 (三) 总结
    Spring cloud config 分布式配置中心(二) 客户端
    Spring cloud config 分布式配置中心(一) 服务端
    jdbcUrl is required with driverClassName spring boot 2.0版本
    JpaRepository接口找不到 spring boot 项目
    解决IntelliJ “Initialization failed for 'https://start.spring.io'
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7079488.html
Copyright © 2020-2023  润新知