POV-Ray : Newsgroups : povray.binaries.images : A doodle and ramblings on pattern{} and iso perturbation Server Time
7 Jun 2025 18:40:44 EDT (-0400)
  A doodle and ramblings on pattern{} and iso perturbation (Message 1 to 10 of 10)  
From: William F Pokorny
Subject: A doodle and ramblings on pattern{} and iso perturbation
Date: 1 Jun 2025 09:44:03
Message: <683c5923@news.povray.org>
Got frustrated and took a break from my options parsing re-work. I used 
the time to implement an isosurface doodle related to a couple recent 
threads. Namely, the ones about perturbing isosurfaces and using 
pattern{} while defining functions.

Tips /thoughts
--------------

1) A subtle use of pattern{} is to wrap existing functions with it so 
you can use the inbuilt pattern modifiers as part of creating a derived 
function. For example, we can apply isosurface perturbations with 
warp{}s. In the posted image the rough texture comes from the 
application of a warp{} turbulence. A code excerpt is below.

As a bonus (especially in yuqk using its raw_wave modifier), the 
approach often leads to much lower isosurface gradients because the 
perturbation is done by the warp{}. The 'nested isosurface evaluation' 
space is smoother / cleaner as the solver sees it - despite the overall 
result.

(Long on my todo list has been trying this kind of pattern enabled 
perturbation with parametric surfaces too. Should work, but...)

2) Bald Eagle posted code using a pigment{} alternative to pattern{} 
wrap. Both wraps are useful depending on needs. However, if what you 
want is the inbuilt pattern's singular value and not a color vector, the 
pattern{} wrap is faster - and more accurate (color vectors internally 
are 32 bit floats).

3) I used yuqk's f_round() inbuilt function here as an alternative to 
mod() to get multiple torus shapes from each FnTorusWarp() use.

4) The large reduction in isosurface gradients due the use of yuqk's 
'raw_wave' pattern modifier hints at a general issue using pattern{} and 
inbuilt patterns with functions. One especially true in the current 
non-yuqk releases of POV-Ray.

The pattern mechanism (and very often the inbuilt pattern specific code 
in alternate ways) clamp and/or wrap values to a 0-1 range for use with 
*maps though it is often not necessary(*). There are several secondary 
issues too at the pattern <-> function interface in the official code. 
It, pretty much, all leads to choppy value fields (high gradients) for 
the isosurface solver.

(*) The *_map code in all recent versions of POV-Ray can handle 
arbitrary pattern return ranges.

Bill P.

// The yuqk fork required for the example code below
//...
#include "functions.inc"
#declare FnTorusWarp = function {
     pattern {
         function {
             f_torus(x,y,z,
                 max(1,min(5,f_round(f_hypot(x,z)))),
             0.04)
         }
         raw_wave // Drives iso gradient improvement of 1903 to 3
         warp {
             it_amount 0.15 it_octaves 3 it_omega 0.8 it_lambda 2.5
             it_scale 1/15
         }
     }
}

#declare FnTorusPlaced = function (x,y,z,X,Y,Z) {
     FnTorusWarp(x-X,y-Y,z-Z)
}

#declare FnTorusTotal = function (x,y,z) { // isosurface function
     min(
         FnTorusPlaced(x,y,z,+2.0,0.0,+2.0),
         FnTorusPlaced(x,y,z,-2.0,0.0,+2.0),
         FnTorusPlaced(x,y,z,+2.0,0.0,-2.0),
         FnTorusPlaced(x,y,z,-2.0,0.0,-2.0)
     )
}
//...
// The final isosurface is scaled by 1/2
//


Post a reply to this message


Attachments:
Download 'larsr_00.png' (293 KB)

Preview of image 'larsr_00.png'
larsr_00.png


 

From: Bald Eagle
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 2 Jun 2025 10:05:00
Message: <web.683daf4a8b738c146b39555b25979125@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:

> 1) A subtle use of pattern{} is to wrap existing functions with it so
> you can use the inbuilt pattern modifiers as part of creating a derived
> function. For example, we can apply isosurface perturbations with
> warp{}s. In the posted image the rough texture comes from the
> application of a warp{} turbulence. A code excerpt is below.

This is actually a great tip!
I personally look for to hearing about more of these types of capabilities.

