The full code. It's ugly and in progress

(but it produce a nice fractal)
Code: Select all
;
; Buddhabrot generator
EnableExplicit
;RunProgram(#PB_Compiler_Home+"\Compilers\pbcompiler.exe", Chr(34)+ "E:\purebasic\buddhabrot3\main.pb" + Chr(34) + " /COMMENTED /SSE2 /EXE " + Chr(34)+ "E:\purebasic\buddhabrot3\buddha3.exe" +Chr(34) , "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
;RunProgram(#PB_Compiler_Home+"\Compilers\pbcompiler.exe", Chr(34)+ "E:\purebasic\buddhabrot3\main.pb" + Chr(34) + " /REASM /SSE2 /EXE " + Chr(34)+ "E:\purebasic\buddhabrot3\buddha3.exe" +Chr(34) , "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Hide)
;Return
Define.q StartTime ;= ElapsedMilliseconds()
StartTime = ElapsedMilliseconds()
#plots = 100000
#RandMax = 2147483647
#RandMaxBy4 = 536870911
; Define constant
Global.u screenSize = 1200
Global.l screenSize2 = screenSize * screenSize
Global.u bailout = 1000
;
Global.u bailoutRmin = 100
Global.u bailoutRmax = 150
;
Global.u bailoutBmin = 100
Global.u bailoutBmax = 500
Global.u bailoutGmin = 400
Global.u bailoutGmax = 1000
;
Global.u miniter = 0
;Global.l plots = 100000
Global.l RandMax = 2147483647
Global.l RandMaxBy4 = 536870911
; Define global var
Global.f maxexposure = 0
Global.f maxexposureR = 0
Global.f maxexposureG = 0
Global.f maxexposureB = 0
Global.q exposures = 0
Global.l performance = 0
Global.i Buffer
Global.i Pitch
Global.i PixelFormat
Global.i refresh = 0
;Define.q screeno
Define.q i
Structure ExposureStruct
R.f
G.f
B.f
A.f
EndStructure
Structure RandomStruct
x.f
y.f
EndStructure
Structure Pixel
Pixel.l
EndStructure
Define *Line.Pixel
Global Dim exposure.ExposureStruct(screenSize2)
;Threaded Dim randomBuffer.RandomStruct(#plots)
; Generate a random number
Procedure.f mrdrand()
Define r.f
Define d.f = 536870911
Define two.f = 2
;r = ((Random(2147483647)/(536870911)) - 2.0)
;ProcedureReturn r
;EnableASM
EnableASM
! RDRAND eax
! MOV dword [p.v_r], eax
! FILD dword [p.v_r]
! FDIV dword [p.v_d]
! FSUB dword [p.v_two]
! FST dword [p.v_d]
! MOV EAX, [p.v_d]
DisableASM
ProcedureReturn
;ProcedureReturn ((Random(2147483647)/(536870911)) - 2.0)
EndProcedure
; Check if point is in Mandelbrot Set
Procedure isInMSet(xi.f, yi.f)
Define.f x ;= 0.0
Define.f y ;= 0.0
Define.f xnew ;= 0.0
Define.f ynew ;= 0.0
Define.u i
Define.f q = (xi-0.25)*(xi-0.25) + (yi*yi)
;Quick rejection check If point is in main cardioid
If( q*(q+(xi-0.25)) < 0.25*(yi*yi))
ProcedureReturn 1
EndIf
;Quick rejection check If point is in 2nd order period bulb
If ( (xi+1.0) * (xi+1.0) + yi*yi < 0.0625)
ProcedureReturn 1
EndIf
;test For the smaller bulb left of the period-2 bulb
If (( ((xi+1.309)*(xi+1.309)) + yi*yi) < 0.00345)
ProcedureReturn 1
EndIf
;check For the smaller bulbs on top And bottom of the cardioid
If ((((xi+0.125)*(xi+0.125)) + (yi-0.744)*(yi-0.744)) < 0.0088)
ProcedureReturn 1
EndIf
If ((((xi+0.125)*(xi+0.125)) + (yi+0.744)*(yi+0.744)) < 0.0088)
ProcedureReturn 1
EndIf
For i = 0 To bailout
xnew = (x*x) - (y*y) + xi
y = 2 * (x*y) + yi
x = xnew
If ((x*x + y*y) > 4) : ProcedureReturn 0 : EndIf
Next i
ProcedureReturn 1
EndProcedure
; Iterate and draw the orbit
Procedure iterate(x0.f, y0.f)
Define.f x = 0.0
Define.f y = 0.0
Define.f xnew ;= 0.0
Define.f ynew ;= 0.0
Define.f ix ;= 0
Define.f iy ;= 0
Define.u i
Define.f originX, originY
Define.f cR, cG, cB
; originX = Int(screenSize * (x0 + 2.25) / 3.5)
; originY = Int(screenSize * (y0 + 1.5) / 3.0)
; cR = originX / (screenSize)
; cB = originY / (screenSize)
; cG = (originX + originY) / (screenSize*2)
;
For i = 0 To bailout
exposures+1
xnew = (x * x) - (y * y) + x0
ynew = 2 * (x*y) + y0
If ((i > miniter))
ix = Int(screenSize * (xnew + 2.25) / 3.5)
iy = Int(screenSize * (ynew + 1.5) / 3.0)
If ((ix >= 0) And (iy >= 0) And (ix < screenSize) And (iy < screenSize))
Define.l pos = ix*screenSize+iy
If ((i < bailoutRmax) And (i > bailoutRmin)) : exposure(pos)\R+1 : EndIf
If ((i < bailoutGmax) And (i > bailoutGmin)) : exposure(pos)\G+1 : EndIf
If ((i < bailoutBmax) And (i > bailoutBmin)) : exposure(pos)\B+1 : EndIf
EndIf
EndIf
If ((xnew*xnew + ynew*ynew) > 4)
ProcedureReturn 1
EndIf
x = xnew
y = ynew
Next i
ProcedureReturn 0
EndProcedure
Procedure iterateThread(Array *exposure.ExposureStruct(1))
Define.f x = 0.0
Define.f y = 0.0
Define.f xnew ;= 0.0
Define.f ynew ;= 0.0
Define.f ix ;= 0
Define.f iy ;= 0
Define.u i
;Define.f originX, originY
;Define.f cR, cG, cB
Repeat
Define.f x0 = mrdrand() ;(Random(#RandMax)/(#RandMaxBy4)) - 2.0
Define.f y0 = mrdrand() ;(Random(#RandMax)/(#RandMaxBy4)) - 2.0
If(isInMSet(x0, y0) = 0)
x = 0.0
y = 0.0
For i = 0 To bailout
exposures+1
xnew = (x * x) - (y * y) + x0
ynew = 2 * (x*y) + y0
If ((i > miniter))
ix = Int(screenSize * (xnew + 2.25) / 3.5)
iy = Int(screenSize * (ynew + 1.5) / 3.0)
If ((xnew*xnew + ynew*ynew) > 4)
Break
EndIf
If ((ix >= 0) And (iy >= 0) And (ix < screenSize) And (iy < screenSize))
Define.l pos = ix*screenSize+iy
Debug i
If ((i < bailoutRmax) And (i > bailoutRmin)) : exposure(pos)\R+1 : EndIf
If ((i < bailoutGmax) And (i > bailoutGmin)) : exposure(pos)\G+1 : EndIf
If ((i < bailoutBmax) And (i > bailoutBmin)) : exposure(pos)\B+1 : EndIf
EndIf
EndIf
x = xnew
y = ynew
Next i
EndIf
ForEver
ProcedureReturn 0
EndProcedure
; Generate a random buffer continuously
Procedure randomGenerator(*Value)
Define k, j
Define *pointeur.randomStruct = *Value
Repeat
*pointeur.randomStruct = *Value
For k = 0 To #plots
*pointeur\x = (Random(#RandMax)/(#RandMaxBy4)) - 2.0;
*pointeur\y = (Random(#RandMax)/(#RandMaxBy4)) - 2.0;
*pointeur + SizeOf(randomStruct)
Next k
ForEver
EndProcedure
; MAIN
; initialize the sprite engine
If InitSprite() = 0
MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
End
EndIf
; open window
If OpenWindow(0, 0, 0, screenSize, screenSize, "Buddhabrot", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, screenSize, screenSize, 0, 0, 0, #PB_Screen_NoSynchronization)
CreateImage(0,screenSize,screenSize,32)
If StartDrawing(ScreenOutput())
Buffer = DrawingBuffer() ; Get the start address of the screen buffer
Pitch = DrawingBufferPitch() ; Get the length (in byte) took by one horizontal line
PixelFormat = DrawingBufferPixelFormat() ; Get the pixel format.
StopDrawing()
EndIf
Else
MessageRequester("Error", "Can't open windowed screen!", 0)
End
EndIf
EndIf
; Local var
Define.i Event
Define.l k
Define.u x
Define.u y
Define.f x0
Define.f y0
Define.f ramp
Define.l rampR
Define.l rampG
Define.l rampB
Define.l pos
;CreateThread(@randomGenerator(), @randomBuffer())
CreateThread(@iterateThread(), exposure())
CreateThread(@iterateThread(), exposure())
CreateThread(@iterateThread(), exposure())
CreateThread(@iterateThread(), exposure())
CreateThread(@iterateThread(), exposure())
CreateThread(@iterateThread(), exposure())
Repeat
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
; FreeMemory(*RandomBuffer)
End
EndSelect
Until Event = 0
; For k = 0 To #plots
; x0 = randomBuffer(k)\x
; y0 = randomBuffer(k)\y
; If(isInMSet(x0,y0) = 0)
; iterate(x0,y0)
; EndIf
; Next k
refresh+1
;If((refresh % 100) = 0)
Delay(1000)
refresh = 0
;findMaxExposure()
For i = 0 To screenSize2
If (exposure(i)\R > maxexposureR) : maxexposureR = exposure(i)\R : EndIf
If (exposure(i)\G > maxexposureG) : maxexposureG = exposure(i)\G : EndIf
If (exposure(i)\B > maxexposureB) : maxexposureB = exposure(i)\B : EndIf
Next i
StartDrawing(ScreenOutput())
For x = 0 To screenSize -1
*Line.Pixel = Buffer+Pitch*x
For y = 0 To screenSize - 1
pos = x*screenSize+y
rampR = exposure(pos)\R / (maxexposureR / 3.0) * 255
rampG = exposure(pos)\G / (maxexposureG / 3.0) * 255
rampB = exposure(pos)\B / (maxexposureB / 3.0) * 255
If (rampR > 255) : rampR = 255 : EndIf
If (rampG > 255) : rampG = 255 : EndIf
If (rampB > 255) : rampB = 255 : EndIf
*Line\Pixel = rampB + (rampG << 8) + (rampR << 16)
*Line+4
Next y
Next x
performance = exposures / (ElapsedMilliseconds() - StartTime)
DrawText(0,0, "(Bailout : " + Str(bailout) + ") (millions of Iterations : " + Str(exposures / 1000000.0) + ") (iterations/ms : " + Str(performance) + ")", RGB(255,255,255))
StopDrawing()
FlipBuffers()
;EndIf
ForEver