zoukankan      html  css  js  c++  java
  • ogre ofusion材质动画使用shader实现

    ofusion导出3dmax中的动画到osm文件,其默认的osmscene加载,没有对material进行材质拷贝.当多个动画不同时播放,而又用到了相同的材质时,就会出现错误.因为ogre的实体默认使用的是全局的material引用.因此需要对material进行拷贝,然后实体重新载入新的material.

    另一种方法是在shader中实现材质动画.主要处理alpha的变化,及纹理动画.

    .h

    View Code
    #ifndef __ShaderAlphaAnimationComponent_h__
    #define __ShaderAlphaAnimationComponent_h__
    
    #include "AlphaAnimationComponent.h"
    
    /************************************************************************/
    /* 说明
        该组件在加载osm的回调函数中配合使用,实现材质的alpha动画
            在OnEntityCreate(Ogre::Entity *pEntity, rapidxml::xml_node<>* pEntityDesc)回调函数中
            使用addEntity(pEntity).
            在OnMaterialAnimatorLoaded(const oMaterialAnimation& materialAnim)回调函数中
            使用pushBack(materialAnim).
        之后即可如之前的alpha组件一样,调用enable,update正常使用.
    
    */
    /************************************************************************/
    
    
        class ShaderPassAnimation;
        class ShaderAlphaAnimationComponent
        {
            typedef boost::shared_ptr<ShaderPassAnimation>  ShaderPassAnimationPtr;
            typedef std::vector<Ogre::Entity*>          EntityList;
        public:
            ShaderAlphaAnimationComponent(void);
            virtual ~ShaderAlphaAnimationComponent(void);
            
        private:
    
            bool enable(int times);
            bool update(TimeType time);
            void disable(void);
            void pushBack(const oMaterialAnimation& materialAnim);
    
            void addEntity(Ogre::Entity* entity);
    
            ComponentQueryInterface _query;    
            boost::scoped_ptr<ShaderAlphaAnimationInterface>    _saaInterface;
            std::vector<ShaderPassAnimationPtr> _passes;
            int _times;
            
    
        };
    
        class ShaderPassAnimation
        {
        public:
            typedef        std::vector<Ogre::SubEntity*>    MySubEntityList;
    
            ShaderPassAnimation(const oMaterialAnimation& materialAnim, const oPassAnimation& passAnim);
            ~ShaderPassAnimation(void);
            bool enable(void);
            bool update(TimeType time);
            void disable(void);
            void setTransparency(float transparency);
            void addSubEntity(Ogre::SubEntity* subEnt) { subEntityList.push_back(subEnt); }
        public:
            oPassAnimation  _passAnim;
            TimeType _time;
            std::string _materialName;
            unsigned int _techniqueIndex;
            float _currentTransparency;
    
            Ogre::ColourValue _ambient;
            Ogre::ColourValue _diffuse; 
            Ogre::SceneBlendType _SBT;
            oPassAnimation::AlphaKeyFramesList::iterator _it;
    
            
            Ogre::Technique*    _technique;
            MySubEntityList        subEntityList;
    
    
        };
    
    #endif

    .cpp

    View Code
    #include "ShaderAlphaAnimationComponent.h"
    
    
    
    ShaderPassAnimation::ShaderPassAnimation(const oMaterialAnimation& materialAnim, const oPassAnimation& passAnim):
    _passAnim(passAnim),
    _time(0.f),
    _materialName(materialAnim.materialName),
    _techniqueIndex(materialAnim.techniqueIndex),
    _SBT(Ogre::SBT_TRANSPARENT_ALPHA)
    {
        _it = _passAnim.alphaKeyFrames.begin();
        _currentTransparency = 0.0f;
    
    }
    ShaderPassAnimation::~ShaderPassAnimation(void)
    {
    
    }
    
    void ShaderPassAnimation::setTransparency(float transparency)
    {
    
        _currentTransparency = transparency;
        if (_currentTransparency >= 0.0f) 
        {
            if (_currentTransparency > 1.0f)
                _currentTransparency = 1.0f;
    
            MySubEntityList::iterator it = subEntityList.begin();
            for(; it != subEntityList.end(); ++it)
            {
                Ogre::SubEntity* subEnt = *it;
                subEnt->setCustomParameter(1, Ogre::Vector4(0, 0, 0, _currentTransparency));
            }
        }
    }
    
    bool ShaderPassAnimation::enable(void)
    {
        MySubEntityList::iterator it = subEntityList.begin();
        for(; it != subEntityList.end(); ++it)
        {
            Ogre::SubEntity* subEnt = *it;
            Ogre::MaterialPtr pMat = subEnt->getMaterial();
            int numTechniques = pMat->getNumTechniques();
            for (int i = 0; i < numTechniques; i++)
            {
                Ogre::Technique* pTechnique = pMat->getTechnique(i);
                int numPasses = pTechnique->getNumPasses();
                for (int j = 0; j < numPasses; j++)
                {
                    Ogre::Pass* pPass = pTechnique->getPass(j);
                    pPass->setVertexProgram("MaterialAlphaAnimatinVP");
                    pPass->setFragmentProgram("MaterialAlphaAnimatinFP");
                }
            }
            break;
        }
    
        _time = 0.f;
        _it = _passAnim.alphaKeyFrames.begin();
        update(0.f);
    
        return true;
    }
    bool ShaderPassAnimation::update(TimeType time)
    {
        _time += time;
        if(_time > _passAnim.alphaLength)
            return false;
    
        if(_it == _passAnim.alphaKeyFrames.end())
            return true;
        if(_time >= _it->first)
        {
            setTransparency(1.0f- _it->second);
            ++_it;
        }else if(_it != _passAnim.alphaKeyFrames.begin() && _it != _passAnim.alphaKeyFrames.end())
        {
    
            oPassAnimation::AlphaKeyFramesList::iterator last = _it;
            last--;
            
    
            float s = (_time - last->first)/ (_it->first - last->first);
            float alpha = (last->second) * (1.f-s) + (_it->second * s);
            setTransparency(1.0f- alpha);
    
        }
    
        return true;
    }
    void ShaderPassAnimation::disable(void)
    {    
        MySubEntityList::iterator it = subEntityList.begin();
        for(; it != subEntityList.end(); ++it)
        {
            Ogre::SubEntity* subEnt = *it;
            subEnt->setCustomParameter(1, Ogre::Vector4(0, 0, 0, 1));
        }
    
    }
    
    //////////////////////////////////////////////////////////////////////////
    ShaderAlphaAnimationComponent::ShaderAlphaAnimationComponent():
    _times(0.f)
    {
    
    }
    
    ShaderAlphaAnimationComponent::~ShaderAlphaAnimationComponent(void)
    {
    
    }
    
    ComponentInterface * ShaderAlphaAnimationComponent::_queryInterface(const TypeInfo & info)
    {
        return _query.queryInterface(info);
    }
    
    
    void ShaderAlphaAnimationComponent::pushBack(const oMaterialAnimation& materialAnim)
    {
    
        BOOST_FOREACH(const oPassAnimation & pa, materialAnim.passAnims)
        {    
            ShaderPassAnimationPtr pp(new ShaderPassAnimation(materialAnim, pa));
            _passes.push_back(pp);
        }
    
    }
    
    void ShaderAlphaAnimationComponent::addEntity(Ogre::Entity* entity)
    {
        if(entity == NULL) return;
    
        int subEntNum = entity->getNumSubEntities();
        for (int i = 0; i < subEntNum; i++)
        {
            Ogre::SubEntity* subEntity =  entity->getSubEntity(i);
            Ogre::String matName = subEntity->getMaterial()->getName();
    
            std::vector<ShaderPassAnimationPtr>::iterator it = _passes.begin();
            for (; it != _passes.end(); ++it)
            {
                if ((*it)->_materialName == matName)
                    (*it)->addSubEntity(subEntity);
            }
        }
    
    }
    
    bool ShaderAlphaAnimationComponent::enable(int times)
    {
    
        _times = times;
        BOOST_FOREACH(ShaderPassAnimationPtr pa  ,_passes)
        {
    
            if(!pa->enable())
                return false;
    
        }
        --_times;
        return true;
    }
    bool ShaderAlphaAnimationComponent::update(TimeType time)
    {
    
        bool ret = false;
    
        BOOST_FOREACH(ShaderPassAnimationPtr pa  ,_passes)
        {
            ret = pa->update(time) | ret;
        }
        if(ret == false && _times == 0)
        {
            if( _times == 0)
            {
                return false;
            }
            else
            {
                _times--;
                disable();
            }
        }        
        return true;
    }
    void ShaderAlphaAnimationComponent::disable(void)
    {
        BOOST_FOREACH(ShaderPassAnimationPtr pa  ,_passes)
        {
            pa->disable() ;
        }
    
    }

    oMaterialAnimation这个类在ofusion提供的osmscene加载文件中有定义.主要是将alpha变化值传入cg中.

    .cg

    void main_vp(float4 position    : POSITION,
                 float2 uv            : TEXCOORD0, 
                    // outputs
                    out float4 oPosition    : POSITION,
                    out float2 outUV : TEXCOORD0,
                    // parameters
                    uniform float4x4 texMatrix,
                    uniform float4x4 worldViewProj)
    {
        oPosition = mul(worldViewProj, position);
        outUV = mul(texMatrix,float4(uv,0,1)).xy;
    }
    
    void main_fp(out float4 color : COLOR,
                    float2 uv : TEXCOORD0,
                    uniform sampler2D texture : register(s0),
                    uniform float4 alphaFactor
                    )
    {
        color = tex2D(texture, uv);
        color.xyz = color.w * color.xyz;
        color.w = 1 - alphaFactor.w;
    }

    注意顶点程序中的outUV = mul(texMatrix,float4(uv,0,1)).xy;纹理动画转换.

    .program

    vertex_program MaterialAlphaAnimatinVP cg
    {
        source MaterialAlphaAnimation.cg
        entry_point main_vp
        profiles vs_1_1 arbvp1
    
        default_params
        {
            param_named_auto texMatrix texture_matrix   0
            param_named_auto worldViewProj worldviewproj_matrix
        }
    }
    
    fragment_program MaterialAlphaAnimatinFP cg
    {
        source MaterialAlphaAnimation.cg
        entry_point main_fp
        profiles ps_1_1 arbfp1 fp20
     
        default_params
        {
            param_named_auto alphaFactor custom 1
        }
    }
  • 相关阅读:
    C# 用装饰模式
    31天重构学习笔记4. 降低方法
    JData 使用教程 对输入数据进行验证(服务端验证)
    sql over的作用及用法
    31天重构学习笔记3. 提升方法
    《博客园精华集》
    const和static readonly 区别
    JData 使用教程(四) 对输入数据进行验证(客户端验证)
    用JQuery制作简单实用的下拉菜单
    图片压缩后,依然很大的解决方案
  • 原文地址:https://www.cnblogs.com/flytrace/p/2499703.html
Copyright © 2011-2022 走看看