Oxygen Basic
		Programming => Example Code => Topic started by: Peter on January 21, 2014, 01:23:31 PM
		
			
			- 
				Deleted
			
- 
				
 Some hardcore for the Mandelbrot algorithm: using the fpu stack to hold temp variables.
 
 include "sw.inc"
 Window 800,600,1
 
 single x,y,zx,zy,cx,cy,tp, sys im=570,z=150,it
 h = GetHeight
 w = GetWidth
 single iz=1/z
 single four=4.0
 For y=0 to <h
 For x=0 to <w
 zx=0
 zy=0
 cx= (x-400)*iz
 cy= (y-300)*iz
 it = im
 (
 '
 'While zx * zx + zy * zy < 4 && it>0
 '
 fld dword zx : fmul st0 : fld dword zy : fmul st0
 'leave zy zx squares on fstack for later use
 fld st0 : fadd st2 'sum squares
 fld dword four
 fcomip : fstp st0 'compare and pop
 (
 ja exit
 fstp st0 'dispose zy
 fstp st0 'dispose zx
 exit 2 'exit main loop
 )
 '
 'tp = zx * zx - zy * zy + cx
 '
 'zy zx squares on fstack
 fchs : faddp st1 : fadd dword cx
 'tp on fstack
 '
 'zy = 2 * zx * zy + cy
 '
 fld1 : fadd st0 '2.0
 fmul dword zx : fmul dword zy : fadd dword cy
 fstp dword zy
 '
 'zx = tp
 '
 fstp dword zx 'pop tp from fstack
 '
 'it -=1
 '
 dec it
 jg repeat
 '
 'Wend
 '
 )
 SetPixel x,y, RGB it*12,it*8,it*4
 Next
 Next
 
 Waitkey
 CloseWindow
 
- 
				Here is my effort, using the SIMD registers.
 
 But first the algorithim is rearranged, for more direct translation:
 
 	do 
 zxx=zx*zx
 zyy=zy*zy
 if zxx+zyy>=4.0 then exit do
 zy = 2 * zx * zy + cy
 zx = zxx - zyy + cx
 if --it<1 then exit do
 end do
 
 Then, step by step, the lines are transformed into SIMD instructions.
 
 (if yout PC is an old banger (pre-2005), it may not have the SSE3  instruction set containing HADDPS and HSUBPS )
 
 include "sw.inc"
 include "gl.inc"
 '! glFlush Lib "opengl32.dll" ()
 
 hwnd = Window 800,600,1
 Init2D (hwnd)
 
 single x, y, zz[16]
 sys im=570, z=150, it, stop
 h = GetHeight
 w = GetWidth
 float iz=1/z
 float xx,yy
 indexbase 0
 
 zz[4]=4.0
 For y=0 to <h
 For x=0 to <w
 zz[8]= (x-400)*iz
 zz[9]= (y-300)*iz
 movups xmm3,zz[4]   '4.0
 movups xmm4,zz[8]   'cx,cy
 xorps    xmm0,xmm0  'zero zx,zy
 mov ecx ,im         'down counter
 def swap 0b11100001 'shuffle-order to swap lower 2 elements
 (
 movups   xmm1,xmm0
 mulps    xmm1,xmm1      'squares
 movups   xmm2,xmm1      '
 haddps   xmm2,xmm2      'squares sum
 comiss   xmm2,xmm3      'compare with 4.0
 jae exit                'exit if value >= 4.0
 movups   xmm2,xmm1      '
 hsubps   xmm2,xmm2      'squares difference
 addss    xmm2,xmm4      'singular add cx for new zx
 '
 movups   xmm1,xmm0      'to compute new zy
 shufps   xmm1,xmm1,swap 'swap zx,zy position
 addss    xmm1,xmm1      'singular 2*zy 'zy+zy
 mulss    xmm1,xmm0      'singular *zx
 movups   xmm5,xmm4      '
 shufps   xmm5,xmm5,swap 'swap cx,cy position
 addss    xmm1,xmm5      'singular add cy
 unpcklps xmm2,xmm1      'pair new zx,zy (by interleaving)
 movups   xmm0,xmm2      'transfer new zx,zy
 dec ecx
 jg repeat
 )
 mov it,ecx 'iter count
 DrawPixel x,y, 1, it*12,it*8,it*4,255
 Next
 Next
 
 SwapBuffer
 
 While KeyDown(27)=0
 DoEvents
 Flush
 Wend
 Quit2D
 CloseWindow
 
