POV-Ray : Newsgroups : povray.binaries.images : high resolution height_field functions : Re: high resolution height_field functions Server Time
31 Jul 2024 06:20:21 EDT (-0400)
  Re: high resolution height_field functions  
From: clipka
Date: 17 Mar 2010 14:14:43
Message: <4ba11c13$1@news.povray.org>
Thomas de Groot schrieb:
> "scott" <sco### [at] scottcom> schreef in bericht 
> news:4ba0d4c3@news.povray.org...
>> Same problem, just smaller scale (see attached the "smooth" version).  IME
>> with mesh modellers the appearance indicates incorrectly calculated 
>> normals
>> (this type of pattern certainly shouldn't be visible with triangles the 
>> size
>> of a few pixels).  Anyway, the image seems to get *worse* with more
>> elements, shouldn't it be getting better?
>>
> 
>  I see what you mean. This goes beyond my capabilities. I suppose that the 
> function is generating a kind of mesh-like object, but is that comparable to 
> a *real* mesh I wonder? Time for the experts to have their say :-)

I suspect an aliasing issue with the Y coordinates.

POV-Ray has three limitations applying to this context:

(1) Smooth height fields use precomputed surface normals, which are 
stored with a precision of 3x16 bits. I don't suspect that this has much 
of an influence though, as this still corresponds to a resolution of 
roughly 0.01 degrees, which shouldn't make any visible difference in 
brightness.

(2) The surface normals are not precomputed from the original source, 
but from the Y coordinate data as stored in the height field's internal 
data structure. As this data structure holds the Y coordinate values 
using 16-bit integers, giving a precision of no more than 1/65535, 
terracing effects may occur, which will obviously "kill" the normal 
smoothing algorithm. At a resolution of 10000 by 10000 samples, this 
will happen wherever the slope is less than about 15% (10000/65535).

Worse yet: As the surface normal depends not on the absolute Y 
coordinates, but rather on coordinate differences, the normals' 
precision directly corresponds not on absolute precision of the Y 
coordinates, but on their precision /relative/ to the Y coordinate 
differences. That is, aliasing problems will already kick in much 
earlier; for instance, even at a resolution of just 1000 by 1000 
samples, a slope of 15% would theoretically give "raw" coordinate 
difference values of 9.83025 (65535*0.15/1000), which due to aliasing of 
the absolute Y values will in practice result in raw Y coordinate 
difference values alternating between 9 and 10; at the default height 
field "aspect ratio" of 1:1:1, this translates to Y coordinate 
difference values of approx. 0.000137 and 0.000153 respectively (9/65535 
and 10/65535), which in turn correspond to normal angles of approx. 7.82 
and 8.68 degrees (atan(1000*9/65535) and atan(1000*10/65535)), respectively.

So at a resolution of 1000x1000 samples, the normals on a 15% slope will 
exhibit "quantization noise" with an amplitude of 0.86 degrees, which 
may already cause visible artifacts in highlights (especially since this 
type of artifacts is likely to exhibit a certain banding structure). At 
more shallow slopes, the noise only gets a little bit worse, but it 
doesn't get much better at steeper slopes too soon eithger: At a slope 
of 100% (45 degrees), for instance, the noise is still at approx. 0.437 
degrees.

It appears to me that the noise roughly follows the formula 
0.5*(1+cos(slope_angle*2))*(image_resolution/65535), with the result 
giving the normal jitter in radians. I guess some mathematically 
inclined will even be able to show why that is - I'm not in that mood 
myself right now :-).

(3) The function is not evaluated directly by the height field code, but 
instead first sampled and stored as a function image; for function 
images, a similar limitation applies: Again, these happen to be limited 
to a depth of 16 bit (per channel in case of pigment functions).


As far as workarounds go, I currently know none, except for using a 
totally different primitive; if you don't need a solid, the parametric 
primitive may be the way to go, using f(u,v)=u and f(u,v)=v for the x 
and z coordinates respectively. If you absolutely need a solid, you may 
want to try the isosurface primitive, using f(x,y,z)=y-g(x,z) (with g 
being your own function) and the default threshold of 0. Or you can use 
SDL to create a mesh primitive from the function.


Post a reply to this message

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