![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I have an isosurface that's making my 2.2 GHz Athlon64 cry. Currently
averaging just 40 pixels/second - and that's just for the *black*
pixels! I hate to think what it will slow down to if it ever gets to the
part with some surface in it...
The real killer is that it's actually a very simple (I might even say
"boring") shape I'm trying to trace. It's essentially a Z-shaped oval
pipe. That's it.
However, since it's the isosurface of a 18th degree polynomial, I've had
to set max_gradient=exp(18) to get it to render correctly.
In layman's terms, the problem is simple. Because the *maximum* gradient
of the function is extremely high, POV-Ray is densely sampling all of
space (even the completely empty parts) just in case there's some
surface there. In fact, it just so happens that the edges of the
bounding box are where the function is steepest; where the surface is,
the function is fairly shallow.
And so, I've been sitting here thinking about all the ways POV-Ray could
arrive at its result faster. The trouble is, I can think of quite a few
that would work for *this* shape, but would fail in special cases. It
just so happens that the shape I'm trying to trace has a huge max
gradient, but is actually a very simple shape.
One idea is if POV-Ray were to cache the locations of previously
discovered surface points. Then instead of densely sampling the entire
length of a ray, you would only need to sample "around" where the last
surface was found.
This instantly fails when you reach a nearer edge that should occlude
the previously-found surface. POV-Ray would *still* need to densely
sample all the way back towards the camera to check it's found the
*nearest* surface point. (Also, a cache lookup would have to end up
being quicker than just calculating samples...)
Another idea is to do a little prepass stage where POV-Ray builds up a
low-res 3D map of the surface, so it has some idea where to start
looking when tracing a ray. You start by finding a surface point - ANY
surface point - and then finding other surface points near to it, until
you have covered the entire surface with a loose grid of points. Doing
it this way avoids the edge problem, because you "follow" the surface
round before you even start tracing.
This instantly fails if the surface is not completely connected. It also
fails if the grid points are too far apart to pick up small details.
(You would need something like a max_complexity number telling POV-Ray
how "messy" the surface is, and hence how fine a grid to use.)
Yet another idea (similar to the previous one) is to split all of space
into a grid of cubic volumes, and attempt to figure out which cubes
actually contain some surface, and which ones are completely empty.
Once again, this doesn't work well for disconnected surfaces. How will
you tell if a cube contains anything? POV-Ray would need to know the
minimum possible size of a feature to look for... And then how would you
actually look for it? We could end up doing more work here then what we
do currently!
In short, lots of ideas that would work for the shape I'm trying to
trace, but none that would work for every possible shape one could try
to trace.
Anybody have any further thoughts?
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> In short, lots of ideas that would work for the shape I'm trying to
> trace, but none that would work for every possible shape one could try
> to trace.
>
> Anybody have any further thoughts?
Nothing general, but if you (the user) know where the bits of surface
are, you could try splitting up the isosurface into smaller chunks, and
set the max_gradient lower where it doesn't need to be as high. I
couldn't tell from your description whether this is the sort of
isosurface that that would work for: it usually works well for functions
with low gradients in most places but singularities at a few points.
--
"Of all things, good sense is the most fairly distributed: everyone
thinks he is so well supplied with it that even those who are the
hardest to satisfy in every other respect never desire more of it than
they already have." -- Descartes, 1637 http://surreal.istic.org/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Anybody have any further thoughts?
> Nothing general, but if you (the user) know where the bits of surface
> are, you could try splitting up the isosurface into smaller chunks, and
> set the max_gradient lower where it doesn't need to be as high. I
> couldn't tell from your description whether this is the sort of
> isosurface that that would work for: it usually works well for functions
> with low gradients in most places but singularities at a few points.
Hmm... could work.
Attached is a graph of the function I'm trying to trace. (Note the
LOGARITHMIC Y SCALE!) The red line is the function. The green line is
the isosurface threshold. (i.e., the parts below that line are "inside",
and the parts about it are "outside".)
You can see why POV-Ray is struggling; on a linear scale, the graph is
two vertical lines with a flat part in the middle. So POV-Ray has to
tip-toe through space at some ridiculous spacing to be absolutely
certain that there isn't some vertical line in the graph taking us down
to a surface. If it was a different function, there might be. But for
this one, there isn't.
Currently POV-Ray has the maximum possible gradient. That is, the 1st
derrivative of the function's value with respect to space. I wonder -
would POV-Ray be able to do something more intelligent if it had the
maximum SECOND derrivative too? Then perhaps it would know that the
sides are very steep, but the steepness can't change very suddenly...
Hmm, no, that's still not much help.
Post a reply to this message
Attachments:
Download 'graph1.png' (11 KB)
Preview of image 'graph1.png'
![graph1.png](/povray.advanced-users/attachment/%3C44f2fdac%40news.povray.org%3E/graph1.png?ttop=443814&toff=650&preview=1)
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v3 wrote:
> Anybody have any further thoughts?
Post a minimal scene with the function, there might be ways to improve
render time.
Thorsten
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v3 <voi### [at] dev null> wrote:
> However, since it's the isosurface of a 18th degree polynomial, I've had
> to set max_gradient=exp(18) to get it to render correctly.
I suppose you have tried with a lower max_gradient and it resulted
in an incorrect rendering?
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> However, since it's the isosurface of a 18th degree polynomial, I've had
>> to set max_gradient=exp(18) to get it to render correctly.
>
> I suppose you have tried with a lower max_gradient and it resulted
> in an incorrect rendering?
Yes.
Specifically, a black image. (max_gradient=exp(17) renders with a few
holes. exp(16) gives a totally black picture.)
Have a look at the graph I posted. The sides of this function rise like
x^18, but the bit in the middle is quite "flat". Without the
astronomical max_gradient, POV-Ray samples the edge of the BB and sees a
value like 10^12 or something, and thinks "hey, no surface for miles
around" and doesn't find anything. But if you turn up the max_gradient
high enough to make POV-Ray take resonable size steps even when f=10^12,
then when you get to the middle POV-Ray start to take *minute* little
steps...
It seems I've found a very pathalogical case for the particular
algorithm POV-Ray is using. As I said, I'm not really sure what POV-Ray
could do differently here...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
I just had a brainwave!
I changed fn(x, y, z) to log(fn(x, y, z)), and changed the max_gradient
to 4. I'm now getting several thousand pixels/second.
Of course - the logarithm function makes the crazy vertical sides less
"vertical", while not flattening out the parts near the solutions so
POV-Ray still has some contours to go on.
(I read somewhere that dividing your function by a big number makes
max_gradient lower, but doesn't make it trace any faster. But this trick
makes the big numbers small, but leaves the small numbers alone so
POV-Ray doesn't go around taking tiny steps there any more.)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Wasn't it Orchid XP v3 who wrote:
>
>(I read somewhere that dividing your function by a big number makes
>max_gradient lower, but doesn't make it trace any faster. But this trick
>makes the big numbers small, but leaves the small numbers alone so
>POV-Ray doesn't go around taking tiny steps there any more.)
That sounds like me
http://www.econym.demon.co.uk/isotut/dont.htm
I'll have to go back to that page and see if your trick can be applied
generally.
--
Mike Williams
Gentleman of Leisure
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> (I read somewhere that dividing your function by a big number makes
>> max_gradient lower, but doesn't make it trace any faster. But this trick
>> makes the big numbers small, but leaves the small numbers alone so
>> POV-Ray doesn't go around taking tiny steps there any more.)
>
> That sounds like me
>
> http://www.econym.demon.co.uk/isotut/dont.htm
Yeah.
Ooo... "you can't use arrays in an isosurface function". Um... well... I
just did. :-.
> I'll have to go back to that page and see if your trick can be applied
> generally.
You gotta see the isosurface function the way POV-Ray sees it. (See the
graph I posted in another reply here.)
I've been thinking about the way POV-Ray's sphere-tracing algorithm
works. (I should diagram that thing sometime...) Anyway, it seems that a
large max_gradient isn't too much of a problem, by itself. The problem
occurrs when
1. The function has a high max_gradient.
2. The function has large areas of "nearly zero".
The high max_gradient makes POV-Ray take tiny little steps through the
nearly-zero areas. (But if you turn down the max_gradient, the high
values make POV-Ray take giant steps and completely miss the surface.)
The logarithm function is perfect here, because it makes big values
small, but doesn't change small values much. (The sqrt() function would
work too, but to a lesser extent.)
Problem #1 is going to be negative numbers. You'll have to bias the
function completely into positive space before attempting to take the
logarithm, and then bias the result back. This fails for functions that
zip of to minus infinity. (Actually, it's probably best to keep the
whole function above 1, rather than just above 0.)
Note that my solution works because the surface I'm actually trying to
draw is quite simple, it's just the maths is confusing POV-Ray. Not sure
what happens if the surface really *is* complicated - I suspect you
can't do too much about that...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v3 <voi### [at] dev null> wrote:
> Ooo... "you can't use arrays in an isosurface function". Um... well... I
> just did. :-.
You can use an array to *create* an isosurface function. You can't
use an array *in* an isosurface function (IOW the function cannot
access an array).
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |