Im trying to implement deferred shading using Ogre 1.8. This is my final compositor:
compositor DeferredShadingShowLit
{
technique
{
texture rt0 target_width target_height PF_A8R8G8B8
texture_ref mrt_output DeferredShadingGBuffer mrt_output
target rt0
{
input none
shadows off
pass clear
{
identifier 1
}
pass render_quad
{
identifier 2
material DeferredShadingPostQuadLight
input 0 mrt_output 0
input 1 mrt_output 1
}
}
target_output
{
input none
pass render_quad
{
identifier 3
material DeferredShadingFinal
input 0 rt0
}
}
}
}
I need to pass the lights position, that is altered every frame to the DeferredShadingPostQuadLight
material (used to render lights). Its a simple example and i havent implemented any optimizations such as z tests and bounding volumes for lights. For that purpose im using compositor listener that is set up this way:
class LightListener : public Ogre::CompositorInstance::Listener
{
public:
LightListener(Ogre::Vector3 alightPos);
virtual ~LightListener();
virtual void notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat);
virtual void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat);
Ogre::Vector3 lightPos;
Ogre::GpuProgramParametersSharedPtr fpParams;
};
LightListener::LightListener(Ogre::Vector3 alightPos)
{
lightPos = alightPos;
}
LightListener::~LightListener()
{
}
void LightListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
//if (pass_id == 2) // This gives me error
fpParams = mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters();
}
void LightListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
//if (pass_id == 2) // This gives me error
fpParams->setNamedConstant("lightPos", lightPos);
}
The problem is i cant access passes by their id as shown in the commented lines above.
However, if the lines are commented out and i change compositor script like this:
compositor DeferredShadingShowLit
{
technique
{
texture rt0 target_width target_height PF_A8R8G8B8
texture_ref mrt_output DeferredShadingGBuffer mrt_output
target_output
{
input none
shadows off
pass clear
{
}
pass render_quad
{
material DeferredShadingPostQuadLight
input 0 mrt_output 0
input 1 mrt_output 1
}
}
}
}
fragment program of the DeferredShadingPostQuadLight
material gets updated every frame without any problems.
Thing is i need to render to rt0
first and only then to target_output
. Can you please show me what im doing wrong here? Thank you!
I finally got it figured out! Answers on Ogre forums were often misleading. I traced the pass_id
variables - the one you supply to the inherited virtual function notifyMaterialSetup
and the one you put here mat->getBestTechnique()->getPass(pass_id)
are actually completely different values. I have no idea why examples all over the internet have this code written like this. This is completely wrong. pass_id
refers to compositor passes, whereas pass_id
of mat->getBestTechnique()->getPass(pass_id)
refers to materials passes. I got my own example working simply by altering the code like this:
void LightListener::notifyMaterialSetup(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
if (pass_id == 2)
fpParams = mat->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
// I put 0 here because my material has only one pass
}
void LightListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
if (pass_id == 2)
fpParams->setNamedConstant("lightPos", lightPos);
}
Thanks for your attention!