【Ogre引擎架构】 第九讲 像素卷积的艺术-GaussianBlur高斯模糊(二)

来源:互联网 发布:csgo如何优化弹道 编辑:程序博客网 时间:2024/05/16 07:59

     ComopositorManager是ResourceManager的子类,负责管理Compositor,Compositor本身是Resource的子类,CompositorManager还持有两个重要的成员,分别是CompositorLogic和CompositorChain:

                typedef map<string,CompositorLogic*> CompositorLogicMap;CompositorLogicMap m_mCompositorLogics;typedef map<Viewport*,CompositorChain*> CompositorChainMap;CompositorChainMap m_mChains;
     展开讲解之前,先看看图,

                                     原始图:

                              

                                     只做横向模糊:

                                

                                     只做纵向模糊,

                                 

                                   横纵模糊的效果图:

                                  
              可以看到每张图的特征还是比较明显的。

    CompositorChain是最核心的一个类,它负责管理一条CompositorInstance的链表,渲染一帧的时候依次执行每一个CompositorInstance各自的CompositorInstance::RenderSystemOperation。

    程序渲染时,每一帧的渲染顺序是 

RenderTarget::UpdateImpl -> FirePreUpdate ->

 CompositorChain::PreRenderTargetUpdate ->

CompositorChain::Compile->

 CompositorInstance::TargetOperation::RenderSystemOperation::Execute

在CompositorChain::Compile产生全部需要render的TargetOperation,但是不包括最后渲染到默认FBO的那一步,最后的target_output那一步在RenderTarget::UpdateImpl函数里面FirePreUpdate后面的部分,

在Execute里面执行绘制一个Rentangle2D(继承自SimpleRenderable),绘制这个Rect的时候根据指定的材质Ogre/Compositor/HDR/GaussianBloom根据Pass里面的shader进行模糊处理。

GaussianBlur对应的合成器配置文件Example.compositor:

// Gaussian blur effect
compositor "Gaussian Blur"
{
    technique
    {
        compositor_logic GaussianBlur

        // Temporary textures
        texture rt0 target_width target_height PF_A8R8G8B8
        texture rt1 target_width target_height PF_A8R8G8B8

        target rt0
        {
            // Render output from previous compositor (or original scene)
            input previous
        }

        target rt1
        {
            // Blur horizontally
            input none
            pass render_quad
            {
                 material Ogre/Compositor/HDR/GaussianBloom
                 input 0 rt0
                 identifier 700
            }
        }

        target_output
        {
            // Start with clear output
            input none
            // Blur vertically
            pass render_quad
            {
                // Renders a fullscreen quad with a material
                 material Ogre/Compositor/HDR/GaussianBloom
                 input 0 rt1
                 identifier 701
            }
        }
    }
}

里面所用到的material是Ogre/Compositor/HDR/GaussianBloom,对应配置文件如下:

material Ogre/Compositor/HDR/GaussianBloom
{
   technique
   {
      pass
      {
         vertex_program_ref Ogre/Compositor/StdQuad_vs
         {
         }
         fragment_program_ref Ogre/Compositor/HDR/bloom_fs
         {
         }

         // Input 
         texture_unit
        {
        }
     }
   }
}

下面是执行流程的跟踪:

void RenderTarget::UpdateImpl(){FirePreUpdate();//update viewportif(m_pActiveViewport){FireViewportPreUpdate(m_pActiveViewport);m_pActiveViewport->Update();FireViewportPostUpdate(m_pActiveViewport);}}
<pre name="code" class="cpp">void RenderTarget::FirePreUpdate(){for(RenderTargetListenerList::iterator it = m_vListeners.begin();it != m_vListeners.end(); ++it){(*it)->PreRenderTargetUpdate(this);}}
void CompositorChain::PreRenderTargetUpdate(RenderTarget* target){if(m_bDirty)Compile();//else//return ;if(!m_bAnyCompositorEnabled)return ;Camera* cam = m_pViewport->GetCamera();for(CompositorInstance::CompileState::iterator it = m_CompileState.begin();it != m_CompileState.end(); ++it){//if(it->onlyInitial)//it->hasBeenRendered)//continue;//it->hasBeenRendered = true;PreTargetOperation((*it),it->target->GetViewport(),cam);it->target->Update(false);PostTargetOperation((*it),it->target->GetViewport(),cam);}}
void RSQuadOperation::Execute(SceneManager* sm,RenderSystem* rs){Pass* pass = technqiue->GetPass(0);if(pass){Rectangle2D* rect = static_cast<Rectangle2D*>(CompositorManager::GetSingleton().GetTexturedRectangle2D());//sm->InjectRenderWithPass(pass,rect);}}

CompositorChain::Compile里面会调用CompositorInstance::CollectPasses收集TargetOperation

void CompositorInstance::CollectPasses(TargetOperation& targetOp,CompositionTargetPass* target){MaterialPtr mat,srcmat;Technique* srctech;Pass* targetpass,*srcpass;CompositionTargetPass::Passes& passes = target->GetPasses();for(CompositionTargetPass::Passes::iterator it = passes.begin();it != passes.end(); ++it){CompositionPass* pass = *it;switch(pass->GetType()){case CompositionPass::PT_CLEAR:QueueRenderSystemOp(targetOp,new RSClearOperation(pass->GetClearBuffers(),pass->GetClearColor(),pass->GetClearDepth(),pass->GetClearStencil()));break;case CompositionPass::PT_RENDERSCENE://targetOp.currentQueueGroupID = pass->GetLastRenderQueue()+1;targetOp.findVisibleObjects = true;break;case CompositionPass::PT_RENDERQUAD:srcmat = pass->GetMaterial();if(srcmat.IsNull()){LOGERROR("CompositorInstance::CollectPasses material is null");return ;}//srcmat->Load();srctech = srcmat->GetTechnique(0);srcpass = srctech->GetPass(0);MaterialPtr mat = CreateLocalMaterial(srcmat->GetName());Technique* tech = mat->CreateTechnique();targetpass = tech->CreatePass();//use srcpass*targetpass = *srcpass;//set input texconst CompositionPass::InputTex& inTex = pass->GetInput(0);string texName = m_pCompositor->GetName()+"/"+inTex.name;targetpass->GetTextureUnitState()->SetTextureName(texName,TEX_TYPE_2D);//queueQueueRenderSystemOp(targetOp,new RSQuadOperation(this,pass->GetIdentifier(),mat));break;}}}
最后是所用到的shader文件(glsl),

vertex:

#version 400
in vec3 vertex;
in vec3 normal;
in vec2 uv0;

uniform mat4 MVP;

out vec2 uv;
out vec3 outNormal;
//out vec2 outUV;


void main()
{
    gl_Position = MVP * vec4(vertex,1.0);

    //vec2 inPos = sign(vertex.xy);

    //uv = (vec2(inPos.x, inPos.y) + 1.0)/2.0;
    uv = uv0;
    outNormal = normal;
}

fragment:

#version 400
uniform sampler2D inRTT;
uniform vec4 sampleOffsets[15];
uniform vec4 sampleWeights[15];

in vec2 uv;
void main(void)
{
    vec4 accum = vec4(0.0, 0.0, 0.0, 1.0);
    vec2 sampleUV;
    
    for( int i = 0; i < 15; i++ )
    {
        // Sample from adjacent points, 7 each side and central
        sampleUV = uv + sampleOffsets[i].xy;
        accum += sampleWeights[i] * texture2D(inRTT, sampleUV);
    }
    
    gl_FragColor = accum;

}


0 0
原创粉丝点击