GE Patch by Hamed Zaghaghi - Adding Motion Blur to the Game Engine.
authorMal Duffin <malachyduffin@gmail.com>
Sat, 29 Sep 2007 18:51:01 +0000 (18:51 +0000)
committerMal Duffin <malachyduffin@gmail.com>
Sat, 29 Sep 2007 18:51:01 +0000 (18:51 +0000)
I reviewed the code, suggested an update ( initialising accumulation buffer ), and tested the resulting update successfully.

It's great to see more GE developers!GE Patch by Hamed Zaghaghi to add motion blur to the GE ( using the accumulation buffer ).

I reviewed code and tested, gave some feedback ( initialising accumulation buffer ) which was implemented straight away, and re-reviewed.

It's great to have another GE coder on the team!

source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
source/gameengine/GamePlayer/common/GPC_RenderTools.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_IRenderTools.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h

index caf3d120fab1327f1fcb759382fd2eb3fe3fbe13..463f06869d6c64dfd84d4c8b6f15c498d1545544 100644 (file)
@@ -452,4 +452,27 @@ RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial(
        return NULL;
 }
 
+void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
+{
+       int state = rasterizer->GetMotionBlurState();
+       float motionblurvalue;
+       if(state)
+       {
+               motionblurvalue = rasterizer->GetMotionBlurValue();
+               if(state==1)
+               {
+                       //bugfix:load color buffer into accum buffer for the first time(state=1)
+                       glAccum(GL_LOAD, 1.0);
+                       rasterizer->SetMotionBlurState(2);
+               }
+               else if(motionblurvalue>=0.0 && motionblurvalue<=1.0)
+               {
+                       glAccum(GL_MULT, motionblurvalue);
+                       glAccum(GL_ACCUM, 1-motionblurvalue);
+                       glAccum(GL_RETURN, 1.0);
+                       glFlush();
+               }
+       }
+}
+
 unsigned int KX_BlenderRenderTools::m_numgllights;
index dc638d1a43a44fb15c536597f7cf42f8dfb830cd..a79302a283eeda82b0e982fceabcb8ed26c2a282 100644 (file)
@@ -100,7 +100,10 @@ public:
                                                                        void* tface);
        
        bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+
+       virtual void MotionBlur(RAS_IRasterizer* rasterizer);
 };
 
 #endif //__KX_BLENDERRENDERTOOLS
 
+
index 0f6bec30437f206201e4bb16914f36e269536e46..cc5c392d51a5064800d8c91c0d6bf6dd70709907 100644 (file)
@@ -570,4 +570,27 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
        }
 }
 
+void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
+{
+       int state = rasterizer->GetMotionBlurState();
+       float motionblurvalue;
+       if(state)
+       {
+               motionblurvalue = rasterizer->GetMotionBlurValue();
+               if(state==1)
+               {
+                       //bugfix:load color buffer into accum buffer for the first time(state=1)
+                       glAccum(GL_LOAD, 1.0);
+                       rasterizer->SetMotionBlurState(2);
+               }
+               else if(motionblurvalue>=0.0 && motionblurvalue<=1.0)
+               {
+                       glAccum(GL_MULT, motionblurvalue);
+                       glAccum(GL_ACCUM, 1-motionblurvalue);
+                       glAccum(GL_RETURN, 1.0);
+                       glFlush();
+               }
+       }
+}
+
 unsigned int GPC_RenderTools::m_numgllights;
index b7f73df3c3477d1ad1eec2b3fb16aebf1999c769..e1f2a869c22d3e3ae4a2fa42b5c28a4b10a62133 100644 (file)
@@ -149,6 +149,8 @@ public:
        int applyLights(int objectlayer);
 
        bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+
