合成器框架Compositor
合成器框架脚本**.compositior
工作原理:合成器框架是在场景已被渲染后来改变场景的显示,是一种后处理技术。
1.合成器框架将已经渲染的场景渲染到一个texture上去。
2.然后根据需要改变这个texture的内容。
3.为了渲染texture中的改变后的场景,需要创建一个quad用来cover the monitor。
4. 将texture渲染到quad中去(也即是渲染到屏幕上去)。
调用流程:
1. 代码中加入合成器框架。
2. 合成器脚本中定义被渲染到的纹理和输出目标quad。
3. 被渲染到的纹理在mayerial文件夹下面的*.material文件。
4. *.material中定义了用到的fragment_program_ref。
1 compositor compositor1
2 {
3 technique
4 {
5 // 定义场景被渲染到的纹理
6 texture scene target_width target_height PF_R8G8B8
7 // 定义纹理的内容
8 target scene
9 {
10 // 内容是当前被渲染的场景
11 input previous
12 }
13
14 //定义合成器的输出。合成器不需要输入,并将其结果输出到quad。
15 //quad需要用到材质mymaterial18,并需要我们的scene target作为纹理输入
16 target_output
17 {
18 // quad有一个输入参数
19 input one
20 pass render_quad
21 {
22 //quad需要用到材质mymaterial18
23 material mymaterial18
24 // quad用该合成器的渲染目标:secene作为其输入
25 input 0 secene
26 }
27 }
28 }
29 }
1 material mymaterial18
2 {
3 technique
4 {
5 pass
6 {
7 fragment_program_ref myfragmentshader5
8 {
9 }
10
11 texture_unit
12 {
13 }
14 }
15 }
16 }
17
18
19 fragment_program myfragmentshader5 cg
20 {
21 source Ogre3DBeginnersGuideShaders.cg
22 entry_point myfragmentshader5
23 profiles ps_1_1 arbfp1
24 }
1 void myfragmentshader5(
2 float2 uv: TEXCOORD0,
3 out float4 color : COLOR,
4 uniform sampler2D texture
5 )
6 {
7 float4 tmp_color = tex2D(texture, uv);
8 float grey_value = tmp_color.r * 0.3 + tmp_color.g * 0.59 +
9 tmp_color.b * 0.11;
10 color = float4(grey_value, grey_value, grey_value, 0);
11 }
可以将2个合成器组合到一起用,此时在合成器脚本中需要创建2个纹理,一个用来保存场景,一个用来保存中间结果。
compositor compositor2
{
technique
{
texture scene target_width target_height PF_R8G8B8
texture tmp target_width target_height PF_R8G8B8
target scene
{
input previous
}
// 1.合成器将场景内容render到scene;
// 2.利用mymaterial18(材质定义中调用fragment_program)对scene的内容进行处理后保存到tmp
// 3.利用mymaterial19(材质定义中调用fragment_program)对tmp的内容处理后输出到quad
target tmp
{
pass render_quad
{
material mymaterial18
input 0 scene
}
}
target_output
{
input one
pass render_quad
{
material mymaterial19
input 0 tmp
}
}
}
}
也可以只用一个纹理而不需要2个纹理:
compositor compositor3
{
technique
{
texture scene target_width target_height PF_R8G8B8
target scene
{
input previous
}
target scene
{
pass render_quad
{
material mymaterial18
input 0 scene
}
}
target_output
{
input one
pass render_quad
{
material mymaterial19
input 0 scene
}
}
}
}
将2个合成器组合到一起用时也可以不用重新写一个合成器脚本,只需要在代码里加入2个合成器即可,得到一个合成器链,最终结果就是这个链上的每个合成器的结果的累加。
Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "compositor1");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "compositor1", true);
Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "compositor2");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "compositor2", true);
也可以不在材质脚本或者合成器脚本中修改场景
而通过程序修改:
// 合成器的listener
class CompositorListener1 : public Ogre::CompositorInstance::Listener
{
public:
// 当材质创建时会调用该函数
void notifyMaterialSetup(uint32 pass_id, MaterialPtr& mat)
{
// 修改材质的像素参数
mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()
->setNamedConstant("numPixels", 125.0f);
}
private:
};
class MyApplication :public ExampleApplication
{
public:
MyApplication() {compositorListener_ = 0;}
~MyApplication()
{
if (compositorListener_)
{
delete compositorListener_;
}
}
void createScene()
{
Ogre::Entity* ent1 = mSceneMgr->createEntity("entity1", "Sinbad.mesh");
ent1->setMaterial(Ogre::MaterialManager::getSingleton().getByName("mymaterial11"));
Ogre::SceneNode* node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("node1", Ogre::Vector3(0, 0, 450));
node1->attachObject(ent1);
// 加入和启用合成器
Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "compositor8");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "compositor8", true);
// 取得合成器的指针
Ogre::CompositorInstance* comp
= Ogre::CompositorManager::getSingleton().getCompositorChain(mCamera->getViewport())->getCompositor("compositor8");
// 创建合成器监听器,并将其加入到合成器中去
compositorListener_ = new CompositorListener1;
comp->addListener(compositorListener_);
}
private:
CompositorListener1* compositorListener_;
};
当程序运行的时候通过用户的输入来改变像素数目:
1 // 合成器的listener
2 class CompositorListener1 : public Ogre::CompositorInstance::Listener
3 {
4 public:
5 CompositorListener1(){number_ = 125.0;}
6
7
8 // 当材质渲染时会调用该函数
9 void notifyMaterialRender(uint32 pass_id, MaterialPtr& mat)
10 {
11 // 修改材质的像素参数
12 mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()
13 ->setNamedConstant("numPixels", number_);
14 }
15
16 void setNumber(float num)
17 {
18 number_ = num;
19 }
20
21 float getNumber()
22 {
23 return number_;
24 }
25
26 private:
27 float number_;
28 };
29
30
31 class MyFrameListener : public Ogre::FrameListener
32 {
33 public:
34 MyFrameListener(RenderWindow* win, CompositorListener1* listener)
35 {
36 compListener_ = listener;
37 size_t windHnd = 0;
38 std::stringstream winHndStr;
39 win->getCustomAttribute("WINDOW", &windHnd);
40 winHndStr << windHnd;
41
42 OIS::ParamList pl;
43 pl.insert(std::make_pair(std::string("WINDOW"), winHndStr.str()));
44 inputmgr_ = OIS::InputManager::createInputSystem(pl);
45 keyboard_ = static_cast<OIS::Keyboard*>(inputmgr_->createInputObject(OIS::OISKeyboard, false));
46 }
47
48 ~MyFrameListener()
49 {
50 inputmgr_->destroyInputObject(keyboard_);
51 OIS::InputManager::destroyInputSystem(inputmgr_);
52 }
53
54 bool frameStarted(const Ogre::FrameEvent& evt)
55 {
56 keyboard_->capture();
57 if (keyboard_->isKeyDown(OIS::KC_ESCAPE))
58 {
59 return false;
60 }
61
62 if (keyboard_->isKeyDown(OIS::KC_UP))
63 {
64 float num = compListener_->getNumber();
65 ++num;
66 compListener_->setNumber(num);
67 }
68
69 if (keyboard_->isKeyDown(OIS::KC_DOWN))
70 {
71 float num = compListener_->getNumber();
72 --num;
73 compListener_->setNumber(num);
74 }
75
76 return true;
77 }
78
79 private:
80 OIS::InputManager* inputmgr_;
81 OIS::Keyboard* keyboard_;
82 CompositorListener1* compListener_;
83 };
84
85 class MyApplication :public ExampleApplication
86 {
87 public:
88 MyApplication() {compositorListener_ = 0; listener_ = 0;}
89 ~MyApplication()
90 {
91 if (compositorListener_)
92 delete compositorListener_;
93 if (listener_)
94 delete listener_;
95 }
96
97 void createFrameListener()
98 {
99 listener_ = new MyFrameListener(mWindow, compositorListener_);
100 mRoot->addFrameListener(listener_);
101 }
102
103 void createScene()
104 {
105 Ogre::Entity* ent1 = mSceneMgr->createEntity("entity1", "Sinbad.mesh");
106 ent1->setMaterial(Ogre::MaterialManager::getSingleton().getByName("mymaterial1"));
107
108 Ogre::SceneNode* node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("node1", Ogre::Vector3(0, 0, 450));
109 node1->attachObject(ent1);
110
111 // 加入和启用合成器
112 Ogre::CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "compositor8");
113 Ogre::CompositorManager::getSingleton().setCompositorEnabled(mCamera->getViewport(), "compositor8", true);
114
115 // 取得合成器的指针
116 Ogre::CompositorInstance* comp
117 = Ogre::CompositorManager::getSingleton().getCompositorChain(mCamera->getViewport())->getCompositor("compositor8");
118
119 // 创建合成器监听器,并将其加入到合成器中去
120 compositorListener_ = new CompositorListener1;
121 comp->addListener(compositorListener_);
122 }
123
124 private:
125 CompositorListener1* compositorListener_;
126 Ogre::FrameListener* listener_;
127 };
128
129
130 int main()
131 {
132 MyApplication app;
133 app.go();
134 return 0;
135 }