RenderMan & RISpec >> ramp shader -> spline and reparametrization

by UsOpbWkgRm9udGFu » Thu, 08 Dec 2005 18:19:33 GMT

Hi!

I would like to use the spline function to write a ramp shader, however
this function only takes points at equal distance. Then it restrict a
lot the flexibility of my ramp shader.

If there a cheap way to re-parametrize the spline function, and
consequently to interpolate points that are not at equal distance?

So far I've used a second spline to reparametrize the first one.

let's say I want to interpolate the points "spl_y[]".
y = spline(x, spl_y)

Now I want to give the x value of my points to interpolate, I have a
second spline "spl_x[]".

assuming X is "spl_x" reparametrized, I get:

X = reparam(spl_x)
x' = spline(x, X)
y = spline(x', spl_y)


This is working, however my fonction reparam is prettry slow. it does a
stupid search in an array for every single pixel to shade.

first question, is there a way to precompute a table at the first
execution of the shader, then there is no need to compute it again?

Second question, is there a better way to re-parametrized a spline?



here is my function to reparametrize a spline:



// *******************************************************************
/**
* Inverses the spline. We give the result and we get the input
* parameter
* a == spline(i, spl)
* i == invSpline(spl, a, prev, step)

* @param spl spline
* @param a the result from the spline function
* @param prev the previous value or 0. it is used to speed up the search
* @param step how precise do we inverse the spline
*
*/
float invSpline(uniform float spl[];
uniform float a;
uniform float prev;
uniform float step)
{
uniform float j = prev;
while(j<1 && spline(j, spl) < a) {
j += step;
}

return j;
}

// *******************************************************************
/**
* Reparametrizes a spline
*
* @param spl spline to reparametrize
* @param spl_n spline's size
* @param X the resulting spline reparametrized. its size must be bigger
* @param X_n X's size
*/
void reparam(uniform float spl[];
uniform float spl_n;
output uniform float X[];
uniform float X_n) {
uniform float i;
uniform float prev=0;
uniform float step = 1/(X_n*10);

// the first and last point are the same
X[i] = spl[0];
X[X_n-1] = spl[spl_n-1];


for(i=0; i<X_n-2; i+=1) {
uniform float grad = i/(X_n-3);
// we search where in spl the spline is equal to grad
prev = invSpline(spl, grad, prev, step);
X[i+1] = prev;
}
}



Thanks!


RenderMan & RISpec >> ramp shader -> spline and reparametrization

by Olivier3001 » Thu, 08 Dec 2005 22:39:25 GMT



Using two splines is the way to go but you want to use something more
efficient for the inverse computation. With some renderers, you can
prefix the spline name with "solve" to compute the inverse efficiently.
3Delight supports this for all splines and prman supports at least
"solvecatrom" (for catmull-rom splines); I haven't look at other
implementations.

If your renderer can't do that then you can improve your own function
by using binary search instead of linear search through the domain. You
can do even better by using a root finding algorithm which uses the
intermediate values to converge more quickly but beware of the
degenerate cases.

By the way, I think the common way to do ramps isn't to transform the
spline but rather to compute an inverse and a spline for every point to
map. This is probably more accurate and doesn't have a setup cost so
it'll be faster if you only need to ramp a few points. Your way will
probably be faster if there are more points to ramp than there are
control points in the splines. This is more or less what it looks like
(this exact code probably doesn't work):

float ramp(float s; float domain[]; float image[])
{
float x = spline("solvecatrom", s, domain);
return spline("catmull-rom", x, image);
}

As for precomputing arrays in shaders, I think the only way to do that
is through dso shadeops.

Olivier

RenderMan & RISpec >> ramp shader -> spline and reparametrization

by Ri Fontan » Fri, 09 Dec 2005 15:01:51 GMT

Thanks very much, this is very helpful :-)

RenderMan & RISpec >> ramp shader -> spline and reparametrization

by dansspam2@yahoo.com » Sat, 10 Dec 2005 13:30:11 GMT

Another option is to pre-compute a 1-pixel-tall texture map and use
that instead of the spline function.

Dan

Similar Threads

1. Anti-Aliasing for cubic spline shader