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
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"