Looking For C++ Spline Shader Code


#1

Hi,
I’m making shaders in Cinema4D which does not use Renderman shader code or have a built-in spline class for drawing splines.
Does anyone know where I can find a raw C++ spline shader class that I can use as a learning example, and possibly port over to C4D?
By raw I mean no third party stuff in it like Boost if possible.

The maths in these things are hard for me to understand. So I’m looking most for simple splines and not the fancy bezier splines. But I’ll take whatever I can get at this point.

Thanks,
-ScottA


#2

Cinema 4D draws splines in rendering in several ways without requiring any coding, you can use the inbuilt systems (Hair, Sketch & Toon, Geometry), or plugins (Storm Tracer, DPit, DiTools etc), or write your own.

To render splines directly you have a whole load of options, if you want to take full control you would need to pick whichever method suits you best. A simple method would be to do a high quality viewport render of your splines, grab it and simply combine it with your standard render. But you might want to do your own raytracing or scanlining of your splines instead,

Honestly it sounds like you’re trying to bite off a little more than you can chew right now, but it’s not as scary as all that. For you to succeed you should just break down the task into easier to manage parts.

So lets break down spline rendering itself should you wish to go this route, the most common method of dealing with this are to either create geometry and let the render engine deal with all the tessellation, BSP sorting and optimizing. You deal with them as volumetric isosurfaces and can calculate all the hits yourself if you want, but it’s a lot more involved and I think you’d rather go for a quick and dirty method.

This is very easy in Cinema, the fastest route would be to invoke a script that swept a single line along your splines at rendertime in the render document (this would hide the geo from the viewport). You can do this in more or less any “Node” plugin i.e. SceneHookData, VideoPostData (with inherent flag), even TagData, MaterialData, Object data if you had those in scene. You can catch the message from the document that it’s about to render and modify the document however you want at that point. Just be sure to erase your geometry from the document if the render is a viewport render rather than an external render. Another option is within a VideoPostData::Execute function, the SDK docs explain the order of execution on this. To actually generate the sweep why not simply use a sweep generator, this gives you access to e.g. rail splines, or the inbuilt curves for width, twisting etc and solves the problem of you having to learn about LineObject’s, PolygonObject’s and the (pretty simple, but when you’re starting out probably more than you need to know) math involved in generating the correct geometry.

After you’ve created your geometry you’ll want to add a material, I’d imagine you’re after a flat shaded set of lines, so again no need to make a new material, just use the standard one, only enable the luminance channel and if wanted add a gradient (along U) and apply that to your geometry object.

If you want a constant size (i.e. ignore perspective), then either use the opengl/software shading viewport render to get your splines (very fast) or you can scale up the width of your rail by viewport distance to compensate. Obviously it’s just screen size = actual size / distance to eye, however doing some basic math would be effort, so why bother when there are functions for this stuff already built right in. What you need is both in the BaseDraw and VolumeData, personally I’d opt for the BaseDraw as you’ll be generating your geometry actually outside of the render engine, so call BaseDocument::GetRenderBaseDraw() with the current document to get your basedraw, then use the BaseDraw::PW_S() function to give you a unit scale to use for each pixel at the depth passed (i.e. the z-depth of each line point of your sweep).

If you have specific questions you may have more luck on plugincafe.com or in the scripting subforum of the Cinema 4D area here.


#3

Hi Anders,
I get the feeling from your reply that maybe you don’t recognize me?
I’m ScottA in the plugincafe.com forums. The guy who posts a rather large amount of code there.
And I’m also the guy that asks a bazillion annoying question too.:slight_smile:

Anyway.
I know how to use the SplineObject class in C4D.
And I did ask at the cafe for help in creating a custom spline class. And nobody could help me. So I went out and searched the net for code about splines. And I was able to learn enough to write a very simple smooth spline class. Which I then wrote into a plugin that allows the user to draw a smooth 2D spline on the Editor Window.
I’ve also written every type of plugin that C4D supports in both C++ and Python. So I’m fairly familiar with the SDK.

But now I’m working on Shader Plugins. Which is an entirely different thing from the SplineObject class. Or the BaseDraw class stuff that lets us draw things to bitmaps and the Editor Window.
And there’s almost nothing in the C4D shader class. It’s very bare bones in there. And pretty much everything has to be written from scratch. Or at least I don’t know any way to use the other classes inside of the Shader class.
Writing shaders in C4D seems to be a black art that only a few people know how to do. And they don’t post any tutorials about it. And I can’t find anyone with much knowledge about this that I can talk to at the cafe either. So I’m basically climbing this mountain on my own.

