Page 1 of 3

(c++/OpenGL) Motionblur

Posted: Fri Apr 27, 2007 9:09 pm
by TheGameMaker
Hi,
I created some special effect nodes, and I want to make a little gift to you. So here it is: my Motionblur sceneNode!
It´s free, it´s simple it´s fast^^
some screens first(a pic says more than thousand words.. ya know)
Image
Image
Image

Its true Imagebased Motionblur, so its very fast.
It just blend the currend rendered image with the las few. (with just one 3Rendertargets!! so ther is NOT created a img for echa frame!!)
it has little effect on framerate (the testlevel normaly runs with about 180 FPS, with the MB applied at 130 at 1024x768)...
Its simple.. just do following:

Code: Select all


#include "PostProcessmotionblur.h"
// include the file(just like you named it^^)
    IPostProcessMotionBlur *MotionBlur = new IPostProcessMotionBlur(smgr->getRootSceneNode(), smgr, 666);
//create the node.. just somewhere in the code...

    MotionBlur->initiate(1024,512,0.85,smgr); //this sets the params: 
//(screenW,screenH,strength,smgr*) while screenW&H have to be the next llower power of two to the screensize.. strength should lay between 0.8&0.9.. just try it^^ 

	while(device->run()) 
	if (device->isWindowActive())
	{
	driver->beginScene(true, true, 0); //and change the renderloop
        MotionBlur->render();          //
	driver->setRenderTarget(0);// in fact this is the code that does the MB
	MotionBlur->renderFinal();   // pretty simple, you see??


		env->drawAll(); //and all the other blabla in the mainloop
	driver->endScene();

	}
and now the source that belongs into PostProcessMotionBlur.h



Code: Select all

#ifndef __POST_PROCESS_EFFECT_MOTION_BLUR__
#define __POST_PROCESS_EFFECT_MOTION_BLUR__
#include "irrlicht.h"


using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;



class PPE_MotionBlur_callback: public video::IShaderConstantSetCallBack
{
public:
    float strength;
  virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  {
    video::IVideoDriver* driver = services->getVideoDriver();
    services->setVertexShaderConstant("strength", reinterpret_cast<f32*>(&strength),1);
    int var0=0;
    services->setPixelShaderConstant("texture1", (float*)(&var0), 1);
    int var1=1;
    services->setPixelShaderConstant("texture2", (float*)(&var1), 1);
	}
};




class IPostProcessMotionBlur : public scene::ISceneNode
{

public:
   core::aabbox3d<f32> Box;
   video::S3DVertex Vertices[6];//the vertices for the onscreenquad
   video::SMaterial Material;//the material used with shader
   video::SMaterial Accum;//a simple diffuse material..
   video::ITexture* next; //the rendertarget
   video::ITexture* prev; //the rendertarget
   video::ITexture* accum; //the rendertarget
   int mat;
   PPE_MotionBlur_callback* callback;

      IPostProcessMotionBlur(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id): scene::ISceneNode(parent, mgr, id)
        {
      Vertices[0] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 1.0f);
      Vertices[1] = video::S3DVertex(-1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 0.0f);
      Vertices[2] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 0.0f);
      Vertices[3] = video::S3DVertex( 1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 1.0f);
      Vertices[4] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 0.0f, 1.0f);
      Vertices[5] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,0,255,255), 1.0f, 0.0f);
        }


    void initiate(unsigned int sizeW,unsigned int sizeH,float strength,scene::ISceneManager* smgr)
   {
static stringc vertShader =
"varying vec2 vTexCoord;"
"void main(void)"
"{"
  " vec2 Position;"
  " Position.xy = sign(gl_Vertex.xy);"
  " gl_Position = vec4(Position.xy, 0.0, 1.0);"
   "vTexCoord =Position.xy *.5 + .5;"
"}";

static stringc fragShader =
"uniform sampler2D texture1;"
"uniform sampler2D texture2;"
"varying vec2 vTexCoord;"
"uniform float strength;"
"void main()"
"{"
"  gl_FragColor = mix( texture2D( texture1, vTexCoord ), texture2D( texture2, vTexCoord ), vec4( strength,strength,strength,strength) );"
"}";


static stringc fragShader2 =
"uniform sampler2D texture1;"
"varying vec2 vTexCoord;"
"void main()"
"{"
"  gl_FragColor =texture2D( texture1, vTexCoord );"
"}";


video::IVideoDriver* driver = smgr->getVideoDriver();
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();

      callback= new PPE_MotionBlur_callback();
      callback->strength=strength;

      Material.MaterialType=(E_MATERIAL_TYPE)gpu->addHighLevelShaderMaterial
        (
               vertShader.c_str(), "main", video::EVST_VS_1_1,
               fragShader.c_str(), "main", video::EPST_PS_1_1,
               callback, (video::EMT_SOLID)
        );
     Accum.MaterialType=(E_MATERIAL_TYPE)gpu->addHighLevelShaderMaterial
        (
               vertShader.c_str(), "main", video::EVST_VS_1_1,
               fragShader2.c_str(), "main", video::EPST_PS_1_1,
               NULL, (video::EMT_SOLID)
        );
      next = driver->createRenderTargetTexture(core::dimension2d<s32>(sizeW,sizeH));
      prev = driver->createRenderTargetTexture(core::dimension2d<s32>(sizeW,sizeH));
      accum = driver->createRenderTargetTexture(core::dimension2d<s32>(sizeW,sizeH));

      Material.Wireframe = false;
      Material.Lighting = false;
      Material.Textures[0]=next;
      Material.Textures[1]=prev;


      Accum.Wireframe = false;
      Accum.Lighting = false;
      Accum.Textures[0]=accum;
    }




   virtual void OnPreRender(){}

   virtual void render() 
   {
      u16 indices[] = {0,1,2,3,4,5};
      video::IVideoDriver* driver = SceneManager->getVideoDriver();             //Fills Next
      driver->setRenderTarget(next, true, true, video::SColor(0,0,0,0));
	  SceneManager->drawAll();
	  
	  driver->setRenderTarget(accum, true, true, video::SColor(0,0,0,0));     //Combine Next&prev in accum   
      driver->setMaterial(Material);
      driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
      driver->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2);
      
      driver->setRenderTarget(prev, true, true, video::SColor(0,0,0,0));        //Write back accum into prev
      driver->setMaterial(Accum);
      driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
      driver->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2);
   }
   
   virtual void renderFinal() 
   {
      video::IVideoDriver* driver = SceneManager->getVideoDriver();
      u16 indices[] = {0,1,2,3,4,5};
      driver->setMaterial(Accum);
      driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
      driver->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2);
   }


  virtual u32 getMaterialCount(){return 1;}
  virtual video::SMaterial& getMaterial(s32 i){return (Material);}
  virtual const core::aabbox3d<f32>& getBoundingBox() const{return Box;}
};
#endif
sry.. i work with DevC++ so no DX, onl GLSL..
hope you like it!
greetz TGM

