Buddhabrot Fractal

(DynAsm and DynC User Submissions)

Moderator: Mike Lobanovsky

Buddhabrot Fractal

Unread postby Mike Lobanovsky » Fri Jan 02, 2015 3:30 am

Hi all,

You can get a nice looking Buddhabrot fractal on your screen in about 7 seconds using a little DynC in your FBSL script. If you have a good modern CPU then you can Resize() the main window to any size with almost no loss of speed.

Note that the actual tint of final picture will vary somewhat from time to time due to the random nature of pixel plotting.

Enjoy! :noel:

Code: Select all
#Option Strict

#Include <Include\Windows.inc>

Type BMPBLOB Align 2 // fake BITMAPINFOHEADER
  %biSize
  %biWidth
  %biHeight
  %biPlanes * 16
  %biBitCount * 16
  $biUnused * 24
End Type

Dim %width, %height
Dim wxmin = -2.0, wxmax = 1.0
Dim wymin = -1.5, wymax = 1.5

StyleRemove(ME, WS_MAXIMIZEBOX BOr WS_MINIMIZEBOX BOr WS_THICKFRAME)
Resize(ME, 0, 0, 500, 500): Center(ME)
Fbsl.GetClientRect(ME, 0, 0, width, height)

Dim bb As BMPBLOB
With bb
  .biSize = LenB(BMPBLOB)
  .biWidth = width
  .biHeight = height
  .biPlanes = 1
  .biBitCount = 32
End With

Dim %pixels, hBmp = CreateDIBSection(NULL, @bb, 0, @pixels, NULL, 0)
Dim hDC = GetDC(ME), memDC = CreateCompatibleDC(NULL)
Dim hOldBmp = SelectObject(memDC, hBmp)

Show(ME)

Randomize
DrawBrot()

Begin Events
  If CBMSG = WM_ERASEBKGND Then
    Return 1
  ElseIf CBMSG = WM_PAINT Then
    BitBlt(hDC, 0, 0, width, height, memDC, 0, 0, SRCCOPY)
    Return 0
  ElseIf CBMSG = WM_CLOSE Then
    DeleteObject(SelectObject(memDC, hOldBmp))
    DeleteDC(memDC)
    ReleaseDC(ME, hDC)
  End If
End Events

Sub DrawBrot()
  Dim cut_r = 1250, cut_g = 250, cut_b = 50
  Dim stop_after = 2500000, draw_every = 50000
 
  Dim %hit_r[width * height]
  Dim %hit_g[width * height]
  Dim %hit_b[width * height]
 
  Dim start_time = GetTickCount()
 
  Dim dx = (wxmax - wxmin) / height
  Dim dy = (wymax - wymin) / width
  Dim %max_r, %max_g, %max_b
  Dim %hits, total_hits
 
  While total_hits < stop_after
    CalcPoint(width, height, dx, dy, @max_r, @hit_r[0], cut_r, @hits)
    CalcPoint(width, height, dx, dy, @max_g, @hit_g[0], cut_g, @hits)
    CalcPoint(width, height, dx, dy, @max_b, @hit_b[0], cut_b, @hits)
   
    If hits >= draw_every Then
      total_hits = total_hits + hits: hits = 0
      SelectObject(memDC, hOldBmp)
      DisplayBrot(width, height, max_r, max_g, max_b, @hit_r[0], @hit_g[0], @hit_b[0], pixels)
      SelectObject(memDC, hBmp)
      BitBlt(hDC, 0, 0, width, height, memDC, 0, 0, SRCCOPY)
      FbslSetText(ME, (GetTickCount() - start_time) / 1000 & " sec, " & total_hits & " hits")
      DoEvents
    End If
  WEnd
End Sub

DynC CalcPoint(%wid, %hgt, !!dx, !!dy, %max_hits_ptr, %hits_arr_ptr, %cutoff, %num_hits_ptr)
 
  void main(int wid, int hgt, double dx, double dy, int* max_hits, int hits[], int cutoff, int* num_hits)
  {
    double ESCAPING = 4.0;
    double Wxmin = -2.0, Wxmax = 1.0, Wymin = -1.5, Wymax = 1.5;
   
    double cx = Wxmin + (rand() / 32767.) * (Wxmax - Wxmin);
    double cy = Wymin + (rand() / 32767.) * (Wymax - Wymin);
   
    double x = cx, y = cy;
    double xx = x * x, yy = y * y;
   
    int i, idx;
   
    for (i = 1; i <= cutoff; i++) {
      y = 2 * x * y + cy; x = xx - yy + cx;
      xx = x * x; yy = y * y;
      if (xx + yy >= ESCAPING) break;
    }
   
    if (xx + yy >= ESCAPING) {
      x = cx; y = cy;
      xx = x * x; yy = y * y;
     
      for (i = 1; i <= cutoff; i++) {
        int ix, iy;
        ix = (x - Wxmin) / dx;
        iy = (y - Wymin) / dy;
        if ((ix >= 0) && (ix < hgt) && (iy >= 0) && (iy < wid)) {
          idx = iy * hgt + ix;
          hits[idx] += 1;
          if (*max_hits < hits[idx]) *max_hits = hits[idx];
        }
        else break;
       
        y = 2 * x * y + cy; x = xx - yy + cx;
        xx = x * x; yy = y * y;
        if (xx + yy >= ESCAPING) break;
      }
      *num_hits += 1;
    }
  }
End DynC

DynC DisplayBrot(%wid, %hgt, %max_r, %max_g, %max_b, %hit_r_ptr, %hit_g_ptr, %hit_b_ptr, %pxs_ptr)
 
  void main(int wid, int hgt, int max_r, int max_g, int max_b, int hit_r[], int hit_g[], int hit_b[], int* pixels)
  {
    int x, y, r, g, b, idx;
   
    double scale_r = (255 * 2.5) / max_r;
    double scale_g = (255 * 2.5) / max_g;
    double scale_b = (255 * 2.5) / max_b;
   
    for (y = hgt - 1; y >= 0; y--) {
      for (x = 0; x < wid; x++) {
        idx = x * hgt + y;
        r = hit_r[idx] * scale_r;
        if (r > 255) r = 255;
        g = hit_g[idx] * scale_g;
        if (g > 255) g = 255;
        b = hit_b[idx] * scale_b;
        if (b > 255) b = 255;
        *pixels++ = b | (g << 8) | (r << 16);
      }
    }
  }
End DynC


Buddha.png
Buddha.png (470.94 KiB) Viewed 803 times
Mike
"Я старый солдат, мадам, и не знаю слов любви."
"I am an old soldier, ma'am, and I don't know the words of love."
"Je suis un vieux soldat, madame, et je ne connais pas les mots d'amour."
"Ich bin ein alter Soldat, gnädige Frau, und ich weiß nicht die Worte der Liebe."

__________________________________________________________________________________________________________________________________________________
(3.2GHz i5 Core Quad, 8GB RAM / 2 x nVidia GTX 550Ti SLI-bridged, 2GB VRAM)
(x86 Win XP Pro Russian Sp3/x86 Win Vista Ultimate Sp2/x64 Win 7 Ultimate Sp1/Wine in x64 elementaryOS Luna)
User avatar
Mike Lobanovsky
FBSL Administrator
FBSL Administrator
 
Posts: 1823
Joined: Tue Apr 19, 2005 8:22 am
Location: Republic of Belarus

Return to Assembly- & C-based Projects

Who is online

Users browsing this forum: No registered users and 1 guest

cron