Ogre3d /访问通过合成器侦听器传递并传递标识符

时间:2012-12-21 08:29:58

标签: c++ ogre ogre3d

我尝试使用Ogre 1.8实现延迟着色。这是我最后的合成者:

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
            }
        }
    }
}

我需要传递灯光位置,每个帧都改变为DeferredShadingPostQuadLight材质(用于渲染灯光)。它是一个简单的例子,我还没有实现任何优化,例如z测试和灯光的边界体积。为此目的,我使用以这种方式设置的合成器监听器:

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);
}

问题是我无法访问其ID,如上面的注释行所示。

但是,如果这些行被注释掉了,我改变了这样的合成器脚本:

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
            }
        }
    }
}

DeferredShadingPostQuadLight材料的片段程序每帧都会更新,没有任何问题。

我需要先向rt0渲染,然后再渲染到target_output。你能告诉我这里我做错了什么吗?谢谢!

1 个答案:

答案 0 :(得分:0)

我终于搞清楚了! Ogre论坛上的答案经常会产生误导。我跟踪了pass_id个变量 - 你提供给继承的虚函数notifyMaterialSetup的变量,你放在这里的变量mat->getBestTechnique()->getPass(pass_id)实际上是完全不同的值。我不知道为什么整个互联网上的例子都有这样的代码。这是完全错误的。 pass_id指合成器通行证,pass_id mat->getBestTechnique()->getPass(pass_id)指物质通行证。我通过改变代码来得到我自己的例子:

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);
}

感谢您的关注!