int main(int argc, char *argv[]) { // initialize the engine e = new engine(argv[0], (const char*)"../../data/"); e->init(); e->set_caption(APPLICATION_NAME); const xml::xml_doc& config_doc = e->get_config_doc(); // init class pointers fio = e->get_file_io(); eevt = e->get_event(); egfx = e->get_gfx(); t = e->get_texman(); ocl = e->get_opencl(); exts = e->get_ext(); s = e->get_shader(); r = e->get_rtt(); f = new fft(config_doc.get<bool>("config.audio.fake_spectrum", false)); ah = new audio_handler(f, config_doc.get<bool>("config.audio.playback", false)); sce = new scene(e); cam = new camera(e); // for debugging purposes debug_tex = a2e_texture(new texture_object()); debug_tex->width = e->get_width(); debug_tex->height = e->get_height(); // compile additional shaders const string ar_shaders[][2] = { { "IR_GP_SKINNING", "inferred/gp_skinning.a2eshd" }, { "IR_MP_SKINNING", "inferred/mp_skinning.a2eshd" }, { "RTT_MESH", "misc/rtt_mesh.a2eshd" }, { "PARTICLE DEBUG", "particle/particle_debug.a2eshd" }, { "MOTION BLUR", "misc/motion_blur.a2eshd" }, }; for(size_t i = 0; i < A2E_ARRAY_LENGTH(ar_shaders); i++) { if(!s->add_a2e_shader(ar_shaders[i][0], ar_shaders[i][1])) { a2e_error("couldn't add a2e-shader \"%s\"!", ar_shaders[i][1]); done = true; } } // compile additional kernels const string ar_kernels[][4] = { // identifier, kernel name, file name, build options { "PARTICLE MESH INIT", "particle_init", "particle_mesh_spawn.cl", " -DA2E_PARTICLE_INIT" }, { "PARTICLE MESH RESPAWN", "particle_respawn", "particle_mesh_spawn.cl", "" }, { "PARTICLE MESH COMPUTE", "particle_compute", "particle_mesh_compute.cl", " -DSPECTRUM_WIDTH="+size_t2string(FFT_CL_BUFFER_WIDTH) +" -DSPECTRUM_HEIGHT="+size_t2string(FFT_CL_BUFFER_HEIGHT) }, }; for(size_t i = 0; i < A2E_ARRAY_LENGTH(ar_kernels); i++) { bool success = ocl->add_kernel_file(ar_kernels[i][0], ocl->make_kernel_path(ar_kernels[i][2].c_str()), ar_kernels[i][1], ar_kernels[i][3].c_str()) != nullptr; if(!success) { a2e_error("couldn't add opencl kernel \"%s\"!", ar_kernels[i][2]); done = true; } } // initialize the camera cam->set_rotation_speed(300.0f); cam->set_cam_speed(5.0f); cam->set_mouse_input(false); cam->set_keyboard_input(true); cam->set_wasd_input(true); // get camera settings from the config const float3 cam_pos = config_doc.get<float3>("config.camera.position", float3(0.0f, -12.0f, -5.0f)); const float2 cam_rot = config_doc.get<float2>("config.camera.rotation", float2(0.0f, 180.0f)); cam->set_position(cam_pos); cam->set_rotation(cam_rot.x, cam_rot.y, 0.0f); // create the scene create_scene(); // load model model_loader ml(e); bmodel = ml.load(e->data_path("NI-Elem.txt"), e->data_path("NI-Vrts.txt"), e->data_path("NI-Tex0.txt"), e->data_path("NI-boneW.txt"), e->data_path("NI-boneI.txt"), e->data_path("NI-bindMatrix-CM.txt")); // render mesh border and mesh push mesh_border* mb = new mesh_border(); mb->load(e->data_path("NI-Border1.txt"), e->data_path("NI-Border2.txt")); mb->render(); mesh_push* mp = new mesh_push(); mp->load(e->data_path("NI-Push1.txt")); mp->render(); // init openni const string oni_file = (argc > 1 ? string(argv[1]) : ""); const int init_ret = ni_handler::init(oni_file, mb, mp); if(init_ret != XN_STATUS_OK) { a2e_error("couldn't initialize openni: %u", init_ret); done = true; } // add event handlers event::handler key_handler_fnctr(&key_handler); eevt->add_event_handler(key_handler_fnctr, EVENT_TYPE::KEY_DOWN, EVENT_TYPE::KEY_UP, EVENT_TYPE::KEY_PRESSED); event::handler mouse_handler_fnctr(&mouse_handler); eevt->add_event_handler(mouse_handler_fnctr, EVENT_TYPE::MOUSE_RIGHT_CLICK); event::handler quit_handler_fnctr(&quit_handler); eevt->add_event_handler(quit_handler_fnctr, EVENT_TYPE::QUIT); // additional debug stuff const int2 buffer_size(1024); particle_debug_fbo = r->add_buffer(buffer_size.x, buffer_size.y, GL_TEXTURE_2D, texture_object::TF_POINT, rtt::TAA_NONE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT, 1, rtt::DT_NONE); // main loop while(!done) { // event handling eevt->handle_events(); // set caption (app name and fps count) if(e->is_new_fps_count()) { static stringstream caption; caption << APPLICATION_NAME << " | FPS: " << e->get_fps(); caption << " | Cam: " << float3(-*e->get_position()); caption << " " << cam->get_rotation(); e->set_caption(caption.str().c_str()); core::reset(&caption); } // render e->start_draw(); if(ni_update) ni->run(); cam->run(); sce->draw(); // draw debug texture if(show_debug_texture) { if(debug_tex->width > 0 && debug_tex->height > 0) { e->start_2d_draw(); size_t draw_width = debug_tex->width, draw_height = debug_tex->height; float ratio = float(draw_width) / float(draw_height); float scale = 1.0f; if(ratio >= 1.0f && draw_width > e->get_width()) { scale = float(e->get_width()) / float(draw_width); } else if(ratio < 1.0f && draw_height > e->get_height()) { scale = float(e->get_height()) / float(draw_height); } draw_width *= scale; draw_height *= scale; egfx->draw_textured_color_rectangle(gfx::rect(0, 0, (unsigned int)draw_width, (unsigned int)draw_height), coord(0.0f, 1.0f), coord(1.0f, 0.0f), float4(1.0f, 1.0f, 1.0f, 0.0f), float4(0.0f, 0.0f, 0.0f, 1.0f), debug_tex->tex()); e->stop_2d_draw(); } } e->stop_draw(); // for debugging purposes only: reset players (set if opencl kernels are reloaded) if(debug_players_reset) { debug_players_reset = false; ni_handler::reset_players(); } } debug_tex->tex_num = 0; // cleanup eevt->remove_event_handler(key_handler_fnctr); eevt->remove_event_handler(mouse_handler_fnctr); eevt->remove_event_handler(quit_handler_fnctr); r->delete_buffer(particle_debug_fbo); delete ah; delete f; ni_handler::destroy(); delete mb; delete mp; delete mat; for(const auto& model : models) { delete model; } models.clear(); for(const auto& l : lights) { delete l; } lights.clear(); if(bmodel != nullptr) delete bmodel; delete sce; delete cam; delete e; return 0; }
int main(int argc floor_unused, char* argv[]) { // initialize oclraster oclraster::init(argv[0], #if !defined(OCLRASTER_IOS) (const char*)"../data/" #else (const char*)"/var/mobile/Documents/oclraster/" #endif ); floor::set_caption(APPLICATION_NAME); floor::acquire_context(); // init class pointers evt = floor::get_event(); //ocl->set_active_device(opencl_base::DEVICE_TYPE::FASTEST_CPU); ocl->set_active_device(opencl_base::DEVICE_TYPE::FASTEST_GPU); //ocl->set_active_device(opencl_base::DEVICE_TYPE::GPU0); // cam = new camera(); #if 0 cam->set_position(0.0f, 0.1f, -0.3f); //cam->set_position(1.12157e-12f, 0.1f, -2.22f); cam->set_rotation(0.0f, 0.0f, 0.0f); #elif 1 cam->set_position(0.8f, 0.28f, 3.2f); cam->set_rotation(-5.2f, 196.0f, 0.0f); #else cam->set_position(10.0f, 5.0f, -10.0f); cam->set_rotation(-20.0f, -45.0f, 0.0f); #endif cam->set_speed(cam_speeds.x); cam->set_rotation_speed(cam->get_rotation_speed() * 1.5f); cam->set_wasd_input(true); // create the pipeline, set the active camera and // notify oclraster that this is the active pipeline p = new pipeline(); p->set_camera(cam); oclraster::set_active_pipeline(p); // load the model (blender monkey with uv coordinates) a2m* model = new a2m(floor::data_path("monkey_uv.a2m")); //a2m* model = new a2m(floor::data_path("blend_test.a2m")); //model->flip_faces(); // add event handlers event::handler key_handler_fnctr(&key_handler); evt->add_event_handler(key_handler_fnctr, EVENT_TYPE::KEY_DOWN, EVENT_TYPE::KEY_UP); event::handler mouse_handler_fnctr(&mouse_handler); evt->add_internal_event_handler(mouse_handler_fnctr, EVENT_TYPE::MOUSE_RIGHT_CLICK, EVENT_TYPE::MOUSE_MOVE); event::handler quit_handler_fnctr(&quit_handler); evt->add_event_handler(quit_handler_fnctr, EVENT_TYPE::QUIT); event::handler kernel_reload_handler_fnctr(&kernel_reload_handler); evt->add_internal_event_handler(kernel_reload_handler_fnctr, EVENT_TYPE::KERNEL_RELOAD); #if defined(OCLRASTER_IOS) event::handler touch_handler_fnctr(&touch_handler); evt->add_event_handler(touch_handler_fnctr, EVENT_TYPE::FINGER_UP, EVENT_TYPE::FINGER_DOWN, EVENT_TYPE::FINGER_MOVE); #endif // load, compile and bind user shaders if(!load_programs()) return -1; // create / ref buffers const opencl::buffer_object& index_buffer = model->get_index_buffer(0); const opencl::buffer_object& input_attributes = model->get_vertex_buffer(); oclraster_struct tp_uniforms { matrix4f modelview; matrix4f rotation_matrix; } transform_uniforms { matrix4f(), matrix4f() }; opencl::buffer_object* tp_uniforms_buffer = ocl->create_buffer(opencl::BUFFER_FLAG::READ | opencl::BUFFER_FLAG::INITIAL_COPY | opencl::BUFFER_FLAG::BLOCK_ON_WRITE, sizeof(tp_uniforms), (void*)&transform_uniforms); float light_pos = PI, light_dist = 10.0f, light_intensity = 32.0f; oclraster_struct rp_uniforms { float4 camera_position; float4 light_position; // .w = light radius ^ 2 float4 light_color; } rasterize_uniforms { float4(cam->get_position(), 1.0f), float4(sinf(light_pos)*light_dist, 0.0f, cosf(light_pos)*light_dist, light_intensity*light_intensity), //float4(1.0f, 1.0f, 1.0f, 1.0f) float4(0.0f, 0.3f, 0.7f, 1.0f) }; opencl::buffer_object* rp_uniforms_buffer = ocl->create_buffer(opencl::BUFFER_FLAG::READ | opencl::BUFFER_FLAG::INITIAL_COPY | opencl::BUFFER_FLAG::BLOCK_ON_WRITE, sizeof(rp_uniforms), (void*)&rasterize_uniforms); // textures static constexpr size_t textures_per_material = 3; static const array<string, material_count * textures_per_material> texture_names { { "light_512", "light_normal_512", "light_height_512", "planks_512", "planks_normal_512", "planks_height_512", "rockwall_512", "rockwall_normal_512", "rockwall_height_512", "acid_512", "acid_normal_512", "acid_height_512", "blend_test_512", "light_normal_512", "scale_gray", } }; static constexpr auto image_backing = image::BACKING::BUFFER; // or image::BACKING::IMAGE array<array<shared_ptr<image>, textures_per_material>, material_count> materials; for(size_t i = 0; i < material_count; i++) { for(size_t j = 0; j < textures_per_material; j++) { materials[i][j] = make_shared<image>(image::from_file(floor::data_path(texture_names[(i * textures_per_material) + j]+".png"), image_backing, IMAGE_TYPE::UINT_8, IMAGE_CHANNEL::RGBA)); } } // float* fp_noise_data = new float[512*512]; for(size_t i = 0; i < (512*512); i++) { fp_noise_data[i] = core::rand(0.0f, 1.0f); } image* fp_noise = new image(512, 512, image_backing, IMAGE_TYPE::FLOAT_32, IMAGE_CHANNEL::R, fp_noise_data); delete [] fp_noise_data; #if 0 // enable this if you want the framebuffer clear color to be white p->get_default_framebuffer()->set_clear_color(ulong4 { ~0 }); #endif // init done floor::release_context(); // main loop float model_rotation = 0.0f; float3 model_scale { 1.0f, 1.0f, 1.0f }; float3 target_scale { model_scale }; static constexpr float model_scale_range = 0.4f, model_scale_step = 0.01f; while(!done) { // event handling evt->handle_events(); #if 0 // enable this to disable rendering when the window is inactive // stop drawing if window is inactive if(!(SDL_GetWindowFlags(floor::get_window()) & SDL_WINDOW_INPUT_FOCUS)) { SDL_Delay(20); continue; } #endif // set caption (app name and fps count) if(floor::is_new_fps_count()) { const unsigned int fps = floor::get_fps(); //oclr_log("fps: %u", fps); stringstream caption; caption << APPLICATION_NAME; caption << " | " << fps << " FPS"; caption << " | ~" << floor::get_frame_time() << "ms "; caption << " | Cam: " << cam->get_position(); caption << " " << cam->get_rotation(); floor::set_caption(caption.str()); } oclraster::start_draw(); cam->run(); p->set_camera(cam); // update pipeline camera #if 0 // enable this to test a custom depth test function p->set_depth_function(DEPTH_FUNCTION::CUSTOM, "bool depth_test(float incoming, float current) {" \ " const float depth = fmod(incoming, 0.1f);" \ " return (depth > 0.05f && incoming < current);" \ "}"); #endif // update uniforms if(update_model) { transform_uniforms.modelview = matrix4f().rotate_y(model_rotation); transform_uniforms.rotation_matrix = transform_uniforms.modelview; model_rotation += 1.0f; if(model_rotation >= 360.0f) { selected_material = (selected_material + 1) % material_count; model_rotation = core::wrap(model_rotation, 360.0f); } const float3 scale_diff = (model_scale - target_scale).abs(); if((scale_diff <= float3(model_scale_step * 2.0f)).all()) { target_scale.x = 1.0f + core::rand(-model_scale_range, model_scale_range); target_scale.y = 1.0f + core::rand(-model_scale_range, model_scale_range); target_scale.z = 1.0f + core::rand(-model_scale_range, model_scale_range); } else { for(unsigned int i = 0; i < 3; i++) { if(scale_diff[i] <= (model_scale_step * 2.0f)) continue; model_scale[i] += model_scale_step * (model_scale[i] <= target_scale[i] ? 1.0f : -1.0f); } } transform_uniforms.modelview.scale(model_scale.x, model_scale.y, model_scale.z); ocl->write_buffer(tp_uniforms_buffer, &transform_uniforms); } if(update_light) { light_pos -= 0.125f; rasterize_uniforms.light_position.set(sinf(light_pos)*light_dist, 0.0f, cosf(light_pos)*light_dist, light_intensity * light_intensity); } if(update_light_color) { static constexpr float color_step_range = 0.05f; rasterize_uniforms.light_color.x += core::rand(-color_step_range, color_step_range); rasterize_uniforms.light_color.y += core::rand(-color_step_range, color_step_range); rasterize_uniforms.light_color.z += core::rand(-color_step_range, color_step_range); rasterize_uniforms.light_color.clamp(0.0f, 1.0f); } rasterize_uniforms.camera_position.vector3<float>::set(cam->get_position()); ocl->write_buffer(rp_uniforms_buffer, &rasterize_uniforms); // draw something p->bind_buffer("index_buffer", index_buffer); p->bind_buffer("input_attributes", input_attributes); p->bind_buffer("tp_uniforms", *tp_uniforms_buffer); p->bind_buffer("rp_uniforms", *rp_uniforms_buffer); p->bind_image("diffuse_texture", *materials[selected_material][0]); p->bind_image("normal_texture", *materials[selected_material][1]); p->bind_image("height_texture", *materials[selected_material][2]); p->bind_image("fp_noise", *fp_noise); p->draw(PRIMITIVE_TYPE::TRIANGLE, model->get_vertex_count(), { 0, model->get_index_count(0) }); oclraster::stop_draw(); } // cleanup for(auto& mat : materials) { for(auto& tex : mat) { tex = nullptr; // clear } } delete fp_noise; delete model; delete cam; ocl->delete_buffer(tp_uniforms_buffer); ocl->delete_buffer(rp_uniforms_buffer); evt->remove_event_handler(key_handler_fnctr); evt->remove_event_handler(mouse_handler_fnctr); evt->remove_event_handler(quit_handler_fnctr); delete p; oclraster::destroy(); return 0; }