Skip to main content

Blow up pictures with OpenCL and Graphics3D!

This is small demonstration of N-body problem solved on GPU and then simulated in real-time using RGB flakes. To make it more entertaining we suggest to use command palette snippet Take a Picture and paste your face to the cell below instead of a cat

Download original notebook
face = (*VB[*)(FrontEndRef["aecb2e7c-dd49-4466-9812-cff8fd83d7aa"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJ6YmJxmlmifrpqSYWOqamJiZ6VpaGBrpJqelWaSlWBinmCcmAgCVkhZ1"*)(*]VB*);

Evaluate the cell below to see the result!

Graphics3D[{
    PointSize[0.015], 
    GraphicsComplex[npos // Offload, Point[Range[numParticles]], "VertexColors"->Offload[colors]], 
    AnimationFrameListener[npos // Offload, "Event"->"frame"]
  }, ImageSize->500]
(*VB[*)(FrontEndRef["bce47a7d-19ff-43c8-814c-4f31e70538ec"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJyWnmpgnmqfoGlqmpemaGCdb6FoYmiTrmqQZG6aaG5gaW6QmAwCOwBXe"*)(*]VB*)

Program

Needs["OpenCLLink`"]
srcf = FileNameJoin[{$OpenCLLinkPath, "SupportFiles", "NBody.cl"}];
NBody = OpenCLFunctionLoad[File[srcf], 
  "nbody_sim", {{"Float[4]", _, "Input"}, {"Float[4]", _, 
    "Input"}, _Integer, "Float", 
   "Float", {"Local", "Float"}, {"Float[4]", _, 
    "Output"}, {"Float[4]", _, "Output"}}, 256];
numParticles = 4096;
deltaT = 0.15;
epsSqrt = 50.0;
pos = OpenCLMemoryLoad[Flatten[Table[2.0 {x,y,(*FB[*)((x+y)(*,*)/(*,*)(2.0))(*]FB*),1.0}, {x,64}, {y,64}],1], "Float[4]"];
colors = With[{img = ImageResize[face, {64,64}] //ImageData},
  Flatten[Table[img[[x,y, 1;;3]], {x,64}, {y,64}],1] // NumericArray
];

vel = OpenCLMemoryLoad[Table[{0.,0.,0.,0.}, {i, numParticles}], "Float[4]"];
newPos = OpenCLMemoryAllocate["Float[4]", {numParticles}];
newVel = OpenCLMemoryAllocate["Float[4]", {numParticles}];

Test flight

NBody[pos, vel, numParticles, deltaT, epsSqrt, 256*4, newPos, newVel, 
  numParticles];
NBody[newPos, newVel, numParticles, deltaT, epsSqrt, 256*4, pos, vel, 
  numParticles];

Animation loop

npos = Take[#, 3] & /@ OpenCLMemoryGet[pos] // NumericArray;

EventHandler["frame", Function[Null,
NBody[pos, vel, numParticles, deltaT, epsSqrt, 256*4, newPos, 
     newVel, numParticles];
    NBody[newPos, newVel, numParticles, deltaT, epsSqrt, 256*4, pos, 
     vel, numParticles];
     
    npos = Take[#, 3] & /@ OpenCLMemoryGet[pos] // NumericArray
]]
"frame"