Drawing shapes, and specifically splines, in shaders requires a lot of maths that I’m having a hard time finding on the net.
Most shader code out there is written for Renderman. Which uses different naming conventions than the C4D shader code. So it’s a bit of a challenge to convert them. But so far I’m doing ok. And I’m slowing building a library of C4D shaders from them.
But I’m having a very, very hard time figuring out how to make a spline class for C4D shader plugins.
Renderman has a built-in spline class. So none of the RM code out there is helping me out.

As far as I know.
I can’t use any of the existing spline classes in the SDK for Shader plugins. I have to write one from scratch on my own.
But I can’t seem to find any spline class code out there written specifically for use in shaders.
So I’m asking around if anyone has ever seen one that I might be able to learn from. And possibly be able to convert into C4D compatible shader code.

-ScottA


#4

Sorry, I’m afraid I don’t visit plugincafe very frequently. I’m not sure why no-one would give you help there on this, but what you’re asking is not particularly complex, unless you have specific needs.

Making a custom spline type is almost the same as making any other generator. The only difference is that you must set the OBJECT_ISSPLINE flag during registration and overload the ObjectData::GetContour function to return your spline on demand.

Could you clarify your objectives a little. Shaders, Materials and VideoPosts all have their merits for different situations. You’re talking about shaders, which confuses me, typically shaders only apply to geometry and splines on their own have none. So unless you’re wanting to make another spline shader or proximal style affair that’s different in some way from the inbuilt ones then I’m not quite sure of the intent. What exactly is the end goal here? Something like the older version of Doodle that allowed you to draw with vector (splines) as well as bitmap tools?

Right now you can simply put a spline into the spline shader, use that as the alpha channel for a foreground object and render away that way if you just need a 2D spline rendering. No need to write your own shader for this.

If there’s some reason for the shader itself then they’re also pretty simple things. The sample function is invoked most commonly by an owning Material which is in turn called to evaluate one of the materials own channels (see BaseMaterial and MaterialData for a list of these), most of those channels are surface based with the exception of CalcVolumetric, which is not made use of by the default standard Cinema Material, they can also be called of course by VideoPost plugins or any other plugin that simply wishes to, From within them you have your surface intersection information, the ray info, the current state of the render engine for that thread, and access to the render engine itself to invoke whatever functions you need in the VolumeData, and finally whatever info you feed it and you simply return a Vector as the output. The SDK examples together with the documentation should be sufficient starting point for most endeavors, but it helps if you’re comfortable with render engines and know what order things get called in and why within Cinema’s own object system. The problem with a shader for what I assume you’re describing is that unless your plugin controls when and where that Shader is called then without actually generating geometry then I’m not sure that it can do what you want.

The far superior way of rendering splines either as volumetric or as 2D is to use a VideoPostData as I described before. For 2D (like the HUD and Doodle) you simply grab the bitmap and draw right into it. For volumetric (like Sketch & Toon, HAIR, Storm Tracer) you have lots more fun options, CalcVolumetric, ExecuteLine, ExecutePixel in the VideoPostData or generating geometry as I covered in my previous post.

If you could explain how you’re using your Shader, what you expect it to output, what it’s actually outputting, then it might be a little clearer.

If you just require something to render the splines to bitmaps, then the inbuilt bitmap classes have enough to do that, and you can always as mentioned just use your existing drawing code for the basedraw, do a viewport render and grab that. Or you could try a library like Cairo : http://cairographics.org/ however as it doesn’t have your custom spline type that you’ve made then you will still have to use it to draw your splines exactly as you’re already doing, so no additional fidelity.


#5

Yes. I know about the built-in spline shader in C4D.
In fact I like it, and I’ve used it a lot. And I’ve even written some helper code for it so that it redraws the shader automatically whenever I edit the spline object that’s it’s using.
It currently doesn’t redraw automatically like that. And that was annoying so I wrote some code to send a message and update it whenever the spline was altered.
Like I said…I am pretty familiar with C4D and most of the SDK.

But I am learning to make shaders. And I would like to learn how to draw a spline directly inside my shader space using the shader maths.

An example of some C4D shader code:

//This code creates a square shape using a custom pulse formula
   //The pulse formula is created by subtracting two Step() functions
   
   #define PULSE(a,b,x) (Step((a),(x)) - Step((b),(x)))   //A custom pulse formula
   
   	Vector colors;
   	Real px = cd->p.x;
   	Real py = cd->p.y;
   
   	Vector red = Vector(1,0,0);
   	Vector white = Vector(1,1,1);
   
   	Real xValue = 0;  //Grow in X
   	Real yValue = 0;  //Grow in Y
   	Real pulse = PULSE( px-xValue, py+yValue, 0.5 );
   	colors = Mix( red, white, pulse );
   
   	return colors;

I keep reading that the Renderman shader code has a spline built-into it.
But the C4D sdk does not have one.
So I am looking for the code that will let me draw splines in shader space using shader maths.
And I then I’m going to try and convert it to work in C4D if I can.

