Page 1 of 1

Android Compositor Rendertarget listener not called

Posted: Wed Apr 10, 2013 8:47 pm
by Emerich
Hi all,

I'm trying to get red cyan anaglyphic stereo to run on Android.
As for the setup: I'm running a custom project on my Android device with ogre 1.9 compiled according to the CMake quick build tut by the great wolfman.
It starts and runs and stuff but when I try to apply my compositor and the listeners to the two render targets, they simply never get called.

Now I know the material and all work, since I can change the shader i wrote and i get different coloring in my scene.

I took the Stereomanager apart since it wouldn't work on Android and came up with the following minimal example:

Code: Select all

class myRenderTargetListener: public Ogre::RenderTargetListener
{
public:
	virtual void preRenderTargetUpdate (const Ogre::RenderTargetEvent& evt)
	{
//never thrown
		__android_log_write(ANDROID_LOG_VERBOSE, "DEBUGGING", "myRenderListener preRenderTargetUpdate");
	}
	virtual void postRenderTargetUpdate  (const Ogre::RenderTargetEvent& evt)
	{
//never thrown
		__android_log_write(ANDROID_LOG_VERBOSE, "DEBUGGING", "myRenderListener postRenderTargetUpdate");
	}
	virtual void preViewportUpdate (const Ogre::RenderTargetViewportEvent &evt)
	{
//never thrown
		__android_log_write(ANDROID_LOG_VERBOSE, "DEBUGGING", "myRenderListener preViewportUpdate");
	}
	virtual void postViewportUpdate (const Ogre::RenderTargetViewportEvent &evt)
	{
//never thrown
		__android_log_write(ANDROID_LOG_VERBOSE, "DEBUGGING", "myRenderListener postViewportUpdate");
	}
};

void MyApp::setupViewport(Ogre::SceneManager *curr)
{	
	Ogre::String materialName="Stereo/RedCyanAnaglyph";
	Ogre::Viewport *vp = mWindow->addViewport(mCamera); //Our Viewport linked to the camera
	Ogre::CompositorInstance* mCompositorInstance = CompositorManager::getSingleton().addCompositor(vp, "Stereo/BaseCompositor");
	if(!mCompositorInstance)
		OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Cannot create compositor, missing StereoManager resources",
		"StereoManager::initCompositor"); //not thrown
	CompositorManager::getSingleton().setCompositorEnabled(vp, "Stereo/BaseCompositor", true);

	MaterialPtr mat = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(materialName));
	if(mat.isNull())
		OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, materialName + " not found, missing StereoManager resources",
		"StereoManager::initCompositor"); //not thrown

	mCompositorInstance->getTechnique()->getOutputTargetPass()->getPass(0)->setMaterial(mat);
	Ogre::RenderTarget* leftTarget = mCompositorInstance->getRenderTarget("Stereo/Left");
	Ogre::RenderTarget* rightTarget = mCompositorInstance->getRenderTarget("Stereo/Right");
	Ogre::Viewport* out_left = leftTarget->getViewport(0);
	Ogre::Viewport* out_right = rightTarget->getViewport(0);
	leftTarget->addListener(new myRenderTargetListener());
	rightTarget->addListener(new myRenderTargetListener());
}
Now the necessary compositor, taken from the StereoManager:

Code: Select all

compositor Stereo/BaseCompositor
{
    technique
    {
        // Temporary textures
        texture Stereo/Left target_width target_height PF_R8G8B8
        texture Stereo/Right target_width target_height PF_R8G8B8

        target Stereo/Left
        {
            input none
            pass clear
			{
			}
            pass render_scene 
            {
            }
        }
        
        target Stereo/Right
        {
            input none
            pass clear
			{
			}
			pass render_scene 
            {
            }
        }

        target_output
        {
            // Start with clear output
            input none
            pass render_quad
            {
                // Renders a fullscreen quad with a material
                // redefined by the manager
                material Stereo/BaseCompositorMaterial
                input 0 Stereo/Left
                input 1 Stereo/Right
            }
        }
    }
}
the material from the StereoManager, modified to support GLSLES

Code: Select all

fragment_program Stereo/Anaglyph_RC_GLSLES_FP glsles
{
	default_params
	{
		param_named LEFT_MASK float4 1.0 1.0 0.0 1.0
		param_named RIGHT_MASK float4 0.0 0.0 1.0 1.0
		param_named Left int 0
		param_named Right int 1
	}
	source redcyan.glsles
}

fragment_program Stereo/Anaglyph_RC unified
{
	//delegate Stereo/Anaglyph_RC_GLSL_FP
	delegate Stereo/Anaglyph_RC_GLSLES_FP
	//delegate Stereo/Anaglyph_RC_CG_FP
}



material Stereo/BaseCompositorMaterial
{
	technique
	{
		pass
		{
			vertex_program_ref Ogre/Compositor/StdQuad_vp
			{
			}
			
			texture_unit Left
			{
				tex_address_mode clamp
				filtering linear linear none
				tex_coord_set 0
				texture_alias Left
			}
			
			texture_unit Right
			{
				tex_address_mode clamp
				filtering linear linear none
				tex_coord_set 0
				texture_alias Right
			}
		}
	}
}
material Stereo/RedCyanAnaglyph : Stereo/BaseCompositorMaterial
{
	technique
	{
		pass
		{		
			fragment_program_ref Stereo/Anaglyph_RC
			{
			}
		}
	}
}
And finally the shader.. redcyan.glsles

