Example CreateRay()

  • Hi folks,

    is there an example lens effect using the CreateRay() override somewhere? I'm trying to make a custom lens but the draw is all over the place. Would like to see a working example. Something similar that would draw like the default (assuming there is one).


  • hello,

    We don't have example for this, I've write an example with the really minimum.
    This videopost will only be available with the standard render.

    You have to define for each pixel where you are ( dst->p) and where you are looking to (dst->v) (ray position and ray direction)

    This is for render time, if you want to create a Lens Effect for the viewport this is a bit more complicated.

    I hope this will help while we create a final example.

    #include "c4d_videopost.h"
    #include "c4d_baseobject.h"
    #include "c4d_tools.h"
    #include "c4d_basedocument.h"
    #include "c4d_basedraw.h"
    #include "c4d_resource.h"
    #include "c4d_gui.h"
    #include "drendersettings.h"
    class VP_PC11585 : public VideoPostData
    	INSTANCEOF(VP_PC11585, VideoPostData);
    	static NodeData* Alloc() { return NewObjClear(VP_PC11585); }
    	virtual VIDEOPOSTINFO GetRenderInfo(BaseVideoPost *node);
    	virtual void CreateRay(Ray* dst, Float x, Float y);
    	virtual RENDERRESULT Execute(BaseVideoPost* vp, VideoPostStruct* vps);
    	virtual Bool Init(GeListNode* node);
    	virtual Bool RenderEngineCheck(BaseVideoPost* node, Int32 id);
    	Matrix camMg; /// Will store the camera matrix
    	Int32 m_xres, m_yres; /// Render size in parameters
    VIDEOPOSTINFO VP_PC11585::GetRenderInfo(BaseVideoPost *node) {
    	// The videopost will provide custom lens rays with VideoPostData::CreateRay.
    Bool VP_PC11585::Init(GeListNode *node) {
    	return true;
    RENDERRESULT VP_PC11585::Execute(BaseVideoPost *vp, VideoPostStruct *vps)
    	if (vps->vp == VIDEOPOSTCALL::INNER && vps->open && *vps->error == RENDERRESULT::OK && !vps->thread->TestBreak())
    		const RayCamera* cam = vps->vd->GetRayCamera();
    		if (cam == nullptr)
    		// Retrieves the camera matrix
    		camMg = cam->m;
    		// Store the image resolution
    		m_xres = vps->vd->GetRayParameter()->xres;
    		m_yres = vps->vd->GetRayParameter()->yres;
    	return RENDERRESULT::OK;
    void VP_PC11585::CreateRay(Ray *dst, Float x, Float y) {
    	Float ppx = m_xres / 2.0;
    	Float ppy = m_yres / 2.0;
    	// Projection 360° in probe render (circle)
    	// centering optical axis around image center:
    	// Check if width or height is the larger
    	Float maxRad = (ppx < ppy) ? ppx - 1 : ppy - 1;
    	// Linear mapping of radius to angle (90 Deg = max)
    	Float  angleStep = PI / maxRad;
    	Float newx = x - ppx;
    	Float newy = y - ppy;
    	Float r = sqrt(newx * newx + newy * newy);
    	// Do not render outside of radius
    	if (r < maxRad)
    		// Calculates polar coordinates
    		Float phi = atan2(y - ppy, x - ppx);
    		Float theta = r * angleStep;
    		// Calculates ray direction v in global coordinates
    		Vector H = camMg.sqmat.v1;
    		Vector V = camMg.sqmat.v2;
    		Vector A = camMg.sqmat.v3;
    		H *= cos(phi) * sin(theta);
    		V *= -sin(phi) * sin(theta);
    		A *= cos(theta);
    		Vector v = H + V + A;
    		dst->p = camMg.off;
    		dst->v = v;
    Bool VP_PC11585::RenderEngineCheck(BaseVideoPost *node, Int32 id) {
    	// Only supports standard render
    		return true;
    	return false;


  • Interesting!

    Just out of personal interest, how would one start off with a custom lens that does nothing (just creates rays as the "default lens" would do)? If you could include code in your example that generates "unchanged" rays, that would be a great start for interesting custom lenses!


  • That did the trick - thanks Manuel. 👍

  • hello,

    @fwilleke80 i'm working on a example and i'll try to provide one as soon as possible.


Log in to reply