Posted: Sat Apr 28, 2007 5:55 am
by jingquan
Oh, great effect. But do you have any idea how to do that in .NET?

Posted: Sat Apr 28, 2007 6:20 am
by BlindSide
I doubt its much diffrent from replacing all the -> with . :lol:

Great work, will try this out sometime. What do you mean by just one 3 rendertargers? Which is it one or 3 :P

PS: Nice to see it is PS1.1 yay

Posted: Sat Apr 28, 2007 8:46 am
by roxaz
good idea about motion blur. effect looks nice :)

Posted: Sat Apr 28, 2007 9:09 am
by Virion
Nice, keep it up! :D

Posted: Tue May 01, 2007 9:31 am
by Steel Style
You missed a #endif on your file.H, but Great Work!

Posted: Tue May 01, 2007 12:34 pm
by sio2
roxaz wrote:good idea about motion blur. effect looks nice :)
Yes, good idea. Probably didn't get the idea from my own motion blur demo at all. :wink:

Posted: Tue May 01, 2007 1:57 pm
by TheGameMaker
ok.. endif issue fixed..
Yes, good idea. Probably didn't get t ... all. Wink
well, its not my idea at all, i got an idea that should worke like this, but neer actualy did.. then I saw the ATI Rendermonkey Motionblur example, that worked more or less like I thought. Well.. a little later I got Motionblur^^

Posted: Mon May 21, 2007 3:53 pm
by m_krzywy
have that error just including teh file...

323 Z:\irrlicht-1.2\include\ISceneNode.h overriding `virtual irr::s32 irr::scene::ISceneNode::getMaterialCount()'

Irrlicht 1.2, Dev C++

edit:

I //virtual u32 getMaterialCount(){return 1;} that line and it's workin but i dono if effect is the same ;)

Posted: Mon May 21, 2007 4:46 pm
by Ico
Don't comment it out. Just change the "u32" to "s32" (or other way around? Not sure atm... damn ;) ) in the file you got from this thread.

Posted: Mon May 21, 2007 5:43 pm
by LLDD
Ico wrote:Don't comment it out. Just change the "u32" to "s32" (or other way around? Not sure atm... damn ;) ) in the file you got from this thread.
I had to change it to s32 and it works fine now. Good job TheGameMaker :)
________
Teen Health Forums

Posted: Mon May 21, 2007 11:30 pm
by RhavoX
With dev-cpp u can also do dx apps so if someone would point you in the right direction would u try to do that in dx? :P

Posted: Tue May 22, 2007 1:04 pm
by TheGameMaker
no need for that... someone else already converted it for DX..
http://irrlicht.sourceforge.net/phpBB2/ ... c&start=15
thx to belfegor for his amount of time&work he spent on doing this!
besides I would be interested in a tutorial for using dx with DevC++, since its a problem many new users have.
(I personaly don´t like DX, nor do I want to develop Apps using it, since its more work to get them working on Linux)

Posted: Sat Aug 25, 2007 11:35 pm
by Yarcanox
is GLSL version 1.3 good enough for this? I got a geforce 4 and using opengl I get "GLSL shader failed to compile"!

Posted: Tue Aug 28, 2007 3:53 pm
by TheGameMaker
tbh I´m not shure if shader 1.3 is enought.. I only tested in on shader 2.0 systems.. sry (But I think this should be your problem indeed) :|