A program itt is több részből áll. A hatékonyabb kezelés érdekében van definiálva egy Sphere nevű struktúra a gömbök tárolását, és használatát teszi Egyszerűbbé.
A Sphere struktúrában található egy RGB színkód, ami a gömb színét adja majd, illetve a gömb (X,Y,Z) koordinátái és sugara.
struct Sphere {
float r,b,g;
float radius;
float x,y,z;
__device__ float hit( float ox, float oy, float *n ) {
float dx = ox - x;
float dy = oy - y;
if (dx*dx + dy*dy < radius*radius) {
float dz = sqrtf( radius*radius - dx*dx - dy*dy );
*n = dz / sqrtf( radius * radius );
return dz + z;
}
return -INF;
}
};
A struktúrához tartozim még egy hit() függvény ami egy sugár és egy gömb találkozását képes detektálni. A függvény bemenetül két normalizálr koordinátát kap ox, és oy néven, és visszadja az ütközés a sugárral való metszés távolságát, és a normálvektor és a sugár által bezárt szög koszinuszát a metszés pontjában. (A programot az Nvidia programozói készítették, jól optimalizált, viszont ettől nagyon bonyolult. Megértése csak azoknak célszerű, akik sugárkövetéssel akarnak foglalkozni.)
A porgramban definiálva van még egy konstans tömb, ami 20 darab gömböt tárol.
#define SPHERES 20
__constant__ Sphere s[SPHERES];
A CPU-n futó fő program nem túl édrekes. Annyit csinál mont a korábbi képeket előállító kódok. Lefoglalja a képtömbböt, és elindítja a kernelt. Illetve ezeken kívül legenerál még 20 db véletlenszerű gömböt, amiket átmásol a konstans memóriába.
Sphere *temp_s = (Sphere*)malloc( sizeof(Sphere) * SPHERES );
for (int i=0; i<SPHERES; i++) {
temp_s[i].r = rnd( 1.0f );
temp_s[i].g = rnd( 1.0f );
temp_s[i].b = rnd( 1.0f );
temp_s[i].x = rnd( 1000.0f ) - 500;
temp_s[i].y = rnd( 1000.0f ) - 500;
temp_s[i].z = rnd( 1000.0f ) - 500;
temp_s[i].radius = rnd( 100.0f ) + 20;
}
cudaMemcpyToSymbol( s, temp_s, sizeof(Sphere) * SPHERES);
free( temp_s );