- 
				I always create a texture with the pixels, then bind the texture to a quad surface. The scene has to be rebuilt every time the window is altered in some way. But, with the texture preloaded, most of the action is in the graphics card.
 
 Not sure how best to handle animation strips though. The ideal texture is a square 2^n pixels, but I think this constraint no longer applies.
 
- 
				You can rebuild the scene whenever a WM_MOVE or WM_SIZE message is received.
 Also receive the WM_ERASEBKGND message but do nothing (return 0)
 
 This is the WndProc from OpengleSceneFrame.inc. I rarely need to alter this code: it is intended for moveable and resizeable windows.
 
   function WndProc(sys hwnd, uMsg, wParam, lParam) as sys callback
 ================================================================
 '
 static sys hDC,hRC
 
 select umsg
 '
 case WM_CHAR        : lastchar=wparam
 case WM_MOUSEMOVE   : mposx=LoWord[lparam] : mposy=HiWord[lparam] : act=1
 case WM_LBUTTONDOWN : bleft=1 : sposx=LoWord[lparam] : sposy=HiWord[lparam] : act=1
 case WM_LBUTTONUP   : bleft=0
 case WM_RBUTTONDOWN : bright=1 : act=1
 case WM_RBUTTONUP   : bright=0
 case WM_KEYUP       : key[wparam]=0
 case WM_TIMER       : act=1
 case WM_MOVE        : act=2
 case WM_SIZE        : act=3
 case WM_ERASEBKGND  :
 case WM_CLOSE       : DestroyWindow hwnd
 '
 case WM_KEYDOWN
 select case wparam
 keydown 'macro
 'default cases
 case 27 : SendMessage hwnd, WM_DESTROY, 0, 0
 case 32 : if key[32]=0 then pause=1-pause 'toggle
 end select
 lastkey=wparam
 key[wparam]=1
 '
 case WM_CREATE
 '
 'SETUP DEVICE CONTEXT AND RENDER CONTEXT
 '
 hDC=GetDC hwnd
 SelectPixelformat hDC,1
 hRC = wglCreateContext hDC
 wglMakeCurrent hDC, hRC
 ! Initialize(sys hWnd) : Initialize hWnd
 SetWindowText hwnd,title
 #ifdef fontA
 BuildFont hWnd, hDC, hRC,fontA,1000
 #endif
 
 act=2
 '
 case WM_DESTROY
 '
 ! Release(sys hWnd) : Release hWnd
 #ifdef fontA
 glDeleteLists 1000, 255
 #endif
 wglMakeCurrent hDC, NULL
 wglDeleteContext hRC
 ReleaseDC hWnd,hDC
 PostQuitMessage 0
 return 0
 '
 case else
 '
 return DefWindowProc(hwnd, uMsg, wParam, lParam) 'unprocessed messages
 '
 end select
 '
 if not act then exit function
 '
 'CREATE SCENE FRAME AND SWAP BUFFERS
 '===================================
 '
 '
 if act=3 then
 '
 'SET THE VIEWPORT AND PERSPECTIVE
 '
 GetClientRect  hwnd,&cRect
 glViewport 0, 0, crect.right, crect.bottom
 aspect=crect.right/crect.bottom
 perspective
 end if 'act=3
 '
 ! scene(sys hwnd) : scene hWnd
 '
 if act
 glfinish
 swapBuffers hdc
 act=0
 end if
 return 0 'done
 '
 end function
 
 PS: Just added WM_MOVE
 
 one trick for static scenes to reduce system load:
 
 'at the end of the scene procedure:
 if bleft 'mouse button
 sleep 10
 elseif act>1 'move or resize
 sleep 10
 else
 sleep 100
 end if
 end sub
 
- 
				Not sure how best to handle animation strips though. The ideal texture is a square 2^n pixels, but I think this constraint no longer applies. The constraint still applies, just most graphics cards and drivers now automatically rescale something to the nearest power of 2.  However, this causes a slight performance hit.  Animation strips would be handled via a texture atlas.
- 
				Okay, That makes sense for texture scaling (with depixelation). The individual strip frames can be patched into the texture square, as a grid.
			
- 
				The individual strip frames can be patched into the texture square, as a grid.
 
 Yeppers.  Just shift the UV coordinates for each frame of animation.
- 
				What I had in mind was to patch frames from Peter's BMP strips, for example, into a square texture, say 4x4 images, then manipulate the U V coordinates, as you say.