Author Topic: White Snowflake  (Read 3304 times)

0 Members and 1 Guest are viewing this topic.

Peter

  • Guest
White Snowflake
« on: January 21, 2014, 01:23:31 PM »
Deleted
« Last Edit: April 25, 2015, 03:14:39 AM by Peter »

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #1 on: January 21, 2014, 10:23:42 PM »

Some hardcore for the Mandelbrot algorithm: using the fpu stack to hold temp variables.

Code: [Select]
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

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #2 on: January 23, 2014, 12:35:23 PM »
Here is my effort, using the SIMD registers.

But first the algorithim is rearranged, for more direct translation:

Code: [Select]
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 )

Code: [Select]
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
« Last Edit: January 23, 2014, 01:03:35 PM by Charles Pegge »

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #3 on: January 23, 2014, 02:09:43 PM »
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.
« Last Edit: January 23, 2014, 02:17:37 PM by Charles Pegge »

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #4 on: January 23, 2014, 03:18:39 PM »
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.

Code: [Select]
  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:

Code: [Select]
'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
« Last Edit: January 23, 2014, 03:41:45 PM by Charles Pegge »

Kuron

  • Guest
Re: White Snowflake
« Reply #5 on: January 23, 2014, 07:32:30 PM »
Quote
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.

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #6 on: January 23, 2014, 10:21:04 PM »
Okay, That makes sense for texture scaling (with depixelation). The individual strip frames can be patched into the texture square, as a grid.

Kuron

  • Guest
Re: White Snowflake
« Reply #7 on: January 24, 2014, 01:55:23 AM »
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.

Charles Pegge

  • Guest
Re: White Snowflake
« Reply #8 on: January 24, 2014, 02:17:25 AM »
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.