Beispiel #1
0
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;
}
Beispiel #2
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;
}