struct Agent { float x; float y; float direction; }; static struct Agent *agents; static float *ground; static float *working_ground; static int2 ground_dimensions; constant float sense_distance = 3.0f; constant float move_distance = 3.0f; constant float diffusion_rate = 0.05f; constant float cone_of_vision = 2.0f*M_PI_F/4.0f; constant float vision_sensing_steps = 8.0f; constant float color_r = 0.0f; constant float color_g = 255.0f; constant float color_b = 255.0f; 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-diffusion_rate; 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)*cone_of_vision/1000.0f-cone_of_vision/2.0f; } else { float directional_change = cone_of_vision/2.0f; float mx = agents[current_index].x + sense_distance*cos(agents[current_index].direction+directional_change); float my = agents[current_index].y + sense_distance*sin(agents[current_index].direction+directional_change); float max_sense = ground[(int)mx+(int)my*ground_dimensions[0]]; for(int i = 1; i <= 8; i++) { mx = agents[current_index].x + sense_distance*cos(agents[current_index].direction+cone_of_vision/2.0f-(float)i*cone_of_vision/vision_sensing_steps); my = agents[current_index].y + sense_distance*sin(agents[current_index].direction+cone_of_vision/2.0f-(float)i*cone_of_vision/vision_sensing_steps); if (ground[(int)mx+(int)my*ground_dimensions[0]] > max_sense) { directional_change = cone_of_vision/2.0f-(float)i*cone_of_vision/vision_sensing_steps; max_sense = ground[(int)mx+(int)my*ground_dimensions[0]]; } } agents[current_index].direction += directional_change; } float nx = agents[current_index].x + move_distance*cos(agents[current_index].direction); float ny = agents[current_index].y + move_distance*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); draw_data[4*index] = (uchar)(color_b*ground[index]); draw_data[4*index+1] = (uchar)(color_g*ground[index]); draw_data[4*index+2] = (uchar)(color_r*ground[index]); draw_data[4*index+3] = 255; }