Localized Motion Blur

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Localized Motion Blur

Post by dark_sylinc »

Hi!
People here have been very busy lately due to the inminent Shoggoth release.
It's been a long time. And I still don't work on the SSS filter. Ok. My fault.

Anyway I came out with something cooler: Localized Motion Blur.
Before you ask, this is NOT Pixel Motion Blur.

It is based upon the old ping-pong technique used in Motion Blur, and it inherits most of it's pros and cons. But it is different:
Existing Motion Blur in OGRE whether blurs the entire screen or does nothing. And pixel motion blur is expensive, and harder to understand.
Instead, this filter only works on specific objects, not on the entire frame buffer. With separate parameters for each object with different blur factors

This filter is a post process effect, which can selectively blur per object. You specify a blur factor for each object to a material override (which is made easy thanks to OGRE material templates)

Each object in the scene can have it's own factor. Yes you read it correct. And every material hat has not been enabled for this kind of motion blur will not be blurred.

Pros:
*Each object has it's own blur factor
*With additional C++ coding, you can gather the object's velocity and set the blur factor accordingly (works per object, not per pixel though)
*It's fast
*Insanely easy to integrate to your game

Cons:
*Blurriness still depends on frame-rate. You can try this formula though
*Needs to draw the whole scene twice

A blur factor = 1 means full blur. Also such high value will cause glitches due to the ping-pong nature. Use 0.9
A bluf factor = 0 means no blur at all

Those who analize the algorithm will find out that it's actually pretty simple. And if you make use of MRTs, you don't need to draw the whole scene twice at all. Plus, the Z buffer optimizations could help a lot too.
I haven't coded an MRT version because it was harder (I was trying Eihort, didn't know Shoggoth was much more flexible), and I would lose the great flexibility I have now. Plus, the developer would requiere much more effort to implement it, as it would requiere to customize it's own pixel shaders. The solution is simple: those who want MRTs, need to write it themselves.

Now the pics, note that each object has it's own blur factor. And the head + the barrel are not blurred:
Image
Image
Image
Image

Pictures show a bit of it. It's much better seeing it in action. Binary download will be up soon.

Edit:
Patch here

Edit2:
Binary demo here!!!

Edit3:
Stand-alone source code here (instead of a patch)

Just apply to the main SVN folder. It will update sollution files and create the new ones.

PS: If people like this filter, further optimizations could integrate it into the OGRE core and make it easier for developers, as just defining "blurFactor xx" in the material ought to be enough. Everything else can be handled automatically.
Last edited by dark_sylinc on Wed Sep 03, 2008 3:59 am, edited 4 times in total.
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

Looks good, I have been looking at pixel motion blur myself but I'm not too hot with these things.

One thing I dislike about motion blur effects though is that they just duplicate perfectly clear images that fade out, which sort of makes you feel sick to look at it. How easy would it be to actually blur the residual images?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

Captain_Deathbeard wrote:One thing I dislike about motion blur effects though is that they just duplicate perfectly clear images that fade out, which sort of makes you feel sick to look at it. How easy would it be to actually blur the residual images?
May be I can try something like that. But it wouldn't be perfect.
In my opinion though, when blurred, there wouldn't be a perfectly clear image because we're moving (Try moving your head quickly, are you able to see a sharp image? Try looking at a very fast train, are you able to see it sharp? But if you do, I'm pretty sure you actually don't even see it blur). However, games tend to exaggerate the ammount of blur which makes us fell sick (not to mention most of them apply it to the whole scene). Seeing the ninja model proves that motion blur cannot make you sick when properly handed (it has the less ammount of blur from all 5)
And the blur factor can be reduced even more, therefore the game can have a touch of motion blur, without overdoing it.
Mid-to-high blur factors should be used when rotating the camera very fast or in characters with superman-like speed.

Cheers
Dark Sylinc

PS: While I'm writting this reply, I was coincidentally looking at your "Kenshi" post. Pretty awesome. I think a small blur factor would make it look great.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