> As a bonus (especially in yuqk using its raw_wave modifier), the
> approach often leads to much lower isosurface gradients because the
> perturbation is done by the warp{}. The 'nested isosurface evaluation'
> space is smoother / cleaner as the solver sees it - despite the overall
> result.

I have been delving a little deeper into this topic of late, and i have to say
that anyone looking to understand isosurfaces and gradients would be well served
to read Inigo Quilez's articles on min, max, and other functions messing up
Signed Distance Functions (SDFs), since they abruptly change or truncate the
values.
Mike Williams had some excellent advice about calculating the derivative of the
function (if possible) to get an idea about the gradient.

I have also been repeatedly running into the work of Mark Gillespie lately
https://markjgillespie.com/

as well as the Hessian matrix

So my to do list with regard to Continuing Education grows ever longer.

> (Long on my todo list has been trying this kind of pattern enabled
> perturbation with parametric surfaces too. Should work, but...)

I would implore you to look at the parametric code once again should you get the
opportunity.
It seems rather odd that it is so slow, when it should be the easiest to
calculate and render. (Especially when we can render it faster in SDL using the
"approximation" macros.
Isosurfaces require searching the whole contained_by container at the level of
the user-defined accuracy and estimating where the roots of the functions equal
the threshold.
Parametrics by their very nature allow the exact calculation of where the
surface is!

> 2) Bald Eagle posted code using a pigment{} alternative to pattern{}
> wrap. Both wraps are useful depending on needs. However, if what you
> want is the inbuilt pattern's singular value and not a color vector, the
> pattern{} wrap is faster - and more accurate (color vectors internally
> are 32 bit floats).

I did it that way as more of a didactic exercise, since people seem to more
familiar with the color map method of doing things.   Plus it explicitly shows
the 0 and 1 values returned by the color map and allows the user to follow along
at home by experimenting with different color map values.  It's also not
"hidden" under the hood like the pattern keyword method, so I thought there
would be less confusion by omission doing it the color map way.

> 3) I used yuqk's f_round() inbuilt function here as an alternative to
> mod() to get multiple torus shapes from each FnTorusWarp() use.

The more I experiment with patterns in POV-Ray, the more I'm convinced that I
could eventually write an entire 'nother monograph on modular arithmetic and
different versions of the modulo function that handle values in slightly
different but significant ways.


> The pattern mechanism (and very often the inbuilt pattern specific code
> in alternate ways) clamp and/or wrap values to a 0-1 range for use with
> *maps though it is often not necessary(*). There are several secondary
> issues too at the pattern <-> function interface in the official code.
> It, pretty much, all leads to choppy value fields (high gradients) for
> the isosurface solver.

While trying to craft some illustrations for some new isosurface documentation,
I was annoyed by constantly having to grapple with value wrapping with an
endless list of one-off solutions / work-arounds.

Then, as usual, I got a Crazy Idea about a general solution, where we never have
to worry about what the domain of the function results are ever again.  It's
completely reversible too.

I spent the better part of my day Saturday working out a method for reliably
mapping -inf to +inf onto the 0 to 1 domain.
Works like a charm.
The distribution of the raw conversion values sucks, but that was what the rest
of the day was spent fiddling with.
I spent a lot of time relearning what I did with the Importance Sampling code
that I wrote, and then pursued another route that finally gave me an even,
regular spread of values from 0 to 1.

All of the above would be a valuable addition to our value-handling toolbox.

> (*) The *_map code in all recent versions of POV-Ray can handle
> arbitrary pattern return ranges.

Huh?

Whatchoo talkin' 'bout, Willis.  ?

- BW


Post a reply to this message

From: William F Pokorny
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 3 Jun 2025 07:20:04
Message: <683eda64$1@news.povray.org>
On 6/2/25 10:03, Bald Eagle wrote:
>> (*) The *_map code in all recent versions of POV-Ray can handle
>> arbitrary pattern return ranges.
> Huh?

I mean the *_map mechanism itself has long supported -inf to +inf index 
ranges. It is the 'pattern modifier' code in front of it which does not 
- in official releases of POV-Ray (*).

The yuqk fork has 'function_interval' which supports a -1 to 1 range 
along with all the other existing pattern modifiers; plus 'raw_wave' 
which bypasses the 'pattern modifier' code altogether'.

