home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Shareware 32
/
hot34.iso
/
ficheros
/
DGRAF
/
FRAIN196.ZIP
/
PHCTUTOR.TXT
< prev
next >
Wrap
Text File
|
1997-05-04
|
22KB
|
656 lines
* * * * * * * * * * * * * * * *
* *
* PHC and PTC tutorial *
* *
* v 2.0 *
* *
* May 1997 *
* *
* * * * * * * * * * * * * * * *
1 - PHC Method: Overlaying two fractals ("16-bit PHC")
1-1 - Assignment statements
1-2 - Bailout tests
1-3 - Examples
1-3-1 - Mandel and Julia types
1-3-2 - Mandel and Newton types
2 - First PTC Method: Overlaying three fractals ("24-bit PTC")
3 - Second PTC Method: Overlaying four fractals ("32-bit PTC")
4 - Speed ups
4-1 - Avoid exponentiation...
4-2 - Avoid unnecessary calculations...
4-3 - Use the algebraic rules...
5 - How to write or modify PHC and PTC formulas
6 - Conversion of existing formulas
6-1 - Example 1
6-2 - Example 2
6-3 - Example 3
6-4 - Example 4: bailout tests
7 - Notes about the formula parser
7-1 - Calculation modes
7-2 - What's wrong with 3 * trunc(cr / 3) ?
7-3 - Precedence
8 - Limitations of PHC and PTC
9 - Conclusion
This document is Copyright (c) 1996-1997 by Sylvie Gallet.
I encourage you to copy and distribute it, so long as you leave it
unchanged. It may NOT be used for commercial purposes without my
explicit prior permission.
Any comments, questions, corrections... are welcome.
My addresses are:
CompuServe: Sylvie_Gallet [101324,3444]
Internet: sylvie_gallet@compuserve.com
Pseudo-HiColor (PHC) was co-discovered by Jim Deutch who wrote the
very first PHC formula and Lee Skinner who realized the enormous
possibilities that this technique offers. Given the great interest
aroused by PHC, the Fractint developers decided to implement three
new variables that make formulas much simpler; a big thank you to
Tim Wegner, Jonathan Osuch and George Martin for doing this!
And a MEGA thanks for the IF..ELSE instruction they implemented in
Fractint 19.6. This very powerful instruction considerably improves
the readability of the formulas that use conditional statements and
makes them generally faster.
In this second version of the PHC and PTC tutorial, I have rewritten
both the explanatory material and the formulas to take advantage
of the express branching instructions available now with Fractint 19.6.
Some historical perspective may be helpful. Branching instructions have
evolved from the technique described by Bradley Beacham in his formula
tutorial, to the more direct conditional assignments commonly seen now,
to the new IF..ELSE instructions. PHC formulas originally contained
rather complex calculations to achieve the checkerboard effect required,
but were much simplified when the "whitesq", "scrnpix", and "scrnmax"
predefined variables were added to the formula parser.
Because of these developments, the same PHC formula may be found in
different formula files with much different instructions, depending on
the "state of the art" when the particular version of the formula was
written. I have included samples of formulas written in the previous
style in the accompanying phctutor.frm. This should help the Fractint
user to understand how the old formulas worked and make easier the
conversion of existing formulas written in the prior old formats.
Pseudo-TrueColor (PTC) is an extension of the PHC concept. All the
PHC and PTC formulas included in this document are by the author of
these lines.
Thanks to Lee Skinner and George Martin for their help, suggestions
and encouragements.
1 - PHC Method: Overlaying two fractals ("16-bit PHC")
======================================================
It is possible to combine two fractals (say fractal_0 and fractal_1) in
one image. Imagine that alternate screen pixels form a checkerboard
pattern (represented by 0's and 1's) as follows:
0 1 0 1 0 . .
1 0 1 0 1 . .
0 1 0 1 0 . .
1 0 1 0 1 . .
. . . . . . .
If one fractal is drawn on the "white squares" (the 1's) and the other
on the black squares (the 0's), the separate fractals will be visible,
and at higher screen resolutions you will not be able to see the way the
individual pixels intermesh with the others. The effect is as if the two
fractals were drawn on separate transparent sheets and overlaid.
Fractint v. 19.5 provides a predefined variable "whitesq", which is
automatically set to 1 prior to the calculation of a white square pixel,
and to 0 prior to calculation of a black square pixel. Let's see how to
use this variable in a formula.
1-1 - Assignment statements
-+-+-+-+-+-+-+-+-+-+-+-+-+-
Suppose that fractal_0 and fractal_1 have the following assignment statements:
fractal_0
var = something
fractal_1
var = somethingelse
To overlay the two fractals in PHC fashion, you can use the following
IF..ELSE instruction in a formula:
IF (whitesq == 0) ; "whitesq == 0" is TRUE
var = something
ELSE ; "whitesq == 0" is FALSE
var = somethingelse
ENDIF
or, even more simple:
IF (whitesq) ; "whitesq == 1" is TRUE
var = somethingelse
ELSE ; "whitesq == 1" is FALSE
var = something
ENDIF
1-2 - Bailout tests
-+-+-+-+-+-+-+-+-+-
Suppose that fractal_0 and fractal_1 use the bailout tests bailout_0 and
bailout_1. What will be the PHC bailout test?
Remember that if the answer of a bailout test is "TRUE" (the real portion
of the complex number is nonzero), the loop must be performed again;
otherwise, it is time to quit iterating.
The bailout test of the PHC formula must be the translation in the parser
language of the following rule:
PHC_bailout is TRUE only in two cases:
when (whitesq == 0) and (bailout_0 == TRUE)
or
when (whitesq == 1) and (bailout_1 == TRUE)
Under Fractint 19.6, this expression becomes:
--------------------------------------------
IF (whitesq)
PHC_bailout = bailout_1
ELSE
PHC_bailout = bailout_0
ENDIF
PHC_bailout
You'll notice that the IF block is followed by the name of a variable.
Omitting the last line will produce an error message from Fractint.
1-3 - Examples
-+-+-+-+-+-+-+
1-3-1 - Mandel and Julia types
------------------------------
This is the easiest case: both fractal use the same iteration instruction
and the same bailout test.
mandel { ; Mandel set of z^2 + c
z = c = pixel :
z = z*z + c
|z| <= 4
}
julia { ; Julia set of z^2 + (-0.75,0.1234)
z = pixel , c = (-0.75,0.1234) :
z = z*z + c
|z| <= 4
}
Since the only difference is the initial value of c, the PHC formula will
use whitesq only in the init section:
phc_mj { ; overlay the Mandel set of z^2 + c with
; the Julia set of z^2 + (-0.75,0.1234)
; Modified for if..else logic, April 1997
z = pixel
IF (whitesq)
c = (-0.75,0.1234)
ELSE
c = pixel
ENDIF
:
z = z*z + c
|z| <= 4
}
1-3-2 - Mandel and Newton types
-------------------------------
Here, except "z = pixel", everything is different.
mandel { ; Mandel set of z^2 + c
z = c = pixel :
z = z*z + c
|z| <= 4
}
newton { ; Julia set of Newton's method applied to z^3 - 1 = 0
z = pixel :
n = z^3 - 1 , d = 3*z^2
z = z - n/d
|n| >= 0.000001
}
The resulting PHC formula is:
phc_mn_A { ; overlay the Mandel set of z^2 + c with the Julia
; set of Newton's method applied to z^3 - 1 = 0
; Modified for if..else logic, April 1997
z = pixel :
IF (whitesq)
n = z^3 - 1 , d = 3*z^2 , z = z - n/d
PHC_bailout = |n| >= 0.000001
ELSE
z = z*z + pixel , PHC_bailout = |z| <= 4
ENDIF
PHC_bailout
}
2 - First PTC Method: Overlaying three fractals ("24-bit PTC")
==============================================================
Overlaying three fractals can be done with the following pattern:
0 1 2 0 1 2 . .
1 2 0 1 2 0 . .
2 0 1 2 0 1 . .
0 1 2 0 1 2 . .
. . . . . . . .
Fractint v. 19.5 provides a predefined variable "scrnpix", which is set
to (column, row) prior to calculation of each pixel. The upper left hand
corner of the screen is (0,0); at resolution 1024x768, the lower right
hand corner is therefore (1023,767).
Here, we'll use scrnpix to assign the value 0, 1 or 2 to a variable r
(as you can see, I choose a very explicit name!).
With col = real(scrnpix) and row = imag(scrnpix), the value of r should
be:
r = (col + row) modulo 3
or, using the parser language:
cr = real(scrnpix) + imag(scrnpix)
r = cr - 3 * trunc(cr / 3)
But this instruction doesn't work (see section 7-2).
The following instruction does work:
r = cr - 3 * trunc(cr / real(3))
Now, let's see an example:
--------------------------
Suppose you want to overlay the three following fractals:
mandel { ; Mandel set of z^2 + c
z = c = pixel :
z = z*z + c
|z| <= 4
}
julia { ; Julia set of z^2 + (-0.75,0.1234)
z = pixel , c = (-0.75,0.1234) :
z = z*z + c
|z| <= 4
}
newton { ; Julia set of Newton's method applied to z^3 - 1 = 0
z = pixel :
n = z^3 - 1 , d = 3*z^2
z = z - n/d
|n| >= 0.000001
}
We can merge them in the following way:
ptc_mjn_A { ; overlay the Mandel set of z^2 + c with the Julia set
; of z^2 + (-0.75,0.1234) and the Julia set of Newton's
; method applied to z^3 - 1 = 0
; Modified for if..else logic, April 1997
cr = real(scrnpix) + imag(scrnpix)
r = cr - 3 * trunc(cr / real(3))
z = pixel
IF (r == 0)
c = pixel
ELSEIF (r == 1)
c = (-0.75,0.1234)
ENDIF
:
IF (r == 2)
n = z^3 - 1 , d = 3*z^2 , z = z - n/d
PTC_bailout = |n| >= 0.000001
ELSE
z = z*z + c
PTC_bailout = |z| <= 4
ENDIF
PTC_bailout
}
3 - Second PTC Method: Overlaying four fractals ("32-bit PTC")
==============================================================
The best dithering is produced by the following pattern:
0 1 2 3 0 1 . .
2 3 0 1 2 3 . .
0 1 2 3 0 1 . .
2 3 0 1 2 3 . .
. . . . . . . .
and r is given by the formula:
r = (col + 2*row) modulo 4
or, using the parser language:
cr = real(scrnpix) + 2 * imag(scrnpix)
r = cr - 4 * trunc(cr / 4)
and r can then be used as in the previous examples, to combine four
fractals in one image.
Here is an example:
-------------------
mand_0 { mand_1 {
z = c = sin(pixel) : z = c = pixel :
z = z*z + c z = z*z + c
|real(z)| <= 4 |z| <= 4
} }
mand_2 { mand_3 {
z = c = 1/pixel : z = c = -pixel :
z = z*z + c z = z*z + c
|imag(z)| <= 4 |real(z)+imag(z)| <= 4
} }
ptc_4m_A { ; overlay four Mandels with different initializations
; and bailout tests
; Isn't it terrific???
; Modified for if..else logic, April 1997
cr = real(scrnpix) + 2 * imag(scrnpix)
r = cr - 4 * trunc(cr / 4)
IF (r == 0)
z = c = sin(pixel)
ELSEIF (r == 1)
z = c = pixel
ELSEIF (r == 2)
z = c = 1/pixel
ELSE
z = c = -pixel
ENDIF
:
z = z*z + c
IF (r == 0)
PTC_bailout = |real(z)| <= 4
ELSEIF (r == 1)
PTC_bailout = |z| <= 4
ELSEIF (r == 2)
PTC_bailout = |imag(z)| <= 4
ELSE
PTC_bailout = |real(z)+imag(z)| <= 4
ENDIF
PTC_bailout
}
4 - Speed ups
=============
The best way to make your formulas run a little faster would be to read or
reread Bradley Beacham's FRMTUTOR.TXT (that'll save me having to plagiarize
his work <g>).
4-1 - Avoid exponentiation...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
In the newton formula, we can replace
n = z^3 - 1 , d = 3*z^2
with
z2 = z*z , n = z2*z - 1 , d = 3*z2
This gives:
newton_B { ; Julia set of Newton's method applied to z^3 - 1 = 0
z = pixel :
z2 = z*z , n = z2*z - 1 , d = 3*z2
z = z - n/d
|n| >= 0.000001
}
4-2 - Avoid unnecessary calculations...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Look at this formula:
mandelvariation {
z = c = pixel:
z = z*z + sin(c) - 0.2
|z| < 4
}
Once you notice that the expression sin(c) - .2 is the same value every
time it is calculated for a pixel (which could be many thousands of times)
you will get in the habit of writing formulas like this one as follows:
mandelvariation {
z = pixel
c = sin(pixel) - 0.2:
z = z*z + c
|z| < 4
}
By moving the constant expression into the initialization section, the
calculation is made only once per pixel.
4-3 - Use the algebraic rules...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
An expression such as
z = (3.5 * a + 3.5 * b) / (10.5 * c)
is reduced to the simpler
z = (a + b) / (3 * c)
While this example seems trivial, cases where such speedups are possible
abound in existing formulas; in more complicated formulas, the algebraic
reductions may not be as obvious.
5 - How to write or modify PHC and PTC formulas
===============================================
As we've seen earlier, the PHC or PTC dithering is based on the value of
a variable initialized by Fractint (whitesq) or in the formula (r).
To write a PHC formula, you just have to use "whitesq" at least once.
A PTC formula will start with these lines:
cr = real(scrnpix) + imag(scrnpix)
r = cr - 3 * trunc(cr / real(3))
or these ones:
cr = real(scrnpix) + 2 * imag(scrnpix)
r = cr - 4 * trunc(cr / 4)
For a good dithering, it's essential to leave the variables "whitesq", "cr"
and "r" intact.
For example, if you change:
r = cr - 3 * trunc(cr / real(3))
to:
r = cr - 3 * trunc(cr / real(3.5))
the values of r will be:
0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, ...
and the result will be quite disappointing. Also, it will be helpful if
you use the templates (including the variable names "r" and "cr") in
exactly the form shown above. This will make it easier to identify and
update formulas using PHC and PTC if future changes to Fractint's formula
parser would make such updating desirable.
6 - Conversion of existing formulas
===================================
The following examples show typical old style PHC statements and their
translation for Fractint 19.6.
6-1 - Example 1
+-+-+-+-+-+-+-+
z = z*z + sin(z)*whitesq + pixel
IF (whitesq)
z = z*z + sin(z) + pixel
ELSE
z = z*z + pixel
ENDIF
6-2 - Example 2
+-+-+-+-+-+-+-+
z = z^(z + whitesq - (whitesq == 0))
IF (whitesq)
z = z^(z + 1)
ELSE
z = z^(z - 1)
ENDIF
6-3 - Example 3
+-+-+-+-+-+-+-+
z = (z*z + pixel)*whitesq + (exp(z) + c)*(whitesq == 0) + p1
IF (whitesq)
z = z*z + pixel + p1
ELSE
z = exp(z) + c + p1
ENDIF
6-4 - Example 4: bailout test
+-+-+-+-+-+-+-++-+-+-+-+-+-+-
The best way to translate a bailout test that uses whitesq is to assign its
value to a variable and to end the formula with this variable.
For example:
(|z| <= 4 && whitesq == 0) || (|n| >= 0.000001 && whitesq)
will read as follow:
IF (whitesq)
PHC_bailout = |n| >= 0.000001
ELSE
PHC_bailout = |z| <= 4
ENDIF
PHC_bailout
Of course, if the iterated section already has an IF block controlled by
whitesq, we can put the "PHC_bailout =" statements in this block as in the
example below:
phc_mn_A { ; overlay the Mandel set of z^2 + c with the Julia
; set of Newton's method applied to z^3 - 1 = 0
z = c = pixel :
n = z^3 - 1 , d = 3*z^2
z = (z*z + c) * (whitesq == 0) + (z - n/d) * whitesq
(|z| <= 4 && whitesq == 0) || (|n| >= 0.000001 && whitesq)
}
phc_mn_A { ; overlay the Mandel set of z^2 + c with the Julia
; set of Newton's method applied to z^3 - 1 = 0
; Modified for if..else logic, April 1997
z = pixel :
IF (whitesq)
n = z^3 - 1 , d = 3*z^2 , z = z - n/d
PHC_bailout = |n| >= 0.000001
ELSE
z = z*z + pixel , PHC_bailout = |z| <= 4
ENDIF
PHC_bailout
}
7 - Notes about the formula parser
==================================
7-1 - Calculation modes
-+-+-+-+-+-+-+-+-+-+-+-
Fractint provides two calculation modes: integer math and floating point
math.
Though it often produces very nice images, integer math has an important
limitation: you can't use numbers greater than 255.999... In integer mode,
when you *think* you're using say 372, Fractint uses 116 (372-256=116).
For this reason, the Fractint developers decided to force the floating
point mode when the formula parser detects the use of one of the predefined
variables "scrnpix", "scrnmax" and "maxit".
7-2 - What's wrong with 3 * trunc(cr / 3) ?
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
When you run a formula in floating point mode, the formula parser uses
some tricks to optimize the code. Trunc(cr / 3) is the victim of one of
these tricks.
The problem is this: trunc(cr/3) is replaced by trunc(cr*(1/3)), but since
1/3 is represented internally as .33333..., cr*(1/3) is slightly less than
cr/3. If cr is a multiple of 3, trunc(cr/3) therefore returns one less
than you would expect. For example trunc(6/3) calculates as
trunc(6*.3333333...) or trunc(1.9999...), which in turn evaluates to 1
instead of the expected result of 2.
Replacing 3 with real(3) circumvents this problem and yields the desired
result.
7-3 - Precedence
-+-+-+-+-+-+-+-+
Precedence is a way to make mathematical expressions more readable by using
less parentheses. For a better comprehension of this section, you might
want to look at the table of precedence in the Fractint documentation.
The following expressions are mathematically equivalent because division and
multiplication have a higher precedence than addition and subtraction (this
means that divisions and multiplications will be performed before additions
and subtraction):
2+(3*((5*3)+(4/5))*(7-5))
2 + 3 * (5*3 + 4/5) * (7 - 5)
(they both evaluate to 96.8)
I must confess that I tend to prefer the second one... (OK, I'm cheating,
I just added a few white spaces... <g>).
Now, let's see another example:
-------------------------------
In this expression:
(|z| <= 4) && (whitesq == 0)
the parentheses mean that the comparisons must be performed before the
logical AND. Comparisons have a higher precedence than logical operators
thus, we can remove the parentheses:
|z| <= 4 && whitesq == 0
However, with
(|z| <= 4 && whitesq == 0) || (|n| >= 0.000001 && whitesq)
Can we remove the parentheses? The answer is: no! Without parentheses,
and since we know that comparisons are performed first, this expression has
the following format:
A && B || C && D
"&&" and "||" have the same precedence and in such a case, the expression
must be calculated from the left to the right. Just look at this:
(1 && 1) || (1 && 0) =
1 || 0 = 1
1 && 1 || 1 && 0 =
1 || 1 && 0 =
1 && 0 = 0
8 - Limitations of PHC and PTC
==============================
With the new variables introduced in Fractint 19.5, PHC and PTC formulas
are now resolution independent and the image can be interrupted, saved and
restored. Panning an even number of pixels for PHC images or multiples of
3 for "24-bit PTC's" and multiples of 4 for "32-bit PTC's is possible
without artifacts.
All PHC and PTC formulas require passes=1.
The use of symmetry in PHC or PTC formulas or par files is not recommended
since symmetry alters the pattern along the axes and results in horizontal
or vertical lines.
9 - Conclusion
==============
That's all for now! I hope you found this text interesting and useful.
I'm planning an update of Bradley Beacham's Formula Tutorial which could
include this text and any subject you'd like to see treated.