I forgot to tell the specs:
*Shader was written in Cg
*PS 2.0 is requiered
*VS 1.1 is requiered
dudeabot
Gnome
Posts: 334
Joined: Thu Jun 28, 2007 2:12 pm
Location: Brazil
x 5

Post by dudeabot »

really nice effect!

but could you post the source as a project, or separated files?
User avatar
Game_Ender
Ogre Magi
Posts: 1269
Joined: Wed May 25, 2005 2:31 am
Location: Rockville, MD, USA

Post by Game_Ender »

The screenshots look really cool. I was wondering why you had to patch the core to implement this feature?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

Game_Ender wrote:The screenshots look really cool. I was wondering why you had to patch the core to implement this feature?
I didn't. The patch adds files under the "Samples" folder.
This is for convenience for the OGRE mantainers, so they can quickly integrate the sample to the project.
but could you post the source as a project, or separated files?
OK, now 2 people asking for the same thing. I will upload the source as a separate zip shortly.

Thanks for the feedback!
Dark Sylinc
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

Firstly, your effect is awesome:

Image

But I cannot reduce it enough. The screenshot above is with the blurFactor param set to 0, and it is still that blurry. I would have thought that setting it to 0 should result in no blur at all. Am I missing a setting somewhere?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

Captain_Deathbeard wrote:Firstly, your effect is awesome:
That pic look really cool. Good to see it in action.
Captain_Deathbeard wrote: But I cannot reduce it enough. The screenshot above is with the blurFactor param set to 0, and it is still that blurry. I would have thought that setting it to 0 should result in no blur at all. Am I missing a setting somewhere?
That's pretty strange. You're guessing right. blurFactor = 0 means no blur at all. Furthermore, usually blur<0.6 shows very little blur.
Can I see the material's code? (You can PM if you don't want to make it public)
Mostly sure the blurFactor variable isn't being overriden.
The key code is the following, and should look really similar:

Code: Select all

vertex_program LocalizedMotionBlur/AllWhite_VP cg
{
	source LocalizedMotionBlur.cg
	entry_point main_white_vp
	profiles vs_1_1 arbvp1
	default_params
	{
		param_named_auto worldViewProj worldviewproj_matrix
		param_named blurFactor float 0.65
	}
}

material Ogre/LocalizedMotionBlur/LMB_Template
{
	technique
	{
	}
	
	technique MotionBlurLocalizedVP
	{
		scheme LMB_White
		pass
		{
			lighting off
			depth_write on

			vertex_program_ref LocalizedMotionBlur/AllWhite_VP
			{
			}
		}
	}
}

material LMBlur/SampleTest03 : Ogre/LocalizedMotionBlur/LMB_Template
{
	technique
	{
//Do whatever you want here
		pass
		{
			ambient 0.7 0.7 0.7
			diffuse 1 1 1

			texture_unit
			{
				texture Dirt01.jpg
			}
		}
	}
	
	//Override some paramters (MUST BE AFTER main technique)
	technique MotionBlurLocalizedVP
	{
		pass 0
		{
			vertex_program_ref LocalizedMotionBlur/AllWhite_VP
			{
				param_named blurFactor float 0 //Override
			}
		}
	}
}

IN THAT ORDER.

PS: Just to be sure, OpenGL or Direct3D plugin? What GPU do you have?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

Mmmm... I'm taking a look at the pic again.
And there's something I noticed: The human on the left is very slightly blurred. (Look it's right leg)
If it doesn't have the blur material template, check the C++ code (the Listeners)
If it does have it, then it can be that you're lowering the blurFactor from the wrong object.

If you're changing the blurFactor from C++; it is possible that you're somehow not telling OGRE to update the parameters to the shaders. Sometimes this may happen, depending on how's the material setup.

Or else.... this blurry leg may actually be just some JPEG artifact.

I'll be waiting for your reply
Dark Sylinc
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