// yuqk is required for raw_wave
#version 3.8;
global_settings { assumed_gamma 1.0 }

#declare ElectricBlue = srgb <0.4902,0.97647,1>;
#declare ElectricBrown = srgb <0.7098,0.38431,0.34118>;
#declare ElectricCrimson = srgb <1,0,0.24706>;
#declare ElectricCyan = srgb <0,1,1>;
#declare ElectricGreen = srgb <0,1,0>;
#declare ElectricIndigo = srgb <0.43529,0,1>;
#declare ElectricLavender = srgb <0.95686,0.73333,1>;
#declare ElectricLime = srgb <0.8,1,0>;
#declare ElectricOrange = srgb <1,0.20784,0.01176>;

sky_sphere {
     pigment {
         function { +1/0 }
         raw_wave
         color_map {
             [val("-inf") ElectricBlue]
             [-9.0        ElectricLime]
             [-6.0        ElectricIndigo]
             [-3.0        ElectricCyan]
             [+0.0        ElectricCrimson]
             [+3.0        ElectricGreen]
             [+6.0        ElectricLavender]
             [+9.0        ElectricOrange]
             [val("+inf") ElectricBrown]
         }
     }
}
//---


It happens I was looking at the parametric code back in late March / 
early April at first with respect to updating my documentation with 
respect to the gradients used, but as I looked at the code I was both 
reminded of bugs/limitations and I managed to find a few more playing 
around. I'd also like the surface to be UV map-able in some standard 
way. I put the work back into my head to let things rattle around for a 
while more.

Jerome implemented the only fast, general way I know to get performance 
in a release of hgpovray38 (**). He implemented a feature that turns the 
parametric equations into a mesh prior to ray tracing - which can be 
done somewhat easily though much more slowly in today's SDL as well. And 
there are external packages for working with parametric equations too 
(with mesh output) though I've not played with any of those in years.

Bill P.

(*) - Lying a little. The potential pattern in official v3.8 implements 
'raw_wave' in a completely internal way for just that feature.

(**) - Lying a little more. Five or more years ago I created three image 
files I used directly as a kind of tri-cache, via functions as the 
parametric inputs. It worked as a speed improvement and kinda / sortof 
worked as an ugly result. The up front limitation was having no really 
deep bit depth image format. A 32 bit float format is available in the 
yuqk fork's function created color image feature as of ... sometime in 
the last year IIRC. Not gotten back to playing with parametric caching 
by image based functions using that improved bit-depth yuqk feature.

The mesh and uv range caching, of course, are always approximating the 
parametric with respect to a good double float calculated result.

Bill P.


Post a reply to this message

From: Kenneth
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 4 Jun 2025 07:25:00
Message: <web.684029a98b738c14e83955656e066e29@news.povray.org>
[Running v3.8 beta 1 in Windows]

I simplified your 'FnTorusWarp' function to be just a basic torus, so that I
could run it for experimenting.

I am seeing some odd isosurface behavior when the torus function is turned into
a pattern (regardless of the additional warp.)  It seems that the contained_by
object-- a sphere for example-- cannot be larger than a radius of 1.0.
Otherwise, an inverted(?) version  of the torus begins to appear, outside of the
initial object. And POV-ray actually crashed several times which is difficult to
reproduce, depending on... ?

An isosurface made from  POV-ray's basic torus function itself does not produce
these anomalies.

(As an experiment, I substituted a different basic function shape for the torus,
using f_comma instead, just to see if this behavior still occurs. It does.)

With the torus pattern, an interplay of various values causes the 'outside
parts' to appear: It depends on the major and minor radii values (and the ratio
between the two), and *especially* the isosurface contained_by size. And when
the odd parts begin to come in, the isosurface's required max_gradient wildly
increases. (Although, adding triangle_wave to the function pattern *greatly*
reduces this-- from 2000 down to 2!-- which seems to produce a similar effect to
your 'raw' wave type. A nice discovery!)

I tried various ways of re-writing my isosurface code block to eliminate the
'extra parts', but without success: negating the function; subtracting the
function from 1.0; negating the threshold value; using 'open';  using v3.8's
'polarity' keyword.

Do you have an idea as to what causes this function-to-pattern behavior?
-----------------
BTW: For the pattern use, the iso threshold value is a tricky one. It cannot be
zero (as far as I can tell), but increasing it increases the torus's minor
radius without affecting the major radius. So it does not seem possible to get
an exact-size torus that matches the given minor radius.