+       virtual void MotionBlur(RAS_IRasterizer* rasterizer);
 protected:
        /** 
         * Copied from KX_BlenderGL.cpp in KX_blenderhook
@@ -173,3 +175,4 @@ protected:
 
 #endif  // __GPC_RENDERTOOLS_H
 
+
index e76e28bcb7b98baf342cfaefc389374231c9f483..f8826245aab55644c7643bacd686e859ce640905 100644 (file)
@@ -966,6 +966,9 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
        scene->CalculateVisibleMeshes(m_rasterizer,cam);
 
        scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
+
+       m_rendertools->MotionBlur(m_rasterizer);
+
 }
 
 
@@ -1463,3 +1466,4 @@ void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
        b = m_overrideFrameColorB;
 }
 
+
index 7a937d5e3492088f97f5c449e7bb497a79681887..1a3a0490d218702c74061362ed511ef4ab4a1326 100644 (file)
@@ -618,7 +618,31 @@ static PyObject* gPyMakeScreenshot(PyObject*,
        Py_Return;
 }
 
+static PyObject* gPyEnableMotionBlur(PyObject*,
+                                                                       PyObject* args,
+                                                                       PyObject*)
+{
+       float motionblurvalue;
+       if (PyArg_ParseTuple(args,"f",&motionblurvalue))
+       {
+               if(gp_Rasterizer)
+               {
+                       gp_Rasterizer->EnableMotionBlur(motionblurvalue);
+               }
+       }
+       Py_Return;
+}
 
+static PyObject* gPyDisableMotionBlur(PyObject*,
+                                                                       PyObject* args,
+                                                                       PyObject*)
+{
+       if(gp_Rasterizer)
+       {
+               gp_Rasterizer->DisableMotionBlur();
+       }
+       Py_Return;
+}
 
 STR_String     gPyGetWindowHeight__doc__="getWindowHeight doc";
 STR_String     gPyGetWindowWidth__doc__="getWindowWidth doc";
@@ -645,6 +669,9 @@ static struct PyMethodDef rasterizer_methods[] = {
  {"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"},
   {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"},
   {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"},
+  {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"},
+  {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_VARARGS,"disable motion blur"},
+
   
   {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"},
   {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"},
index 8ecc9e7ad059859351edd117ff887f29ae39f090..560c6741260355b64b35d2578f8c120b2c82d25f 100644 (file)
@@ -48,7 +48,6 @@ class RAS_IPolyMaterial;
  */
 class RAS_IRasterizer
 {
-
 public:
 
        RAS_IRasterizer(RAS_ICanvas* canv){};
@@ -398,7 +397,15 @@ public:
 
        virtual bool    QueryLists(){return false;}
        virtual bool    QueryArrays(){return false;}
+       
+       virtual void    EnableMotionBlur(float motionblurvalue)=0;
+       virtual void    DisableMotionBlur()=0;
+       
+       virtual float   GetMotionBlurValue()=0;
+       virtual int     GetMotionBlurState()=0;
+       virtual void SetMotionBlurState(int newstate)=0;
 };
 
 #endif //__RAS_IRASTERIZER
 
+
index fa3c777553d5b3647c82548dbd18ed49292dad78..114783b9a47a9908e5aaaf425f0e72f29429bbc2 100644 (file)
@@ -174,6 +174,10 @@ public:
                struct RAS_LightObject* lightobject
        );
 
+       virtual
+               void
+       MotionBlur(RAS_IRasterizer* rasterizer)=0;
+
        virtual 
                class RAS_IPolyMaterial*        
        CreateBlenderPolyMaterial(
@@ -195,3 +199,4 @@ public:
 
 #endif //__RAS_IRENDERTOOLS
 
+
index 53ec7a02e6f79043196c9407b96ab5ca983265b0..85250fcd552d8033a188f926b010e23320a0a4a4 100644 (file)
@@ -82,7 +82,9 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
        m_setfocallength(false),
        m_noOfScanlines(32),
        m_useTang(false),
-       m_materialCachingInfo(0)
+       m_materialCachingInfo(0),
+       m_motionblur(0),
+       m_motionblurvalue(-1.0)
 {
        m_viewmatrix.Identity();
        
@@ -1979,3 +1981,15 @@ void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
        else
                glDisable(mode);
 }
+
+void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
+{
+       m_motionblur = 1;
+       m_motionblurvalue = motionblurvalue;
+}
+
+void RAS_OpenGLRasterizer::DisableMotionBlur()
+{
+       m_motionblur = 0;
+       m_motionblurvalue = -1.0;
+}
index d95ced658cedab9b58a1348093d47bd9afe9848c..6728905aa577bbec993c80e7f473587d3a83fa69 100644 (file)
@@ -91,6 +91,10 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
        int                             m_noOfScanlines;
        bool                    InterlacedStereo() const;
 
+       //motion blur
+       int     m_motionblur;
+       float   m_motionblurvalue;
+
 protected:
        int                             m_drawingmode;
        TexCoGen                m_texco[RAS_MAX];
@@ -293,8 +297,22 @@ public:
                                        const RAS_TexVert& v2,
                                        const RAS_TexVert& v3,
                                        const MT_Vector3 &no);
-
+       
+       virtual void    EnableMotionBlur(float motionblurvalue);
+       virtual void    DisableMotionBlur();
+       virtual float   GetMotionBlurValue(){return m_motionblurvalue;};
+       virtual int     GetMotionBlurState(){return m_motionblur;};
+       virtual void SetMotionBlurState(int newstate)
+       {
+               if(newstate<0) 
+                       m_motionblur = 0;
+               else if(newstate>2)
+                       m_motionblur = 2;
+               else 
+                       m_motionblur = newstate;
+       };
 };
 
 #endif //__RAS_OPENGLRASTERIZER
 
+