Motion Vector pass for Spherical render

   6022   10   1
User Avatar
Member
22 posts
Joined: 6月 2006
Offline
In the past I've generally used a simple shader like the one in the pic attached, when it comes to render motion vectors, and it works pretty well with a regular camera.

I tried to use the same shader to generate a motion vector pass for a lat-long (spherical shader) render for a VR project, but it doesn't seem to work as expected. The vectors are there but the Vector Blur in Nuke doesn't produce the correct result. Not only the direction of blur is incorrect, but it doesn't seem to take into account the distance from the camera (far objects move slower than closer object, in camera space).

Is there anything anybody can think of that could help me on this ?


Edited by mrWolf - 2016年8月8日 23:25:09

Attachments:
Screenshot.jpg (110.8 KB)

Alessandro Pepe
http://www.alessandropepe.com [www.alessandropepe.com]
http://pepefx.blogspot.com [pepefx.blogspot.com]
User Avatar
Member
22 posts
Joined: 6月 2006
Offline
I did some more investigation and renders.
A simple hip file illustrating the issue I'm having is attached below.
The issue seems to be happening looking right and left in the lat-long render, which corresponds to the areas with sudden changes of color in the motion_vectors render below (and the consequent streaky artifacts in the vectorBlur generated by Nuke).

It feels like the vectors should be treated with some spherical mapping math. Did anybody run into this before ?



Attachments:
viewport.gif (4.5 MB)
motion_vectors.gif (990.2 KB)
nuke_render.gif (2.8 MB)
issue.png (12.0 KB)
apepe_fx_motionVectorTest_v003.hip (551.7 KB)

Alessandro Pepe
http://www.alessandropepe.com [www.alessandropepe.com]
http://pepefx.blogspot.com [pepefx.blogspot.com]
User Avatar
Member
182 posts
Joined: 4月 2009
Offline
I think the culprit is the transform to NDC space. Usually when you convert P to NDC you get an even linear gradient for left/right top/bottom. Not so much with a spherical camera as it seems.
User Avatar
Member
178 posts
Joined: 1月 2013
Offline
Hi Alessandro!

Did you ever figure this one out?

-Jon
User Avatar
Member
22 posts
Joined: 6月 2006
Offline
jpparkeramnh
Hi Alessandro!

Did you ever figure this one out?

-Jon

hey Jon,
no , after a couple of days I gave up.
I wonder if the issue is still there in H16.
Did you find a solution by any chance ?
Alessandro Pepe
http://www.alessandropepe.com [www.alessandropepe.com]
http://pepefx.blogspot.com [pepefx.blogspot.com]
User Avatar
Member
7771 posts
Joined: 9月 2011
Offline
Try transforming your blur space into polar coordinates before computing the delta. The logic is the same as for standard motion vectors, transform shading space to screen space before computing the difference.

#include <math.h>
vector latlong( const vector pos ) {
vector tmp_p = set(pos.x,pos.z,-pos.y);
float r = length(tmp_p);
float phi = atan2(tmp_p.y,tmp_p.x);
float theta = acos(tmp_p.z/r);
return set(phi/M_TWO_PI,theta/M_PI,r);
}
surface
myshader( export vector motion = {0,0,0} )
{
vector p1 = getblurP(0);
vector p2 = getblurP(1);
vector res;
int found = renderstate("image:resolution",res);
if (!found) res = {1,1,1};
res.z = 1.0;
p1 = latlong(p1);
p2 = latlong(p2);
motion = p2 - p1;
motion *= res;
}
User Avatar
Member
178 posts
Joined: 1月 2013
Offline
jsmack,

Thanks! I was about 90 percent of the way towards exactly what you posted but never got a chance to test it. Still don't have time to test it… give it a whirl Alessandro!
User Avatar
Member
22 posts
Joined: 6月 2006
Offline
jsmack
Try transforming your blur space into polar coordinates before computing the delta. The logic is the same as for standard motion vectors, transform shading space to screen space before computing the difference.

#include <math.h>
vector latlong( const vector pos ) {
vector tmp_p = set(pos.x,pos.z,-pos.y);
float r = length(tmp_p);
float phi = atan2(tmp_p.y,tmp_p.x);
float theta = acos(tmp_p.z/r);
return set(phi/M_TWO_PI,theta/M_PI,r);
}
surface
myshader( export vector motion = {0,0,0} )
{
vector p1 = getblurP(0);
vector p2 = getblurP(1);
vector res;
int found = renderstate("image:resolution",res);
if (!found) res = {1,1,1};
res.z = 1.0;
p1 = latlong(p1);
p2 = latlong(p2);
motion = p2 - p1;
motion *= res;
}

Jsmack !
This is exactly the kind of ‘spherical mapping math’ I was imagining, but couldn't really implement it at that time.
I'll try this as soon as I've a hour or so. Thank you !
Alessandro Pepe
http://www.alessandropepe.com [www.alessandropepe.com]
http://pepefx.blogspot.com [pepefx.blogspot.com]
User Avatar
Member
178 posts
Joined: 1月 2013
Offline
What happens around the longitude divider line? Does it still work there?
User Avatar
Member
7771 posts
Joined: 9月 2011
Offline
Works well in my testing.
User Avatar
Member
178 posts
Joined: 1月 2013
Offline
Ah, cool, guess I was overthinking that part… which was what held me back from doing the same solution.
  • Quick Links