Previously, when I was working on drawing things to the Editor Window in C4D I discovered that there was no 2D spline function in the SDK. All it had built-in was lines, but no spline function. So I had to write my own spline class myself from scratch.
Nobody could tell me how to write a spline class at the cafe. So I had to learn how to do from C++ examples on the net.
Now I can draw 2D splines in the Editor Window using my custom class. Smoothed splines like you see in the xpresso editor that connect nodes.
I can draw those kinds of smooth splines directly onto the Editor Window now.
That functionality is not in the SDK. I had to write from scratch.

Now I’m in a similar situation with the Shader plugin.
I know how to draw shapes, and lines using shader code I’ve learned from RM examples. But I don’t know how to draw splines in shader code.

I really am 100% looking for shader code here. And nothing else.
I’m learning about writing shaders in C4D. And I’m not looking for a way to cheat using the spline shader or anything else.
I’m trying to learn to code shaders in C4D Shader plugins using shader maths. Without cheating or using anything else.
And the one thing that is proving to be very tough for me to figure out is how to draw splines using shader maths.
There’s very few people in the world writing Shader plugins using shader maths in C4D. So I have to do what I did to solve my Editor Window spline problem.
I have to find a C++ spline shader example that was written for something else like Renderman shaders. And convert it into C4D code.

I really am looking for shader code. And not anything else.
I’m trying to learn how to create splines in shader space using shader maths code.
I know how to draw lines with shader maths. But I don’t know how to connect multiple lines into a smooth spline using shader maths.

I hope that makes it clearer.

-ScottA

*Edit- I might possibly be able to use the spline class I wrote for the EW. Because after all it’s basically the same thing. Connecting multiple lines then smoothing the result.
But since I’m new at shader maths. Trying to apply it to shader lines code is very confusing to me.


#6

Hi. I think you are confused about what ricurves are in renderman, they’re a geometric representation of splines, a spline primitive, I.e. A 3d object in the render engine, not really a surface parameter.

You also do have access to splines from the SDK, I’m not sure why no-one explained this, or why a search for the basic terms in the API docs didn’t bring this stuff up for you, you can also just allocate a standard spline object and call its functions to evaluate its pure form. Just because it’s 3D doesn’t mean you have to fill it with 3D data. However, ignoring all of this, for spline drawing in a shader you can use any algorithm you want.

e.g. You want to draw a filled shape, then just evaluate the in/outside state for the sampled point in uv space. You want to draw an outline you simply calculate the distance to the nearest point on your spoon and return one color if the distance is shorter than your line width. You could also prebuild a bitmap and simply return that, or use it as an acceleration structure…

It’s a pretty open ended thing, but few libraries out there wil be based on rendering splines by sample rather than directly setting pixel values, so they’re unlikely to be of much use. Treat the sampling as if it were stochastic, I.e. You have no control over the spcial order of each point that’s sampled, your cinema 4d shader example was pretty incomplete, you ommited the function it’s in and the passed arguments which contain the information about the location of the sample and current state of this thread of the render engine, just take the uv point and work from there.


#7

I’m not questioning you’re knowledge Anders. So please don’t take this the wrong way.
But what you’re saying doesn’t make any sense to me. Because I have a book that shows the use of renderman shader code using a built-in Spline() function. And there is an illustration of the results of it that looks exactly like a spline being drawn inside of the shader uv canvas.
I call the 0-1 shader area the “canvas”. I don’t know if that’s the correct term for it. It seems natural to me to call it that.
What you’re saying is contradicting what I’m reading. Either that, or I’m completely mis-reading this book. So I hope you’ll understand why what you’re saying isn’t making sense to me.
I have never written any RM shaders. Yet it’s all I have to help me learn how to write C4D shaders. So I am sort of flying blind here. I’m having to make things up to convert the RM example code to C4D. And I’m probably making a lot of mistaken assumptions along the way.

When you say it’s simple. Just evaluate the in/outside state for the sampled point in uv space. That’s not really so easy for me to do. Because to do that and draw as spline across the UV canvas requires using some pretty fancy formulas.
I’m going through those math pains already because drawing any shape on the shader canvas requires pretty fancy formulas. And math is not exactly my best subject. So right now I’m struggling just to create simple shader shapes. And learn the maths.
I’m slowly doing it. I’ve figured out how to make bunch of shapes. But I haven’t fully conquered it yet. And I’m still a long way from having full control over being able to draw what I want on the canvas.

What I want to do the most is to draw splines on the shader canvas. But it’s too mathematically complicated for me to figure out without some kind of example to help me. And any RM code I find always uses a built in Spline() function that the C4D Shader plugin class doesn’t have.
That’s why I’m looking for any kind of spline shader code that might help me figure it out.

-ScottA


#8

