Your task is to implement simple particle system in CUDA/OpenCL/GLSLComputeShader . Particles should move in homogenous gravitational field, collide with simple obstacles (represented as triangle meshes) but need not interact with each other. Simple realtime rendering in OpenGL, best using GL_PONTS for particles.
There are two options: you can start with the sample14 project from the ogl repository (CUDA in C++) or with the 090opencl project from the grcis repository (OpenCL in C#).
Each working thread could have its particles in local memory (registers), obstacle (=scene)
definition should be in the shared memory. Particle generator[s] implementation may remain
in CPU, but it is not difficult to implement generator in CUDA as well..
Use CUDA-OpenGL interop to directly write particle coordinates from CUDA
kernel to pre-allocated VBO buffer for rendering.
Particle-triangle intersection: create small line segment using current particle's
position and its velocity vector. Intersect the line with a triangle. Bounce the particle
in case of collision. You should be able to handle up to 500 triangles w/o problems (see
max-shared-memory size).
#define EPSILON 0.0001f #define MINIEPSILON 0.00001f struct STriangleCUDA { float3 a,b,c; float3 edge1, edge2, normal; }; __device__ bool IntersectTriangle ( STriangleCUDA *tri, float3 orig, float3 dir, float *t ) { const float3 pvec = make_float3( dir.y*tri->edge2.z - dir.z*tri->edge2.y, // dir ^ tri.edge2; dir.z*tri->edge2.x - dir.x*tri->edge2.z, dir.x*tri->edge2.y - dir.y*tri->edge2.x ); const float det = tri->edge1.x*pvec.x + tri->edge1.y*pvec.y + tri->edge1.z*pvec.z; // tri.edge1 * pvec; if( fabs(det) < EPSILON ) return false; const float inv_det = 1.0f / det; const float3 tvec = make_float3( orig.x - tri->a.x, orig.y - tri->a.y, orig.z - tri->a.z ); // orig - tri.a; float lambda = tvec.x*pvec.x + tvec.y*pvec.y + tvec.z*pvec.z; // tvec * pvec; lambda *= inv_det; if ( lambda < -MINIEPSILON || lambda > 1.0f + MINIEPSILON ) return false; const float3 qvec = make_float3( tvec.y*tri->edge1.z - tvec.z*tri->edge1.y, // tvec^tri.edge1; tvec.z*tri->edge1.x - tvec.x*tri->edge1.z, tvec.x*tri->edge1.y - tvec.y*tri->edge1.x ); float mue = dir.x*qvec.x + dir.y*qvec.y + dir.z*qvec.z; // dir * qvec; mue *= inv_det; if ( mue < MINIEPSILON || mue+lambda > 1.0f + MINIEPSILON ) return false; float f = tri->edge2.x*qvec.x + tri->edge2.y*qvec.y + tri->edge2.z*qvec.z; // tri.edge2 * qvec; f *= inv_det; if ( *t <= f || f < EPSILON ) return false; *t = f; return true; }
Use previously implemented interactivity (trackball). Render both particles and the scene (obstacles), you can implement some fancy aging mechanism for particles - changing color, point-size, etc.
Send complete Visual Studio project including shaders and CUDA/OpenCL source. Write a brief document about your ideas and operating manual.
Hand in before: 3. 7. 2016
8 points: basic particle system implementation on the CPU (including collision with obstacles and gravitational field),
18 points: the same in CUDA/OpenCL/compute-shaders,
5 points: efficiency study (discuss grid/block size, time measurements..),
8 points: using shared memory for obstacles and/or generators,
4 points: all the data live in the GPU memory (OpenGL interop is used for rendering),
2 points: for each additional collision geometry type (sphere, rectangle, .. max 6 points),
up to 8 points: bonus for nice scene, more forces, fancy particle generators, ..
Attention: you have to implement at least CUDA/OpenCL/shaders option!
Recommended starting point: Visual Studio project 090opencl from the grcis repository (OpenCL) or the sample14 from the ogl repository (CUDA).
Copyright (C) 2011-2016 J. Pelikán, last change: 2019-05-09 17:52:59 +0200 (Thu, 09 May 2019)