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

     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 viewport
		if(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 tex
						const CompositionPass::InputTex& inTex = pass->GetInput(0);
						string texName = m_pCompositor->GetName()+"/"+inTex.name;
						targetpass->GetTextureUnitState()->SetTextureName(texName,TEX_TYPE_2D);
						//queue
						QueueRenderSystemOp(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;

}


你可能感兴趣的:(【Ogre引擎架构】 第九讲 像素卷积的艺术-GaussianBlur高斯模糊(二))