-----------------
My simplified test code. The two examples use the same torus size and
contained_by size (the latter of which is purposely bad for the
torus-as-pattern).

#include "functions.inc";

// 1)  torus function as pattern function:
#declare FnTorusWarp = function {
     pattern {
         function {f_torus(x,y,z,0.5,0.1)}
                    }
             // triangle_wave
}

isosurface{
     function{FnTorusWarp(x,y,z)}
     threshold .01 // This is a tricky value:
     accuracy .001
     max_gradient 2000
     //polarity on

     // The contained_by shape cannot go beyond a critical size, otherwise extra
     // parts appear. Reduce to 0.9 to get a clean torus-- which also results in
     // a *much*-reduced max_gradient.
     contained_by{sphere{0,1.4}}
     // OR...
     //contained_by{box{-1.4,1.4}}

     //open
 }

// 2)  a basic torus, no pattern use:

isosurface{
 function{f_torus(x,y,z,0.5,0.1)}
 threshold 0
 accuracy .001
 max_gradient 2
 contained_by{sphere{0,1.4}}
 }


Post a reply to this message


Attachments:
Download 'function_vs_pattern_function_1_kw.jpg' (42 KB)

Preview of image 'function_vs_pattern_function_1_kw.jpg'
function_vs_pattern_function_1_kw.jpg


 

From: Bald Eagle
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 4 Jun 2025 09:50:00
Message: <web.68404e568b738c148becbc4525979125@news.povray.org>
Hi Ken,

"Kenneth" <kdw### [at] gmailcom> wrote:
> It seems that the contained_by
> object-- a sphere for example-- cannot be larger than a radius of 1.0.
> Otherwise, an inverted(?) version  of the torus begins to appear, outside of the
> initial object.

Do keep in mind that f_torus is a continuous function "extending outwards" from
the origin infinitely.  To put it better, f_torus operates on any <x, y, z>
point fed to it, and so you may get values returned that equal the threshold
value that you set, in places where you might not expect them if you're just
thinking about f_torus as an "object", which it's not.

And POV-ray actually crashed several times which is difficult to
> reproduce, depending on... ?

Yeah, that's weird and concerning.
We have many phantoms lurking in the code.

> An isosurface made from  POV-ray's basic torus function itself does not produce
> these anomalies.
>
> (As an experiment, I substituted a different basic function shape for the torus,
> using f_comma instead, just to see if this behavior still occurs. It does.)

So that seems to indicate that the problem lies with the pattern {} wrapper.

> With the torus pattern, an interplay of various values causes the 'outside
> parts' to appear: It depends on the major and minor radii values (and the ratio
> between the two), and *especially* the isosurface contained_by size. And when
> the odd parts begin to come in, the isosurface's required max_gradient wildly
> increases.

In my extensive playing with isosurfaces, I have observed that seemingly
innocent changes can have crippling effects on the gradient and render speed.

I think in some of my explorations, I'm using bad equation results/threshold
values, and that sets up the solver for failure.  The solver has to zig-zag back
and forth along the curve, and how it does that depends greatly on the
user-defined starting point.

IIRC, I recently saw some papers on new methods of solving for roots which don't
suffer from these limitations.

>
> I tried various ways of re-writing my isosurface code block to eliminate the
> 'extra parts', but without success: negating the function; subtracting the
> function from 1.0; negating the threshold value; using 'open';  using v3.8's
> 'polarity' keyword.
>
> Do you have an idea as to what causes this function-to-pattern behavior?
> -----------------
> BTW: For the pattern use, the iso threshold value is a tricky one. It cannot be
> zero (as far as I can tell), but increasing it increases the torus's minor
> radius without affecting the major radius. So it does not seem possible to get
> an exact-size torus that matches the given minor radius.

I would first try comparing the pattern {} method to the color_map method.
Then I would render the functions as a pigment {function}} on a plane, so see
how the values behave outside of the little 1-unit box

Under the hood, (povray/source/vm/fnintern.cpp)

the torus equation is:

DBL f_torus(FPUContext *ctx, DBL *ptr, unsigned int) // 70
{
    PARAM_X = sqrt(PARAM_X * PARAM_X + PARAM_Z * PARAM_Z) - PARAM(0);

    return -PARAM(1) + sqrt(PARAM_X * PARAM_X + PARAM_Y * PARAM_Y);
}

