Advanced fractal program skills-Chapter 5 to Chapter 8

Source: Internet
Author: User

Advanced fractal program skills-Chapter 5 to Chapter 8

Housisong@gmail.com

Abstract:

This series of articles is an introductory tutorial for fragment programmers. The chapters of this Article include (which may be added or deleted during planning ):
I. A set of Mandelbrot iterations; II. A simple periodic algorithm with smooth color; iii. Color smoothing of the number of iterations and escape interpolation;
4. Use the sin function for color smoothing; 5. A more effective formula for calculating the number of iterations to escape; 6. Use error diffusion to eliminate chromatic aberration;
7. color in the Set; 8. Julia set; 9. interpolation of the complex values generated by iteration;
10. High-order interpolation of the complex values generated by iteration; 11. Enlargement and rotation of the image; 12. Transformation of the plural initial values;
13. Fixed color table; 14. Design Pattern ing; 15. Texture ing; 16. Parallel Computing;
17. More iterative equations and color schemes; 18. Higher Order Mandelbrot sets; 19. Introduction of other fragges and fragment Animation

Body:

(Chapter 5-8 complete project source code: http://cid-10fa89dec380323f.office.live.com/self.aspx/.Public/hssFractal5%5E_8.zip
)
(My other fractal related articles: http://blog.csdn.net/housisong/category/382024.aspx
)

V. A more effective interpolation formula for the number of iterations