The character on the left is almost stationary and stepping back with the right leg, that is why it is blurred less and the leg blurs. They both blur the same. All characters have same material, but cloned from original.

I am just setting blurFactor to 0 in the material for now, tried setting in code too, and not, so it should definately be set to 0. If i set to something like 0.9 its really ridiculously high.

using Direct3D (latest directX), newest shoggoth, Geforce 7800. Framerate is about 130.

material is like so:

Code: Select all

material human/HWSkinned
{
	technique main
	{
		pass SinglePass
		{
			vertex_program_ref HWSkin_VP
			{
			}
			fragment_program_ref HWSkin_FP
			{
			}
						
			texture_unit base_map
			{
				texture_alias base_map
				texture hu-mau6-body.png
				filtering linear linear linear
				tex_address_mode border
			}
			texture_unit base_normal			//alpha channel is specular
			{
				texture_alias bump_map
				texture hu-f-body_n.tga
				filtering linear linear linear
				tex_address_mode border
			}
		}
	}
	
	technique MotionBlurLocalizedVP
	{
		scheme LMB_White
		pass
		{
			lighting off
			depth_write on

			vertex_program_ref LocalizedMotionBlur/AllWhite_VP
			{
				param_named blurFactor float 0
			}
		}
	}
}

material human/characterSkin : human/HWSkinned
{
	technique main
	{
		pass SinglePass
		{
			
			fragment_program_ref CharacterSkin_FP
			{
			}
			
			texture_unit base_map {}
			texture_unit base_normal	{}
			
			texture_unit headbase_map
			{
///....blah
			}
///...more tex_units
		}
	}
}
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

I just tried totally removing the MotionBlurLocalizedVP technique, and it still blurs the same. Surely it shouldn't blur if I take that out?

Just realised its actually blurring everything in the scene, even terrain
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

Captain_Deathbeard wrote:I just tried totally removing the MotionBlurLocalizedVP technique, and it still blurs the same. Surely it shouldn't blur if I take that out?
If you take that out, it should be no more blur. However (see below):
Captain_Deathbeard wrote: Just realised its actually blurring everything in the scene, even terrain
I guess you're not implementing the C++ correctly (a Listener for the Compositor). If that went wrong, then the blur factor is based on the brightness of that pixel, which is usually garbage for that effect.
You're not using the *.compositor file, aren't you?

To make the C++ part work properly (in this order):
1) Copy the code in the function "createCompositors()" and call it upon initialization. That will create the compositor
2) Enable the compositor
3) Copy the Listener's code, and add it this way:

Code: Select all

//Add a RenderTargetListener for rtWeights (so we can draw as black all other objects)
CompositorChain *cc = CompositorManager::getSingleton().getCompositorChain( mWindow->getViewport(0) );
CompositorChain::InstanceIterator itor = cc->getCompositors( );
while( itor.hasMoreElements() )
{
	CompositorInstance *ci = itor.getNext();
	if( ci->getCompositor()->getName() == "LocalizedMotionBlur" )
	{
		String texName = ci->getTextureInstanceName( "rtWeights", 0 );
		static_cast<TexturePtr>(mRoot->getTextureManager()->getByName(texName))->getBuffer()->getRenderTarget()->addListener(this);
	}
}
Note I add "this" as a Listener because that class is also a Listener, you can use another class if you like.

This is the how the Listener class should look like:

Code: Select all

class LocalizedMotionBlur : Ogre::RenderQueue::RenderableListener, Ogre::RenderTargetListener
{
public:
	LocalizedMotionBlur() :
		Ogre::RenderQueue::RenderableListener()
	{
    }

    ~LocalizedMotionBlur() {  }

virtual void preViewportUpdate(const RenderTargetViewportEvent& evt)
	{ 
		if( evt.source->getMaterialScheme() == "LMB_White" ) 
		{ 
			// Add 'this' as a RenderableListener to replace the technique for all renderables 
			RenderQueue* queue = evt.source->getCamera()->getSceneManager()->getRenderQueue(); 
			queue->setRenderableListener(this);
		}
	}

