|
|
Some days back, Bald Eagle, privately asked me about a comment in
POV-Ray's source code. One mentioning floor() and the FLOOR() macro. The
comment suggests the latter did some mirroring. After a wrong answer or
two, I now believe FLOOR() was always about performance regardless of
code comments - and so functionally not what the quilted coders expected.
With hexagon the two FLOOR() uses are buying performance. Plus, the
results in that case are identical to floor() due the inputs being
conditioned positive.
With quilted's FLOOR() use - in both implementations - it's harder to
determine what's happening. With it, I think someone was expecting
plus/minus axis mirroring - and not getting it.
I created quilted test cases and reviewed the shipped demo scenes. A
number of other issues popped out. One of which is the 'true normal'
results do not match what our documentation shows for quilted normals.
This led me to allnormals.pov which, IIRC, is used for the normal{}
pattern images in the documentation. The set up is shown below and it's
'wrong' as indicated for normal{ <true normal-pattern> } images(1)):
#declare Agate = normal {pigment_pattern{agate
#WRONG Average = normal {pigment_pattern{average
#declare Boxed = normal {pigment_pattern{boxed
#declare Bozo = normal {pigment_pattern{bozo
#declare Brick = normal {pigment_pattern{brick
#WRONG Bumps = normal {pigment_pattern{bumps
#declare Cells = normal {pigment_pattern{cells
#declare Checker = normal {pigment_pattern{checker
#declare Crackle = normal {pigment_pattern{crackle
#declare Cylindrical = normal {pigment_pattern{cylindrical
#WRONG Dents = normal {pigment_pattern{dents
#declare Mandel = normal {pigment_pattern{mandel
#declare Julia = normal {pigment_pattern{julia
#declare Facets = normal {facets
#declare Function = normal {pigment_pattern{function
#declare Gradient = normal {pigment_pattern{gradient
#declare Granite = normal {pigment_pattern{granite
#declare Hexagon = normal {pigment_pattern{hexagon
#declare Image_pattern = normal {pigment_pattern{image_pattern
#declare Leopard = normal {pigment_pattern{leopard
#declare Marble = normal {pigment_pattern{marble
#declare Onion = normal {pigment_pattern{onion
#declare Planar = normal {pigment_pattern{planar
#WRONG Quilted = normal {pigment_pattern{quilted
#declare Radial = normal {pigment_pattern{radial
#WRONG Ripples = normal {pigment_pattern{ripples
#declare Spherical = normal {pigment_pattern{spherical
#declare Spiral1 = normal {pigment_pattern{spiral1
#declare Spiral2 = normal {pigment_pattern{spiral2
#declare Spotted = normal {pigment_pattern{spotted
#WRONG Waves = normal {pigment_pattern{waves
#declare Wood = normal {pigment_pattern{wood
#WRONG Wrinkles = normal {pigment_pattern{wrinkles
Why is allnormals.pov not showing the normal{} version of the pattern
when there is one? (Excepting facets as there's no 'value for map'
version of that pattern.)
The documentation today is confusing with respect to normal{} pattern use.
Where there is a normal specific version of the pattern, we have a
trifecta of possible schemes/results. A 'value for map' pattern result
such as used with a pigment map; A 'value for map' result where sampled
pattern values are used to perturb the surface's normal vector; Lastly,
a normal specific, 'perturbed normal vector' result.
(1) The html generated by allnormals.pov has the statement: "Most of the
patterns, used as a normal." It could, thinly, be argued to be off the
hook by taking pattern to mean the 'value for map' version of perturbed
normals, but...
----
Attached is an image - generated with v3.8 master - showing additional
quilted specific issues.
In the upper left is the 'value for map' pattern surface normal
perturbation. Internally, the map pattern's value is sampled four times
and those samples are used to perturb the shape's surface normal. The
normal block's accuracy setting comes into play here. Beyond that, I've
not worked through what the code is really doing.
In the upper right is today's (v3.7/v3.8) true normal { quilted ... }
result. It shows one of the longstanding issues with the quilted normal
perturbation implementation. Specifically, if the shape's surface
"lands" on any of the texture's axial "floors" during texture
evaluation, you get a noisy result.
The usual fix for that sort of problem is to apply a small positive or
negative epsilon - somewhere - in the system being calculated so such
landings are unlikely in practice. Checker does this internal to the
pattern code. It's that epsilon adjustment I made too small back in
March with povr changes. The quilted's true normal pattern leaves this
epsilon value fudging to users.
In the lower left I shrunk the pattern by a tiny epsilon to nudge the
system off the floor. The noise goes away on the negative x axis. The
the perturbed normal vector also partly inverts! This another
longstanding issue. One which happens over half of each unit interval
along each axis.
In the lower right I expanded the pattern by a tiny epsilon. The noise
is again gone on the -x surface. This time it looks 'quilted.'
Why is the -z face still seeing noise no matter the pattern scaling?
It's because the allnormals.pov template scene translates the shapes +z
by an amount that puts the cube's front face on the 0.0, z, normal
pattern floor during evaluation. To fix this face, one has to adjust
that surface so it lands less unfortunately. The 0.0 position is a
special case that pattern and shape sizing cannot fix.
By sizing a shape by epsilon we can get the perturbed normal polarity
right for only half the cube surfaces at once. Fixing all six requires
sizing, translation and particular placement in the quilted pattern.
Additionally, from other test cases, it looks to me like the quilted
normal has a negative axis bias (no expected FLOOR() mirroring?). The
depth/strength of the perturbed normals is not constant with axially
perpendicular surface position. Non-symmetrical shapes are more
complicated to position well in the pattern.
All said, I believe the normal perturbation quilted code can be tweaked
to eliminate most (all?) of the issues.
There are fewer gotchas in the quilted 'value for map' pattern though
one springs to mind.
The code has long set the quilted's default wave shaping frequency to
0.0(2). I 'suspect' this was to avoid (now old to povr) wave shaping
fudge factor artifacts. Anyway, the point being, the phase modifier
doesn't work by default due this default - and that's not documented.
Further, anyone 'can' set frequency to something other than 0.0 and
phase will suddenly be active again - as will the 0-1 fudge factor
fmod-ing the frequency 0 setting is 'probably' hoping to avoid.
(2) - Yep, there's more that could be said here. This 'Easter egg,' sdl
available mechanism is gone in povr.
I'll add, the 'value map' version of quilted isn't quilted in appearance.
---
For povr, my current plan is to make better the true normal perturbation
quilted code and delete the quilted 'value for map' pattern. Quilted
then to become like facets in normal behavior in having only a normal{}
version. We'll see.
Bill P.
Post a reply to this message
Attachments:
Download 'realnrmlstory.jpg' (147 KB)
Preview of image 'realnrmlstory.jpg'
|
|