I have deduced the interpolation formula for the number of iterations for escape times. Based on the escape threshold m, the current number of iterations I, the relationship between the escape value Zn and the previous zero escape value Zo,
An interpolation formula is obtained:I-(f (| Zn |)-f (| M |)/(f (| Zn |)-f (| Zo | ))
(This formula is highly adaptable and can be used in many different places );
Here, the f (x) function obtains log (ABS (log (x), and when the m value is large (multiple iterations ), then we can get a nearly linear interpolation effect;
It can be proved that this formula can be reduced to the interpolation formula (Special Case) introduced in chapter 3 when m is large enough. Of course, the f (x) function can also take many other functions,
You can also get smooth interpolation results, but the interpolation results may not look linear enough (You may want this effect );
The new interpolation formula Function Code is as follows:
Inline double loglog (const Double X) {<br/> return log (ABS (log (X ))); <br/>}< br/> inline double mandelbrot5 (const double x0, const double y0, const long max_iter) {<br/> const static double M = 256; <br/> const static double lnln_m = loglog (m); <br/> double x_bck = 0; <br/> double y_bck = 0; <br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> for (; I <max_iter; ++ I) {<br/> If (x * x + y * Y> = m) <br/> break; <Br/> x_bck = x; <br/> y_bck = y; <br/> double TMP = x * x-y * Y + x0; <br/> Y = x * y * 2 + y0; <br/> X = TMP; <br/>}< br/> if (I! = Max_iter) {<br/> const double lnln_z = loglog (x * x + y * y ); <br/> const double lnln_zbak = loglog (x_bck * x_bck + y_bck * y_bck); <br/> return I-2-(lnln_Z-lnln_M)/(lnln_Z-lnln_Zbak ); <br/>} else <br/> return I; <br/>}< br/> void draw_mandelbrot5 (const tpixels32ref & DST, const tviewrect & rect, const long max_iter) {<br/> for (long y = 0; y <DST. height; ++ y) {<br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. y0-yr, <br/> double iter = mandelbrot5 (x0, y0, max_iter); <br/> DST. pixels (x, y) = coloring4 (ITER, max_iter); <br/>}< br/>}
The generated image is as follows:

The new interpolation is smoother and better, but in this case it may not be easy to see. When the m value is small (M = 4), you can compare the differences between the two:
Code:

Inline double mandelbrot4_e (const double x0, const double y0, const long max_iter) {<br/> const static double M = 4; <br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> for (; I <max_iter; ++ I) {<br/> If (x * x + y * Y> = m) <br/> break; <br/> double TMP = x * x-y * Y + x0; <br/> Y = x * y * 2 + y0; <br/> X = TMP; <br/>}< br/> if (I! = Max_iter) {<br/> return I + 1-log2 (log2 (x * x + y * y); <br/>} else <br/> return I; <br/>}< br/> void draw_mandelbrot4_e (const tpixels32ref & DST, const tviewrect & rect, const long max_iter) {<br/> for (long y = 0; Y <DST. height; ++ y) {<br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. Y0-yr; <br/> double iter = mandelbrot4_e (x0, y0, max_iter); <br/> DST. pixels (x, y) = coloring4 (ITER, max_iter ); <br/>}< br/> inline double mandelbrot5_e (const double x0, const double y0, const long max_iter) {<br/> const static double M = 4; <br/> const static double lnln_m = loglog (m); <br/> double x_bck = 0; <br/> double y_bck = 0; <br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> (; I <max_iter; ++ I) {<br/> If (x * x + y * Y> = m) <br/> break; <br/> x_bck = X; <br/> y_bck = y; <br/> double TMP = x * x-y * Y + x0; <br/> Y = x * y * 2 + y0; <br/> X = TMP; <br/>}< br/> if (I! = Max_iter) {<br/> const double lnln_z = loglog (x * x + y * y ); <br/> const double lnln_zbak = loglog (x_bck * x_bck + y_bck * y_bck); <br/> return I-(lnln_Z-lnln_M)/(lnln_Z-lnln_Zbak ); <br/>}else <br/> return I; <br/>}< br/> void draw_mandelbrot5_e (const tpixels32ref & DST, const tviewrect & rect, const long max_iter) {<br/> for (long y = 0; y <DST. height; ++ y) {<br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. y0-yr; <br/> double iter = mandelbrot5_e (x0, y0, max_iter); <br/> DST. pixels (x, y) = coloring4 (ITER, max_iter); <br/>}< br/>}

M = 4. Using the interpolation formula in Chapter 3, the error can be seen directly:


M = 4, new interpolation formula (still smooth, but not linear ):


6. Use error diffusion to prevent chromatic aberration

We can see that the color transition of many fragment images is smooth and bright, which is an important factor for many fragment images to become fascinating;
Each color component of our monitor has a brightness of 256. In most cases, it is hard for the eyes to see the color gradient.
Under special circumstances, the generated image may still produce a visible color difference, while the program can actually generate more accurate
The color is lost when it is converted to an integer color. In this case, we can use the error diffusion to process the conversion process;
(For the principle of error diffusion, see my article 3: <Image Processing-> Error Diffusion
Upper, middle, and lower
>
Http://blog.csdn.net/housisong/archive/2008/04/23/2316924.aspx
)

For simplicity, the simplest ** 1 diffusion template I use is the code below:
// Floating point RGB color <br/> struct coldorf {<br/> double r; <br/> double G; <br/> double B; <br/> inline colgrading () {}< br/> inline colgrading (const colgrading & C): R (C. r), g (C. g), B (C. b) {}< br/> inline colgrading (const color32 & C): R (C. R * (1.0/255), g (C. g * (1.0/255), B (C. B * (1.0/255) {}< br/> inline colgrading (const double _ r, const double _ g, const double _ B): R (_ r ), G (_ g), B (_ B) {}< br/> inline void addcolor (const colgrading & C) {r ++ = C. r; G + = C. g; B + = C. B ;}< br/> inline void subcolor (const colgrading & C) {r-= C. r; G-= C. g; B-= C. B ;}< br/> inline void mulcolor (const Double P) {r * = P; G * = P; B * = P ;} <br/> inline static long ftoicolor (const double FC) {<br/> If (FC <= 0) <br/> return 0; <br/> else if (FC> = 1) <br/> return 255; <br/> else <br/> return (long) (FC * 255 + 0.49999 ); <br/>}< br/> inline color32 tocolor32 () const {return color32 (ftoicolor (R), ftoicolor (G), ftoicolor (B ));} <br/>}; <br/> inline double sincoldorf (double ITER) {<br/> return (sin (ITER * 2*3.1415926/510-3.1415926*0.5) + 1) * 0.5; <br/>}< br/> inline color32 coloring6 (const double ITER, const long max_iter, const collf & errorcolorin, collf & errorcolorout) {<br/> collf color = errorcolorin; <br/> If (iter = max_iter) {<br/> color. addcolor (color32 (255, 0, 0); <br/>} else {<br/> color. addcolor (colgrading (sincolgrading (ITER * 20), sincolgrading (ITER * 15 + 85), sincolgrading (ITER * 30 + 171 ))); <br/>}< br/> color32 resultcolor = color. tocolor32 (); <br/> errorcolorout = color; <br/> errorcolorout. subcolor (resultcolor); <br/> return resultcolor; <br/>}< br/> void draw_mandelbrot6 (const tpixels32ref & DST, const tviewrect & rect, const long max_iter) {<br/> for (long y = 0; y <DST. height; ++ y) {<br/> collf errorcolor (, 0); <br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. y0-yr, <br/> double iter = mandelbrot5 (x0, y0, max_iter); <br/> DST. pixels (x, y) = coloring6 (ITER, max_iter, errorcolor, errorcolor); <br/>}< br/>}
The generated image is as follows:
(Many people may not see the difference in their eyes, but the color of this image is too good, and it is difficult for me to create an image in special circumstances so that everyone can see the difference directly)

7. colors inside the set

Previously, we gave a rich color to the areas outside the set to use the number of iterations to escape. The set is simply set to Red. In fact, the set can also be imagined.
Forces give beautiful colors, such as generating colors based on the final complex values of the iteration: (any data generated during the iteration can be used as parameters of the color function)
Inline double mandelbrot7 (double * xlist, double * ylist, const long max_iter) {<br/> const static double M = 256; <br/> const static double lnln_m = loglog (m); <br/> const double & X0 = xlist [0]; <br/> const double & Y0 = ylist [0]; <br/> double x_bck = 0; <br/> double y_bck = 0; <br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> for (; I <max_iter; + + I) {<br/> If (x * x + y * Y> = m) <br/> break; <br/> x_bck = x; <br/> Y_bck = y; <br/> double TMP = x * x-y * Y + x0; <br/> Y = x * y * 2 + y0; <br/> X = TMP; <br/> xlist [I + 1] = x; <br/> ylist [I + 1] = y; <br/>}< br/> if (I! = Max_iter) {<br/> const double lnln_z = loglog (x * x + y * y ); <br/> const double lnln_zbak = loglog (x_bck * x_bck + y_bck * y_bck); <br/> return I-2-(lnln_Z-lnln_M)/(lnln_Z-lnln_Zbak ); <br/>}else <br/> return I; <br/>}< br/> inline color32 coloring7 (const double ITER, const long max_iter, double * xlist, double * ylist, const collf & errorcolorin, collf & errorcolorout, double k = 1) {<br/> collf color = errorcolorin; <br/> If (iter = max_iter) {<br/> const Double X = xlist [max_iter]; <br/> const Double Y = ylist [max_iter]; <br/> double z = SQRT (x * x + y * y ); <br/> double ZD = z-SQRT (xlist [max_iter-1] * xlist [max_iter-1] + ylist [max_iter-1] * ylist [max_iter-1]); <br/> color. addcolor (colgrading (sincolgrading (z * 2000 * K), sincolgrading (Y x * 1000 * K), sincolgrading (ZD * 1000 * k ))); <br/>} else {<br/> color. addcolor (colgrading (sincolgrading (ITER * 20 * K), sincolgrading (ITER * 15 * k + 85), sincolgrading (ITER * 30 * k + 171 ))); <br/>}< br/> color32 resultcolor = color. tocolor32 (); <br/> errorcolorout = color; <br/> errorcolorout. subcolor (resultcolor); <br/> return resultcolor; <br/>}< br/> void draw_mandelbrot7 (const tpixels32ref & DST, const tviewrect & rect, const long max_iter) {<br/> STD: vector <double> xlist; <br/> STD: vector <double> ylist; <br/> xlist. resize (max_iter + 1); <br/> ylist. resize (max_iter + 1); <br/> for (long y = 0; y <DST. height; ++ y) {<br/> collf errorcolor (, 0); <br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. y0-yr; <br/> xlist [0] = x0; <br/> ylist [0] = y0; <br/> double iter = mandelbrot7 (& xlist [0], & ylist [0], max_iter); <br/> DST. pixels (x, y) = coloring7 (ITER, max_iter, & xlist [0], & ylist [0], errorcolor, errorcolor ); <br/>}< br/>}

The generated image is as follows:

8. Julia set

The plural function f (z) = Z ^ 2 + ZM, where ZM (jx0, jy0) is a constant and iterates A z0 point on the plane. After multiple iterations
The post-function value does not spread. A set composed of z0 points is a Julia set. A corresponding Julia set is formed for each specific ZM value;
It can be proved that the Mandelbrot set is a set of ZM parameters that make the Julia set connected.
Rewrite the complex number equation to the corresponding real number equation:
X (I + 1) = x (I) * X (I)-y (I) * Y (I) + jx0; // real part
Y (I + 1) = x (I) * Y (I) * 2 + jy0; // virtual part
Julia iteration function: (and
Mandelbrot
Comparison of iterative Functions
)
Long Julia (const double x0, const double y0, const long max_iter, double jx0, double jy0) {<br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> for (; I <max_iter; ++ I) {<br/> If (x * x + y * Y> = 4) <br/> break; <br/> double TMP = x * x-y * Y + jx0; <br/> Y = x * y * 2 + jy0; <br/> X = TMP; <br/>}< br/> return I; <br/>}
The actual code is as follows:
Inline double julia8 (double * xlist, double * ylist, const long max_iter, double jx0, double jy0) {<br/> const static double M = 256; <br/> const static double lnln_m = loglog (m); <br/> const double & X0 = xlist [0]; <br/> const double & Y0 = ylist [0]; <br/> double x_bck = 0; <br/> double y_bck = 0; <br/> double X = x0; <br/> Double Y = y0; <br/> long I = 0; <br/> for (; I <max_iter; ++ I) {<br/> If (x * x + y * Y> = m) <br/> break; <br /> X_bck = x; <br/> y_bck = y; <br/> double TMP = x * x-y * Y + jx0; <br/> Y = x * y * 2 + jy0; <br/> X = TMP; <br/> xlist [I + 1] = X; <br/> ylist [I + 1] = y; <br/>}< br/> if (I! = Max_iter) {<br/> const double lnln_z = loglog (x * x + y * y ); <br/> const double lnln_zbak = loglog (x_bck * x_bck + y_bck * y_bck); <br/> return I-2-(lnln_Z-lnln_M)/(lnln_Z-lnln_Zbak ); <br/>} else <br/> return I; <br/>}< br/> void draw_julia8 (const tpixels32ref & DST, const tviewrect & rect, const long max_iter, double jx0, double jy0) {<br/> STD: vector <double> xlist; <br/> STD: vector <double> ylist; <br/> xlist. resize (max_iter + 1); <br/> ylist. resize (max_iter + 1); <br/> for (long y = 0; y <DST. height; ++ y) {<br/> collf errorcolor (, 0); <br/> for (long x = 0; x <DST. width; ++ X) {<br/> double X0 = (2 * rect. r) * x/DST. width + rect. x0-rect.r; <br/> double yr = rect. R * DST. height/DST. width; <br/> double Y0 = (2 * yr) * Y/DST. height + rect. y0-yr; <br/> xlist [0] = x0; <br/> ylist [0] = y0; <br/> // double iter = Julia (xlist [0], ylist [0], max_iter, jx0, jy0); <br/> double iter = julia8 (& xlist [0], & ylist [0], max_iter, jx0, jy0 ); <br/> DST. pixels (x, y) = coloring7 (ITER, max_iter, & xlist [0], & ylist [0], errorcolor, errorcolor, 0.5 ); <br/>}< br/>}
Call this function to generate an image. The Code is as follows: (size: 640x480, center point (1.6), r = 1000; Maximum number of iterations)
Const long max_iter = 1000; <br/> tviewrect rect; <br/> rect. x0 = 0; <br/> rect. y0 = 0; <br/> rect. R = 1.6; <br/> tpixels32 dstpic; <br/> dstpic. resizefast (640,480); <br/> draw_julia8 (dstpic. getref (), rect, max_iter, jx0, jy0); <br/>{// save PIC <br/> tfileoutputstream bmpoutstream (dstfilename); tbmpfile: Save (dstpic. getref (), & bmpoutstream); // Save the result graph <br/> piece <br/>}
The generated image is as follows:

(Julia set ZM = (-0.74543, 0.11301 ))

(Julia set ZM = (0.28888, 0.012325 ))

(Julia set ZM = (-0.81442, 0.19633 ))

PS

Upper
Generate nice-looking fragment images
This is the true focus of this series of articles, and this is also the most important motivation for writing fragment programs!
To generate a nice-looking fragment image, I think the main point is the image and color. The image (that is, the image and shape) is a little better, and the appropriate face is given.

Color
More challenging! Sometimes it also requires some luck;
For example, I made some changes to the color generation function of the image of the 3rd Julia set (some will be involved in the following article) and got a new image:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.