physical motion blur in a procedural shader



  • On 25/05/2015 at 07:48, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   16 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    I have a problem with my procedural shader when rendering with the physical renderer with motion blur enabled. The problem being that i don't get the "correct" result/the result i am expecting.

    The shader uses the vertices from rayobject->padr and the surface point cd->vd->p to determine the output. After debugging i noticed that the positions of the vertices don't change during rendering a single frame, while the motion blur time offset cd->vd->mb_offset does. So essentialy i'm using incorrect vertex positions and that causes the wrong result.

    The api has various things dealing with motion blur like vd->CalcMotionObjectMatrixInv, vd->SetPhysicalRayTime but i haven't been able to figure out how to use these to get the correct result.

    Can someone point me in the right direction?



  • On 26/05/2015 at 11:25, xxxxxxxx wrote:

    Hi,

    please bare with me, as this topic touches areas of C4D I have not yet had the time to explore in depth.

    There is one thing, though, I can say: Physical Renderer does not support "in texture" motion blur. You can check with a simple black/white gradient or a noise shader.

    A few questions:
    Is the result with Standard Renderer and Sub-Frame Motion Blur correct?
    In what way is the result with Physical Renderer wrong? Is it simply static?

    Don't get me wrong, I'm not (yet) saying, this is impossible. I will still need to find out, how a moving mesh is handled in Physical Renderer and how this relates to shaders.



  • On 26/05/2015 at 16:58, xxxxxxxx wrote:

    Hi, thnx for the reply.
    I've made some renders that show the problem.

    The object is a simple (quad) polygon moving from left to right and rotating clockwise.

    Case 4 clearly shows the problem. I assumed that cd->vd->p will always lie inside the raypolygon obtained with rayhitid->GetPolygon(), but that assumption does not hold when motion blur is enabled in the physical renderer. In essence, the polygon vertices aren't transformed to deal with subframe motion during motion blur.

    Case 5 shows a box gradient using UV's giving the correct result, but the 3d gradients (case 6) suffer from the same problem i face.

    When trying to transform the vertices and/or p, i found that the matrix returned from  CalcMotionObjectMatrixInv() is the only one that actually changes sub-frame (depending on mb_offset?). I tried transforming the vertices and/or p but couldn't get the correct results (haven't got a clue how CalcMotionObjectMatrixInv() is supposed to be used though).

    Hopefully this makes it a bit clearer.



  • On 26/05/2015 at 22:52, xxxxxxxx wrote:

    Hi,

    before I dig deeper (I will) : In case 5 the gradient itself is not animated, right?



  • On 27/05/2015 at 02:51, xxxxxxxx wrote:

    no, the gradient is not animated.
    I've tried a couple more builtin shaders and found that the UV based ones all work. So noises set to UV 2D space work correctly, all the surfaces shaders (checkerboard etc) work correctly, gradients using one of the 2D modes work, etc.



  • On 27/05/2015 at 06:22, xxxxxxxx wrote:

    CalcMotionObjectMatrixInv() can be used to compensate for Motion Blur like so:

    vSurfIntersect = static_cast<Vector>(cd->vd->CalcMotionObjectMatrixInv(cd->vd->op) * cd->vd->p);
    

    Unfortunately, I'm not sure, this will solve your problems in all situations.



  • On 27/05/2015 at 07:10, xxxxxxxx wrote:

    That's actually one of the first things i tried, unfortunately it still gives the wrong results. Using CalcMotionObjectMatrixInv() in that way also results in wrong renders when motion blur is off.



  • On 27/05/2015 at 20:18, xxxxxxxx wrote:

    Ok, i've analyzed the returned matrix when debugging and have found something that works in in some cases. I used the following code:

      
    Matrix64 invm = cd->vd->CalcMotionObjectMatrixInv(rayObj) * rayObj->mg;  
    Vector surfp = invm * cd->vd->p;  
    

    With this code i get great results with moving objects. Unfortunately rotating objects don't work as expected, but they still look somewhat better than without the above transformation (unless they're rotating super fast).

    It would be nice to also get nice results with rotating objects, but i don't know if this is a limitation of the motion blur implementation in the physical renderer.



  • On 28/05/2015 at 02:42, xxxxxxxx wrote:

    Did you try to increase the Motion Subdivisions parameter in Render Settings? Do the results for rotation improve with values > 4?



  • On 28/05/2015 at 09:40, xxxxxxxx wrote:

    Sadly, increasing the motion subdivisions does not improve the results during rotations.

    If i add a test to determine if p is inside the raypolygon, it shows that during rotation p is often outside the raypolygon and thus giving weird results because the raypolygon from the rayhit is not the correct one. I could handle this by tracing a new ray to determine the correct raypolygon but that would slow down the shader substantially.

    Come to think of it this problem might be the result of a huge optimization in the motion blur implementation because you don't need to transform the complete object to sub-frame positions and you don't need to trace new rays. And for shaders that can sample any point in space (such as noise) this wouldn't be a problem because it just doesn't show any motion blur from rotation.

    Anyway, without knowing the specifics of the motion blur implementation in the physical renderer i'll leave it as it is.


Log in to reply