in SDL, you invoke that with f_torus(x, y, z, major, minor)

so your minor radius is baked into your function result _as the surface where
the threshold is zero_

But since it's and ISOsurface, you have different levels - different thresholds
- and therefore different places in space where the surface gets rendered when
you change the threshold value.

If you read Inigo Quilez's articles on making rounded shapes from SDFs, you need
to shrink the shape so that when you set a higher threshold value to expand the
shape and make it rounded, the two things cancel out, and you get a rounded
shape of the desired size.

What happens when you use a threshold of 1 and a BIG box container?
(Use only half the box so that you render a more revealing cross-section)

I don't have my laptop here to test any of this because ... reasons ... so I'm
just speculating as to the underlying factors of what you're seeing, and trying
to give you more of an overhead view, rather than what you're seeing from your
perspective in the middle of the chaos.

If you write a user-defined torus equation from scratch
https://en.wikipedia.org/wiki/Torus#Geometry
and use
function {pattern{function{MyTorus (x, y, z)}}}
do things behave differently?

- BW


Post a reply to this message

From: William F Pokorny
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 4 Jun 2025 14:07:19
Message: <68408b57$1@news.povray.org>
On 6/4/25 07:19, Kenneth wrote:
> (Although, adding triangle_wave to the function pattern*greatly*
> reduces this-- from 2000 down to 2!-- which seems to produce a similar effect to
> your 'raw' wave type. A nice discovery!)

Hi,

For all your questions, you are running into the pattern{} / pigment{} 
wrap issues I was alluding to in (4) of my response to BE/BW. I don't 
have the energy for an exhaustive guess at causes for each result you 
see. I'm sorry.

Yes! The triangle_wave is another magic bit for gradients which works 
especially well where using yuqk's 'function_interval' (-1 to +1 
wrapping) setting used for lowering the gradients.

In official releases of POV-Ray with the isosurface-adverse, pattern 
mechanism value whacking, it will make the gradient better where all 
values would otherwise be of a 0-1 saw tooth wave aimed at 0-1 *_map 
usage. As you noticed though, the values still never cross 0 to the 
negative/inside of the shape. We have to move to a somewhat positive 
threshold - which generally perverts the specified, inbuilt function's 
shape without detailed value adjustments. Just moving to a slightly 
positive threshold usually gives some result though - which can work 
depending on stuff...

I believe there are no universal solutions for the isosurface issues 
introduced by pattern{} / pigment{} wrapping of otherwise solid 
functions for isosurfaces with the official releases of POV-Ray. It's a 
complicated mess(*). The only general solutions require core code 
changes like those implemented in the yuqk fork.

Bill P.

(*) - Though a work not complete, I should mention too that the yuqk 
fork did a great deal of work to standardize the values returned by the 
inbuilt functions for a threshold of zero while also removing things 
like internal clamping / wrapping.

In other words, the official POV-Ray inbuilt functions tend to be 
one-off mathematical forms difficult (or impossible) to use in general 
ways to build more complicated isosurface functions. Inconsistent 
thresholds, thresholds which are tangled in the definition of the shape 
itself, bugs... That said, one of two inbuilt f_torus* implementations 
survived, pretty much in the form which exists in official POV-Ray - IIRC.


Post a reply to this message

From: Kenneth
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 5 Jun 2025 20:25:00
Message: <web.684233698b738c14e83955656e066e29@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:
>
> [Running v3.8 beta 1 in Windows]
>
> I simplified your 'FnTorusWarp' function to be just a basic torus, so that I
> could run it for experimenting.
>
> I am seeing some odd isosurface behavior when the torus function is
> turned into a pattern...

Hey, I think I solved these problems-- by using min (...). Although, I honestly
don't know *why* it works.

So far, all of my isosurface tests look OK, no 'extra parts' show up. And the
torus object can now be any size, with a larger contained_by object. (There is
still the thorny issue of POV-ray crashing now and then; in 15 of my latest test
renders, it crashed once. No idea why.)

The two arguments of min can be actually be swapped, for the same effect.