	bool renderableQueued( Renderable* rend, uint8 groupID, ushort priority, Technique** ppTech, RenderQueue* pQueue ) 
	{ 
		if( (*ppTech)->getName() == "MotionBlurLocalizedVP" )
			return true;
		else
		{
			MaterialPtr mat = (MaterialPtr)MaterialManager::getSingletonPtr()->getByName( "Ogre/LocalizedMotionBlur/LMB_Template" );
			*ppTech = mat->getTechnique(1);
		}

		return true;
	}

	virtual void postViewportUpdate(const RenderTargetViewportEvent& evt)
	{ 
		if( evt.source->getMaterialScheme() == "LMB_White" ) 
		{ 
			// Reset the RenderableListener 
			RenderQueue* queue = evt.source->getCamera()->getSceneManager()->getRenderQueue(); 
			assert(queue->getRenderableListener()==this); // if this fires, something went wrong 
			queue->setRenderableListener(0);
		}
	}
This is all implemented in the demo. I posted a source-only code. Hope that helps you find all the code you need.

I'll be waiting your reply
Cheers
Dark Sylinc

PS: It may look hard, but it's actually a copy-paste thing
Last edited by dark_sylinc on Wed Sep 03, 2008 3:28 am, edited 1 time in total.
User avatar
leonardoaraujo.santos
Greenskin
Posts: 141
Joined: Fri Apr 27, 2007 6:00 pm
Location: Brazil

Post by leonardoaraujo.santos »

Hi dark_sylinc sorry for the lame question but could you show me how I can decompress the source/binary file that you send?

I've opened the files (bz2) and inside them it was an File without extension... I have to rename it?)

Image

PS: I've tried to apply this file (without extension) with Turtoise SVN but it complained that it was not a text file or something like this)
Last edited by leonardoaraujo.santos on Wed Sep 03, 2008 3:31 am, edited 1 time in total.
Image
Engineering tutorials (Robotics, Electronics, Software, Mechanics)
http://www.tutoriaisengenharia.com
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

leonardoaraujo.santos wrote:Hi dark_sylinc sorry for the lame question but could you show me how I can decompress the source/binary file that you send?

I've opened the files (bz2) and inside them it was an File without extension... I have to rename it?)
That FileFront truncated the filename! thanks for spotting the problem.
Rename the file OGRE_Localized_Motion_Bluc.bz2 to OGRE_Localized_Motion_Bluc.tar.bz2
I'm fixing it as we speak

Thanks!
Dark Sylinc

Edit: Fixed. Rename your copy or download it again
User avatar
leonardoaraujo.santos
Greenskin
Posts: 141
Joined: Fri Apr 27, 2007 6:00 pm
Location: Brazil

Post by leonardoaraujo.santos »

Thanks dark_sylinc I've rename it and its working fine... I will try to use in my game... As soon as I got it working I will post here
Image
Engineering tutorials (Robotics, Electronics, Software, Mechanics)
http://www.tutoriaisengenharia.com
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

As far as I can see, thats exactly what I'm doing. Its modded slightly though, its not derived from ExampleApplication, the constructor calls createScene() and createScene() does this:

Code: Select all

	void createScene(void)
	{
		createCompositors();
		createListener();

		//Add the LocalizedMotionBlur compositor and enable it
		CompositorManager::getSingleton().addCompositor(mWindow->getViewport(0), "LocalizedMotionBlur" );
		CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), "LocalizedMotionBlur", true);
	}
Aside from that its the same. I just "new" the class after I've done all my ogre initialisation.


. I filled the listener with breakpoints though, and createListener() function does get called but never reaches the middle code.

Its this line:

Code: Select all

CompositorChain *cc = CompositorManager::getSingleton().getCompositorChain( mWindow->getViewport(0) );
Its creating a new, empty compositor chain, so the iterator is empty. I have no idea why though.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Post by dark_sylinc »

