您的位置:首页 > 运维架构 > 网站架构

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

2015-12-15 11:05 691 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: