Slime-Simulation/gpu_kernel.clcpp

135 lines
3.9 KiB
Plaintext

struct Agent
{
float x;
float y;
float direction;
};
static struct Agent *agents;
static float *ground;
static float *working_ground;
static int2 ground_dimensions;
uint hash(uint input)
{
input ^= 2747636419u;
input *= 2654435769u;
input ^= input >> 16;
input *= 2654435769u;
input ^= input >> 16;
input *= 2654435769u;
return input;
}
void kernel initialize_globals(global struct Agent *new_agents, global float *new_ground, global float *new_working_ground, global int* new_ground_dimensions)
{
agents = new_agents;
ground = new_ground;
working_ground = new_working_ground;
ground_dimensions[0] = new_ground_dimensions[0];
ground_dimensions[1] = new_ground_dimensions[1];
}
void kernel update_ground()
{
int current_index = get_global_id(0);
int cx = current_index % ground_dimensions[0];
int cy = current_index / ground_dimensions[0];
float sum = 0.0f;
for (int i = cx-1; i <= cx+1; i++)
{
if (i < 0 || i >= ground_dimensions[0])
{
continue;
}
for(int j = cy-1; j <= cy+1; j++)
{
if (j < 0 || j >= ground_dimensions[1])
{
continue;
}
sum += ground[i+j*ground_dimensions[0]];
}
}
working_ground[current_index] = sum/9.0f-0.005f;
if (working_ground[current_index] < 0)
{
working_ground[current_index] = 0.0f;
}
}
void kernel iterate_ground()
{
ground[get_global_id(0)] = working_ground[get_global_id(0)];
}
void kernel move_agents()
{
int current_index = get_global_id(0);
uint psuedorandom_int = hash(agents[current_index].x+agents[current_index].y*ground_dimensions[0]);
if (psuedorandom_int % 100 < 12)
{
psuedorandom_int = hash(psuedorandom_int);
agents[current_index].direction += (float)(psuedorandom_int%1000)*M_PI_F/3.0f/1000.0f-M_PI_F/6.0f;
}
else
{
float lsense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction+M_PI_F/6.0f)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction+M_PI_F/6.0f)) * ground_dimensions[0]];
float ssense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction)) * ground_dimensions[0]];
float rsense = ground[(int)(agents[current_index].x+2.0f*cos(agents[current_index].direction-M_PI_F/6.0f)) + (int)(agents[current_index].y+2.0f*sin(agents[current_index].direction-M_PI_F/6.0f)) * ground_dimensions[0]];
if (lsense > ssense && lsense > rsense)
{
agents[current_index].direction += M_PI_F/6.0f;
}
if (rsense > ssense && rsense > lsense)
{
agents[current_index].direction += -M_PI_F/6.0f;
}
}
float nx = agents[current_index].x + cos(agents[current_index].direction);
float ny = agents[current_index].y + sin(agents[current_index].direction);
if(nx < 0.0f || nx >= ground_dimensions[0] || ny < 0.0f || ny >= ground_dimensions[1])
{
nx = (nx<0.0f)?0.0f:((nx>=ground_dimensions[0])?(ground_dimensions[0]-1.0f):nx);
ny = (ny<0.0f)?0.0f:((ny>=ground_dimensions[1])?(ground_dimensions[1]-1.0f):ny);
psuedorandom_int = hash(psuedorandom_int);
agents[current_index].direction = (float)(psuedorandom_int%1000)*2.0f*M_PI_F/1000.0f;
}
agents[current_index].x = nx;
agents[current_index].y = ny;
}
void kernel emit_agent_pheromones()
{
int current_index = get_global_id(0);
int x = agents[current_index].x;
int y = agents[current_index].y;
int ground_index = x+y*ground_dimensions[0];
ground[ground_index] = 1.0f;
}
void kernel fill_draw_data(global uchar* draw_data)
{
int index = get_global_id(0);
uchar val = (uchar)(255.0f*ground[index]);
draw_data[4*index] = val;
draw_data[4*index+1] = val;
draw_data[4*index+2] = val;
draw_data[4*index+3] = 255;
}