Here's a version of the fractal zoomer from R.I.P. Boogop converted to freeBasic/ASM. I'd love to figure out a way around having to iterate over each pixel 300 times because that's where all your performance goes. It drives me nuts. This seems about as optimized as I know how to make it; if you focus optimizing anywhere else but the iteration loop it's a red herring, that loop is the killer. There are ideas around to split the screen in half and render each half in a separate thread, but that's still working around the central problem of the inability to determine if an equation is going to go to infinity without doing it 300 times.
On my work PC (LoMem Kludge-0-Matic 100) I get to the lose-resolution point in about 22 seconds. If you want to go deeper you'll need to tweak horizPosAdjust and vertPosAdjust to position yourself where you want to be
''''''''''''''''''''''''''''''''''''''''''''''''''
' MANDELBROT ASM ZOOMER TEST
' by boogop
' this may be a little faster than the FB version
' but I'm sure I've done lots of stuff wrong or fb
' is just smarter than I am lol
' Where this loses resolution is about the limit
' of a single data type. Converting to double will
' zoom farther in but also take longer
''''''''''''''''''''''''''''''''''''''''''''''''''
#include "tinyptc_ext.bi"
' 350 x 325 to size it the same as the c# effect
dim shared as integer screenWidth = 320
dim shared as integer screenHeight = 200
const SCR_SIZE as integer = 320*200
dim shared as integer ptr p
dim shared buffer( 0 to SCR_SIZE-1 ) as integer
dim shared as uinteger ptr pntr
dim shared as integer w, h, h2
' initial vals
dim shared as single a1 = -2.5
dim shared as single b1 = -1.5
dim shared as single ax1 = -2.5
dim shared as single ax2 = 1.5
dim shared as single bx1 = -1.5
dim shared as single bx2 = 1.6
dim shared as single bailnum = 2.0
dim shared as single bailGT1 = 1.3
dim shared as single bailLT1 = -1.3
dim shared as single z1, z2, z3, dx, dy, crx, yy, cr, ci', dydx
dim shared as integer k = 0
dim shared as single ww
dim shared as single hh
dim shared as single a1w, b1h
dim shared as single aw
dim shared as single bh
dim shared as single zoom = 1
dim shared as uinteger colSingle(300)
declare sub init
declare sub DrawMandelbrot
declare sub CreateMandelbrot(a1 as single, a2 as single, b1 as single, b2 as single)
declare sub put_pixel(buffer() as integer, byval x as integer, byval y as integer, byval col as integer)
sub init
w = screenWidth
h = screenHeight
h2 = h / 2
' these coords put us in scepter valley
a1 = 153.41801
b1 = h2 - 8.650006
' if you change the size of the window you have to figure out where in the
' mandelbrot set you are - not easy! >:(
dim as single horizPosAdjust = 13.24
dim as single vertPosAdjust = 1.5
a1 = a1 - horizPosAdjust
b1 = b1 - vertPosAdjust
ww = ax2 - ax1
hh = bx2 - bx1
a1w = a1 * ww
b1h = b1 * hh
aw = a1w / w
bh = b1h / h
dim i as integer = 0
' usually the array would be dimensioned to 256 but if we set it to the
' number of iterations we can skip a mod operation
while i < 300
dim as single red = 1 + Cos(i * 3.14 / 128)
dim as single grn = 1 + Cos((i - 85) * 3.14 / 128)
dim as single blu = 1 + Cos((i + 85) * 3.14 / 128)
dim as integer r = int(red * 127) mod 256
dim as integer g = int(grn * 127) mod 256
dim as integer b = int(blu * 127) mod 256
colSingle(i) = rgb(r,g,b)
i = i+1
wend
end sub
sub DrawMandelbrot
zoom = zoom + (zoom * .05)
dim as single d = zoom + zoom
dim as single wax = ww / d
dim as single wah = hh / d
dim as single newleft = aw + ax1 - wax
dim as single newright = aw + ax1 + wax
dim as single newtop = bh + bx1 - wah
dim as single newbottom = bh + bx1 + wah
CreateMandelbrot(newleft, newright, newtop, newbottom)
end sub
sub CreateMandelbrot(a1 as single, a2 as single, b1 as single, b2 as single)
p = @buffer(0)
dim as single dr = (a2 - a1) / w
dim as single di = (b2 - b1) / h
dim as integer j = 0
dim as integer i = 0
dim as single temp, q, a, b
dim as single dx1, dy1
dim as single ptr t
'dim as string key
for j = 1 to h
ci = b1 + j * di
for i = 0 to w-1
cr = a1 + i * dr
dx1 = 0.0
dy1 = 0.0
' PERIOD CHECKING
' if we can tell we're inside the cardiod or period-2 bulb we can skip the iterations.
' period checks make the routine blaze until we're past them but the iteration loop is
' the big problem
crx = cr + 1.0
yy = ci * ci
if ((crx * crx) + yy < .0625) then
' checks for a point inside the period-2 bulb
' but once you're past that it does nothing
*p = 0
goto bail
end if
' check for cardiod bulb
temp = cr - .25
t = @temp
' q = temp * temp + yy
q = (*t) * (*t) + yy
a = q * (q + *t)
b = .25 * yy
if (a < b) then
*p = 0
goto bail
end if
''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''
' SSE ITERATION LOOP
''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''
k = 0
' 32 bit singles are only taking up 1/4 of these registers
asm
mov cx, 0
movss xmm2, [ci]
movss xmm3, [cr]
@starter:
movss xmm0, [dx1]
mulss xmm0, xmm0
movss [z1], xmm0 'z1 = dx1 * dx1
movss xmm1, [dy1]
mulss xmm1, xmm1
movss [z2], xmm1 'z2 = dy1 * dy1
addss xmm0, xmm1 ' z1 + z2
comiss xmm0,[bailnum] ' if z1 + z2 > 2.0
ja @asmdone
inc cx ' handle the iterations counter
cmp cx, 300
je @asmdone
movss xmm0, [dx1]
movss xmm1, [dy1]
mulss xmm0, xmm1 ' dy1 * dx1
addss xmm0, xmm0 ' (dy1 * dx1) + (dy1 * dx1)
addss xmm0, xmm2 ' + ci
movss [dy1],xmm0 'dy1 = (dy1 * dx1) + (dy1 * dx1) + ci
movss xmm0, [z1]
movss xmm1, [z2]
subps xmm0, xmm1 ' z1 - z2
addss xmm0, xmm3 ' + cr
movss [dx1],xmm0 'dx1 = z1 - z2 + cr
jmp @starter
@asmdone:
mov [k],cx
end asm
'''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''
if k = 300 then
*p = 0
else
*p = colSingle(k)
end if
' print k, z3, dx1, dy1
' key = INKEY
' WHILE key = "": key = INKEY: WEND
bail:
p = p + 1
next i
next j
end sub
ptc_setdialog(1,"FullScreen?",0,0)
ptc_open( "tinyPTC Mandelbrot test", screenWidth, screenHeight )
'dim as string key
'print "Press to start"
'WHILE key = "": key = INKEY: WEND
init
dim as single t1,t2
t2 = timer
while inkey() <> chr(27)
t1 = timer
DrawMandelbrot
ptc_update @buffer(0)
print t1 - t2
Wend