The “Shader Canvas” as you describe it is known in rendering terms as UV space. It’s important that you get used to the nomenclature of rendering as it will make your searches many times faster.

A “spline” in RSL is a 1d value interpolation, think like a spline customdatatype in Cinema or more typically a gradient, curves refer to ricurves, which are actual 3d geometry,

Lets look at a bezier shader in RSL :

http://www.hosok2.com/project/st/st_coloration.html

His approach is basically what I described before, find your nearest point to the spline, evaluate distance, if within output one color if not another. You can basically use the same code for the most part in your Cinema 4D shader. Just take your spline, evaluate it by subdividing and sampling for small linear segments, then evaluate the distance for each line segment.

You can simply use the SplineObject’s GetLineObject function to get your line already subdivided up for you if you wish (using the interpolation method described in it’s attributes), or you can do this yourself either on the fly or in your Init function.

Here is a direct link to his source for the kitty example :

http://www.hosok2.com/project/st/bezierCurve_kitty.sl.txt

The maths have already been done for you in here, although you can also make use of the inbuilt function sin Cinema for this stuff, you will find a PointLineDistance function in the c4d_tools code and a PointLineSegment function is available in the BaseView, which you can always allocate as a BaseDraw, initilize with an ortho projection and abuse as you see fit. If your real intent is to get a grip on the math behind it all then a good starting place for coders is Geometry Algorithms http://geomalgorithms.com/ and I recommend PBRT as an introduction to rendering coding concepts.


#9

Yes! Thanks Anders.
Those links are exactly the kind of thing I’m searching for.
Good lord the maths for shaders are so scary. :eek:
It’s going to take me a very long time to figure this geeky stuff out.

And thanks for the clarification on the Spline() function.
The way it is described in my book they make it sound like an actual spline creator. Not a gradient.
It would probably a lot easier to learn this stuff if I had access to working with RM shaders. So I could play with the code and see what happens if I change the values. But I only work with C4D code.

This is something that you mentioned before and I didn’t understand.
As I said earlier. In order to draw a 2Dspline directly on the Editor Window. I had to write a custom spline class which simply make use of the BaseDraw()->DrawLine() function in the SDK.
My class creates 4 or more copies of a line using DrawLine(), connects them end to end, Then uses four control points to control the spline.
The result is a smooth 2Dspline with four control points(Catmull?). Like the ones used in xpresso to connect the nodes together.
But you seem to be saying I could have done that same thing using the SplineObject class. And I don’t understand that. Because I didn’t want to create an actual physical spline object in the OM just to be able to draw one in 2D in the EW.
So I’m wondering how the heck you can use the SplineObject class like that without creating an actual physical spline object in the OM?
That sounds like a useful thing to know how to do. But I don’t really understand how to do that.

This is turning into C4D specific stuff now. So I don’t know if it’s appropriate to keep discussing it here.
I don’t know if it’s better to take it to the plugincafe or not. But I’m sure the people there would also like to know how to do this kind of thing too.
Right now my spline class is the only 2D spline solution ever posted there.

Thanks for your help,
-ScottA


#10

No need to reinvent the wheel. There is nothing wrong with allocating a SplineObject for spline work, it’s what it’s designed for after all and it’s optimized for that task. It also acts as a handy container for your data both for caching and just to reduce complexity while giving you access to many helper classes and functions designed for working with splines.

If you’re going to rewrite something there should be a good reason, e.g. new functionality, better optimization for the task involved etc, and the payoff has to be worth the effort, in this instance I highly doubt you would gain much by rolling your own. To put it another way, it’s a 3D app, it contains among other things such as Vectors, Matrix, Quaternions, their related math and so on structures also for things like splines with plenty of public API access to them, so why not use them?

As an alternative to the SplineObject then if you need a quick calculation with no allocation involved (beyond your own points) and all you have is a points array you can calculate any point along a b-spline quickly from a value array without allocating a container object for the task in 1D, 2D or 3D using the CalcSpline function in c4d_tools.h.


#11

Ok. Thanks.

I really didn’t want to use a physical spline object to draw my 2D splines.
I know we can hide them from the user. But I just wanted to do it without using the the SplineObject. Because if I go to code the same thing in another program. The SplineObject won’t be there for me to lean on as a crutch.
But I’ll take a stab at using the CalcSpline() function and see if I can use it in my code too.
I do try to use the stuff that the developers have already provided us as much as possible.
If there was already a 2DSpline function in the BaseDraw class I would have gladly used it instead writing my own. But at least it was good learning experience for me.
I’m still trying to get better at making splines. Heck…I’m still trying to get better coding period.

I’m having some problems converting that RM spline example you posted a link to into C4D shader plugin code.
But those are C4D SDK specific problems. Not C++ problems. So I’ve asked for help over at the plugincafe about it.

Thanks again for your help and advice,
-ScottA