leonardoaraujo.santos wrote: Thanks dark_sylinc I've rename it and its working fine... I will try to use in my game... As soon as I got it working I will post here
:) I am waiting to see it.

Code: Select all

...
createListener();
//Add the LocalizedMotionBlur compositor and enable it
CompositorManager::getSingleton().addCompositor(mWindow->getViewport(0), "LocalizedMotionBlur" );
CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), "LocalizedMotionBlur", true);
....
}
Wrong order. Call "createListener()" AFTER enabling the compositor. That's why the CompositorChain is returning an empty list. Everything else looks fine.

Hope this helps
Dark Sylinc

Edit: This is the right order:

Code: Select all

void createScene(void) 
   { 
      createCompositors(); 

      //Add the LocalizedMotionBlur compositor and enable it 
      CompositorManager::getSingleton().addCompositor(mWindow->getViewport(0), "LocalizedMotionBlur" ); 
      CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), "LocalizedMotionBlur", true); 

      createListener();  // <- Here
   }
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

Ah that was it, thanks for going out of your way to help me out.
Lord LoriK
Goblin
Posts: 254
Joined: Tue Feb 13, 2007 5:33 am

Post by Lord LoriK »

@Captain_Deathbeard: please post a new picture to see it properly working. Should be amazing to watch a battle with this effect enabled.
User avatar
leonardoaraujo.santos
Greenskin
Posts: 141
Joined: Fri Apr 27, 2007 6:00 pm
Location: Brazil

Post by leonardoaraujo.santos »

And also some code... that would be even nicer! hehehehe
Image
Engineering tutorials (Robotics, Electronics, Software, Mechanics)
http://www.tutoriaisengenharia.com
User avatar
Captain_Deathbeard
Gremlin
Posts: 179
Joined: Mon Nov 21, 2005 6:16 pm
Location: UK
x 7

Post by Captain_Deathbeard »

Took me a while to get looking good once it was working, but was mainly because I wasn't setting all objects equally.

This ones 0.6 at 140fps:
Image

This ones 0.6 at 40fps, not so pretty, thats why I think maybe a blur pass on top of it would make it a bit nicer:
Image
It will look better though once I add the time correction. I won't today though, because I just got Spore :lol:

Here is my code if it helps, its pretty much the same as dark_sylics, except you can just drop it in your project and go "new LocalisedMotionBlurListener(window);" and thats it activated (rather than picking out all the demo code and getting confused like I did). Theres also a function in there for setting the blurFactor.
http://www.lofigames.com/screens2/local ... ur_imp.cpp
User avatar
leonardoaraujo.santos
Greenskin
Posts: 141
Joined: Fri Apr 27, 2007 6:00 pm
Location: Brazil

Post by leonardoaraujo.santos »

Thanks Captain_Deathbeard that was nicer indeed :)
Image
Engineering tutorials (Robotics, Electronics, Software, Mechanics)
http://www.tutoriaisengenharia.com
User avatar
Xplodwild
Goblin
Posts: 231
Joined: Thu Feb 12, 2009 3:49 pm
Location: France
x 13

Re: Localized Motion Blur

Post by Xplodwild »

Could someone please re-upload this? (Or is there any new per-object motion blur available somewhere?)
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5505
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1371

Re: Localized Motion Blur

Post by dark_sylinc »

Hi! I can't find the files in my Drive. Sorry. I must have backed it up in a DVD.

I still have the code in one of my projects, but it's most likely in an uncompilable state.

Anyway I would need to redo that little effect. It re-renders the scene to see which objects need Blur to be applied, which is very slow and not very scalable.
Today, the Depth Sharing system built in the compositor's core would make this effect to be much more usable.
That rewrite won't be happening soon I'm afraid.

Cheers
Dark Sylinc

PS. Try to dig the Shoggoth (1.6) version of Ogre, and apply the patch in SF.net. That will work.