Code: Select all

#version 100

precision mediump int;
precision mediump float;

uniform sampler2D Left;
uniform sampler2D Right;
uniform vec4 LEFT_MASK;
uniform vec4 RIGHT_MASK;
varying vec2 uv;

void main()
{
	vec4 left = texture2D(Left, uv);
	vec4 right = texture2D(Right, uv);
	//this is the actual thing. the others were for testing purposes:
	//gl_FragColor = left * LEFT_MASK + right * RIGHT_MASK;
	//testing:
	//gl_FragColor = right;
	//testing:
	//gl_FragColor = left * LEFT_MASK;
	//testing:
	gl_FragColor = right * RIGHT_MASK;
}
I would really appreciate some advice on how to solve that- especially since the same code works just fine on my Windows host. Meaning that the listeners get called when compiling and running the code on Windows

Re: Android Compositor Rendertarget listener not called

Posted: Fri Apr 12, 2013 4:23 pm
by Emerich
I don't know whether anyone cares or runs into this issue but here's my workaround:

After lots and lots of tries i saw that the callbacks do happen when the textures have a size specified.

For instance:

Code: Select all

{//texture rt1 128 128 PF_A8R8G8B8 in the script file
	Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt1");
	def->width = 128;
	def->height = 128;
	def->formatList.push_back(Ogre::PF_A8R8G8B8);
}
that gave me events... whereas this didn't:

Code: Select all

{//texture rt0 target_width target_height PF_A8R8G8B8  in the script file
	Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt0");
	def->width = 0;//this translates to target_width...
	def->height = 0;
	def->formatList.push_back(Ogre::PF_A8R8G8B8);
}
So i rebuilt the script on my own and added my own listeners:

Code: Select all

Ogre::Viewport *vp = mWindow->addViewport(mCamera);
Ogre::CompositorPtr comp = Ogre::CompositorManager::getSingleton().create(
	"blum", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
	);
{
	Ogre::CompositionTechnique *t = comp->createTechnique();
	{
		Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt0");
		def->width = vp->getActualWidth();
		def->height = vp->getActualHeight();
		def->formatList.push_back(Ogre::PF_R8G8B8);
	}
	{
		Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt1");
		def->width = vp->getActualWidth();
		def->height = vp->getActualHeight();
		def->formatList.push_back(Ogre::PF_R8G8B8);
	}
	{
		Ogre::CompositionTargetPass *tp = t->createTargetPass();
		tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
		tp->setOutputName("rt0");
		Ogre::CompositionPass *pass = tp->createPass();
		pass->setType(Ogre::CompositionPass::PT_CLEAR);
		Ogre::CompositionPass *passtwo = tp->createPass();
		passtwo->setType(Ogre::CompositionPass::PT_RENDERSCENE);
	}
	{
		Ogre::CompositionTargetPass *tp = t->createTargetPass();
		tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
		tp->setOutputName("rt1");
		Ogre::CompositionPass *pass = tp->createPass();
		pass->setType(Ogre::CompositionPass::PT_CLEAR);
		Ogre::CompositionPass *passtwo = tp->createPass();
		passtwo->setType(Ogre::CompositionPass::PT_RENDERSCENE);
	}
	{
		Ogre::CompositionTargetPass *tp = t->getOutputTargetPass();
		tp->setInputMode(Ogre::CompositionTargetPass::IM_PREVIOUS);
		{ 
			Ogre::CompositionPass *pass = tp->createPass();
			pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
			pass->setMaterialName(materialName);
			pass->setInput(0, "rt0");
			pass->setInput(1, "rt1");
		}
	}
}
Ogre::CompositorInstance* mCompositorInstance = CompositorManager::getSingleton().addCompositor(mCamera->getViewport(), "blum");
mCompositorInstance->setEnabled(true);
Ogre::RenderTarget* targetLeft = mCompositorInstance->getRenderTarget("rt0");
Ogre::Viewport* outLeft = targetLeft->getViewport(0);
MyRenderTargetListener* mrtl = new MyRenderTargetListener();
mrtl->init(this,outLeft,true);
targetLeft->addListener(mrtl);
Ogre::RenderTarget* targetRight = mCompositorInstance->getRenderTarget("rt1");
Ogre::Viewport* outRight = targetRight->getViewport(0);
MyRenderTargetListener* mrtr = new MyRenderTargetListener();
mrtr->init(this,outRight,false);
targetRight->addListener(mrtr);

Re: Android Compositor Rendertarget listener not called

Posted: Wed Jan 08, 2014 3:33 am
by RigoCL
Great to know it has a solution, tricky though...

I have integrated the same Stereo code into my project, and was able to compile and run Ogre for Android (with your help btw). Now I'll give it a try to Stereo in Android.