#declare FnTorusWarp = function {
     pattern {
         function {
             min(f_torus(x,y,z, 8.0,2.5),
             .95 // part of min-- this can actually be anything *between* 0 and
                 // 1.0, it seems. But not >= 1.0.
                ) // end of min
                            }
         scale 2
         warp{ turbulence .5, omega .001 }
         scale 1/2

         triangle_wave
     }
}


isosurface{
 function{FnTorusWarp(x,y,z)}
 threshold .01
 accuracy .001
 max_gradient 5
 contained_by{sphere{0,12}}
 }


Post a reply to this message

From: William F Pokorny
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 5 Jun 2025 23:59:55
Message: <684267bb$1@news.povray.org>
On 6/5/25 20:21, Kenneth wrote:
> Hey, I think I solved these problems-- by using min (...).

Ah. Well done. :-) I believe in clamping the maximum value to <1.0 you 
are avoiding the pattern{} clamping / wrapping which otherwise occurs at 
values over >= approximately 1.0.

Where the f_torus() values would normally go to <0.0 at the surface the 
values are probably still getting wrapped to multiple roots. The 
clamping at <1.0 can also lead to complications should you end up 
combining FnTorusWarp() with other functions - including other 
placements of itself, depending of stuff. Lastly, in using the 0.01 
threshold, the surface (in cyan blue in the images) is at a slightly 
different position than the original f_torus() surface would have 
otherwise been.

Lets see... We can use yuqk to get a look at the original FnTorusWarp() 
values in the top row of the attached image using raw_wave over 
triangle_wave. In the middle row I commented raw_wave number 1 and 
uncommented your triangle wave (result matches v3.8 b2 in this case 
too). The bottom row of the image is your result in v3.8 b2 without 
either raw_wave, but the same defined -5 to +5 color_map{} - of which 
only 0-1 portion is used.

All that said, when getting a usable result for whatever the image's 
aims - it's all good, no matter the details! "If it sounds good, it is 
good" :-)

Bill P.

//---
#version 3.8;
#version unofficial 3.8; // yuqk
global_settings { assumed_gamma 1 }

#include "functions.inc"

#declare FnTorusWarp = function {
      pattern {
          function { f_torus(x,y,z, 8.0,2.5) }
        //raw_wave      //Number 1
          triangle_wave
          scale 2
          warp{ turbulence .5 omega .001 }
          scale 1/2
      }
}

plane { -z, 0
     pigment {
         function { FnTorusWarp(x,y,0) }
         raw_wave    // Number 2
         color_map {
         [-5.0  rgb <1,0,0>]
         [-1e-2 rgb <0,0,0>]
         [+1e-2 rgb <0,1,1>]
         [+2e-2 rgb <0,1,1>]
         [+3e-2 rgb <0,0,0>]
         [+5.0  rgb <0,1,0>]
         }
     }
     finish { emission 1 }
}
#declare Cam = camera {}
camera { Cam translate -20*z}
//---


Post a reply to this message


Attachments:
Download 'kennethtorusstory.png' (321 KB)

Preview of image 'kennethtorusstory.png'
kennethtorusstory.png


 

From: William F Pokorny
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 6 Jun 2025 09:57:46
Message: <6842f3da$1@news.povray.org>
On 6/5/25 20:21, Kenneth wrote:
> warp{ turbulence .5, omega .001 }

It just popped into my head I forgot to add a comment on the code above 
in my prior post.

What you've coded is OK for a result, but given the omega value is so 
small all the steps (octaves) of the brownian motion are meaningless 
after the first step (2nd step value is already down to 0.0005).

The octaves default is 6 and this means steps beyond 2 (the effective 
minimum) are just burning CPU time. Coding instead:

warp { turbulence .5 octaves 2 omega .001 }

is about 24% faster in a quick test just now using overkill AA to better 
seen the performance change against the total CPU bill for a complete 
render. FWIW.

Bill P.


Post a reply to this message

From: Kenneth
Subject: Re: A doodle and ramblings on pattern{} and iso perturbation
Date: 6 Jun 2025 22:30:00
Message: <web.6843a2f08b738c14e83955656e066e29@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:

>
> The octaves default is 6 and this means steps beyond 2 (the effective
> minimum) are just burning CPU time. Coding instead:
>
> warp { turbulence .5 octaves 2 omega .001 }
>

Thanks for the tip! I've been using warp turbulence since...ages ago, and I
never knew this. Excellent.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.