Thoughts on Velocity Information

I am currently trying to get a rendered bitmap which represents 3D velocity data at arbitrary intervals, e.g. a value representing the offset between a point’s position in the current frame and the position in the next frame.
From what I can understand from the SDK code (which may or may not be correct), the current interval for calculating velocity data for a mesh is hardcoded as #define PREV_TICKS -8.

Other than workarounds like precalculating all the velocities and baking them to vertex colors, can you think of any solution I could use, maybe writing a custom render element or texture map which would allow me to get what I need? Something that would work on the fly without modifying the scene objects?

Not sure I quite get what you need; you want to bake a velocity map? or you have a bitmap texture with the velocities and you want the renderer to use it?

Best regards,
Vlado

No, I should have explained better.
I’m essentially looking for a VrayVelocity render element, but one where I can control the d(t) interval which was used to calculate the velocity.
For example, generate a velocity element with which I could calculate for each fragment, where this fragment is going to be N frames from now, or where it was N frames ago.

The final use of the data is in 2D tracking.

Sorry if this is still unclear, I can elaborate as necessary.

Ok, I see. This is unfortunately hard-coded in V-Ray right now. I can probably add an environment variable to control the interval, would that work?

Best regards,
Vlado

I very much appreciate it, but I’m afraid a global setting won’t help my particular case. Specifically, I need to generate an element representing offset from (T) to (T+1) and another representing offset from (T) to (T-1) within the same render pass.
I understand of course that this complicates things, and do not expect you to give it priority.

Would it be possible for me to implement a plugin (render element? texturemap?) which achieves this using the VRay SDK?
I only expect it to work for topologically consistent meshes.

Well, the VRaySamplerInfo render element has two options “Forward occlusion” and “Backward occlusion”. In order to get them to work, you need to have motion blur enabled. When either of the two elements is present, V-Ray will render the scene at the motion blur interval center (without motion blur); the “forward occlusion” element will give you the pixel offset of the shaded point from where it is at the moblur interval center to where it is at the end of the moblur interval; the “backward” occlusion will get you the offset from the interval center to the start of the moblur interval.

Would that help?

Best regards,
Vlado

That sounds amazing, except I can’t make sense of the values I’m getting.


What exactly does the R value 0.706 in the forward occlusion element represent in this case?

(This was with 3.20.02 btw, I can try 3.30.03 if it will make a difference)

Sorry, I was wrong, the values are not pixel offsets; they are normalized pixel coordinates (0-1) of where the point would have been at the start (resp. end) of the moblur interval.

So in your case, a value of 0.706 in the R channel means the point would have been at (imageWidth)*0.706 x-coordinate at the end of the moblur interval. What resolution are you rendering at?

Best regards,
Vlado

Ah, that seems correct! (the image I posted was cropped).
This looks like it just might be it. I had looked over this element a few times already, but couldn’t figure out what these values represent, or that they were related to motion blur.
I’ll try to implement my solution using these elements and post back here.

Thanks so much for taking the time to help, Vlado!

Ok, let me know if this helps.

The blue channel, if you ever need it, is the occlusion of the shaded point with respect to the camera in the start/resp. end of the moblur interval.

Best regards,
Vlado

Yeah, that’s an issue I’ll need to resolve. I would need it to be the Z value in camera space.
I’m looking at the VraySamplerInfoTex source now, I will see if it’s something I can achieve using this code,

Maybe if right after:

TracePoint ptCam=sdata.cameraImageSampler->interpolateTimePointInverse(pt, time); //(vraysamplerinfotex.cpp Line 92)

we just return that value instead of mapping it to the screen and computing occlusion (I’m assuming it represents the point in camera space).
I’ll give it a shot.

Yes, you could do that.

Best regards,
Vlado

Seems to be working pretty well. I’ve managed to have the element calculate the velocity and use that.


	DefaultVRayShadeInstance *si = (DefaultVRayShadeInstance*)GET_INTERFACE(rc.rayresult.si, EXT_DEFAULT_SHADE_INSTANCE);
	if (!si)
	{
		return Vector(0.0f);
	}

	// Get the point at the start of the motion blur interval
	Vector offsetPt=si->getBasePt(rc, (which == timeMoment_frameEnd) ? 
		DefaultVRayShadeInstance::baseTime_frameEnd : 
		DefaultVRayShadeInstance::baseTime_frameStart);

	Vector thisPt = Vector(rc.rayresult.getPoint());

	const VRaySequenceData &sdata = rc.vray->getSequenceData();
	// Project the point onto the camera at the start of the motion blur interval
	float time = (which == timeMoment_frameEnd) ? 1.0f : 0.0f;
	TracePoint offsetPtCam = sdata.cameraImageSampler->interpolateTimePointInverse(TracePoint(offsetPt), time);

	VR::Vector2 offset_p_img(0.0f, 0.0f);
	VR::Vector2 this_p_img(0.0f, 0.0f);
	int mapRes = sdata.cameraRaySampler->mapToScreen(offsetPtCam, offset_p_img, time);
	int mapRes2 = sdata.cameraRaySampler->mapToScreen(thisPt, this_p_img, 0.5f);
	if (mapRes && mapRes2)
	{
		double depthDelta = (offsetPt - rc.rayparams.tracedRay.p).length() - rc.rayresult.wpointCoeff;
		VR::Vector2 offset = offset_p_img - this_p_img;
		return Vector((double)offset.x, (double)offset.y, depthDelta);
	}

	return Vector(0.0f);

My current problem is how to get it to ignore atmospheric shading, like VRayVelocity does.

For example, see teapot with VRayToon applied (this is the element, not the main channel).


Can a VRayRenderElement element simply ignore the effect of the atmospheric and shade the surface behind it?

All I needed to do was disable ‘Optimized atmospheric evaluation’.
Works like a charm now, thanks again Vlado.

Ok, glad that it’s working now :slight_smile:

Best regards,
Vlado

I spoke too soon actually. This seems to only work when filtering is disabled for the element (when we only use the ‘front’ Fragment in storeSample).
Anyways it’s a compromise I can gladly live with.

There’s probably a way to resolve this; let me know if you need a solution at some point.

Best regards,
Vlado

Thanks. For now it looks like this will work.

Another question: Are ‘geometry samples’ guaranteed to be equally distributed temporally?
In other words, with the following settings:

Duration (frames): 2.0
Interval center: 0.0
Geometry samples: 3

Are the 3 samples guaranteed to be at (T-1), (T), (T+1) ?

Yes.

Best regards,
Vlado

Just to update, this has worked very well for my purpose.
The only issue I’m still battling with is if the user is rendering via a VRayPhysicalCamera.
Do you know a way I could enforce a duration of 2.0 frames and an interval center of 0.0 at rendertime regardless of the camera settings, or more simply to tell VRay to treat the camera as if it were a regular camera and use the regular motion blur?