Example #1
0
void RWGame::render(float alpha, float time)
{
	lastDraws = getRenderer()->getRenderer()->getDrawCount();
	
	getRenderer()->getRenderer()->swap();
	
	auto size = getWindow().getSize();
	renderer->setViewport(size.x, size.y);
	
	ViewCamera viewCam;
	viewCam.frustum.fov = glm::radians(90.f);
	if( state->currentCutscene != nullptr && state->cutsceneStartTime >= 0.f )
	{
		auto cutscene = state->currentCutscene;
		float cutsceneTime = std::min(world->getGameTime() - state->cutsceneStartTime,
									  cutscene->tracks.duration);
		cutsceneTime += GAME_TIMESTEP * alpha;
		glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
				targetPos = cutscene->tracks.getTargetAt(cutsceneTime);
		float zoom = cutscene->tracks.getZoomAt(cutsceneTime);
		viewCam.frustum.fov = glm::radians(zoom);
		float tilt = cutscene->tracks.getRotationAt(cutsceneTime);

		auto direction = glm::normalize(targetPos - cameraPos);
		auto right = glm::normalize(glm::cross(glm::vec3(0.f, 0.f, 1.f), direction));
		auto up = glm::normalize(glm::cross(direction, right));

		glm::mat3 m;
		m[0][0] = direction.x;
		m[0][1] = right.x;
		m[0][2] = up.x;

		m[1][0] = direction.y;
		m[1][1] = right.y;
		m[1][2] = up.y;

		m[2][0] = direction.z;
		m[2][1] = right.z;
		m[2][2] = up.z;

		auto qtilt = glm::angleAxis(glm::radians(tilt), direction);

		cameraPos += cutscene->meta.sceneOffset;
		targetPos += cutscene->meta.sceneOffset;

		viewCam.position = cameraPos;
		viewCam.rotation = glm::inverse(glm::quat_cast(m)) * qtilt;
	}
	else if( state->cameraFixed )
	{
		viewCam.position = state->cameraPosition;
		viewCam.rotation = state->cameraRotation;
	}
	else
	{
		// There's no cutscene playing - use the camera returned by the State.
		viewCam.position = glm::mix(lastCam.position, nextCam.position, alpha);
		viewCam.rotation = glm::slerp(lastCam.rotation, nextCam.rotation, alpha);
	}

	viewCam.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
	
	if ( state->isCinematic )
	{
		viewCam.frustum.fov *= viewCam.frustum.aspectRatio;
	}

	glEnable(GL_DEPTH_TEST);
	glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);

	renderer->getRenderer()->pushDebugGroup("World");

	RW_PROFILE_BEGIN("world");
	renderer->renderWorld(world, viewCam, alpha);
	RW_PROFILE_END();


	auto rendertime = renderer->getRenderer()->popDebugGroup();

	RW_PROFILE_BEGIN("debug");
	if( showDebugPaths )
	{
		renderDebugPaths(time);
	}

	if ( showDebugStats )
	{
		renderDebugStats(time, rendertime);
	}

	if( showDebugPhysics )
	{
		if( world )
		{
			world->dynamicsWorld->debugDrawWorld();
			debug->flush(renderer);
		}
	}
	RW_PROFILE_END();
	
	drawOnScreenText(world, renderer);
}
Example #2
0
int RWGame::run()
{
	last_clock_time = clock.now();

	// Loop until the window is closed or we run out of state.
	while (window.isOpen() && StateManager::get().states.size()) {
		State* state = StateManager::get().states.back();

		RW_PROFILE_FRAME_BOUNDARY();
		
		RW_PROFILE_BEGIN("Input");
		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			switch (event.type) {
			case SDL_QUIT:
				window.close();
				break;

			case SDL_WINDOWEVENT:
				switch (event.window.event) {
				case SDL_WINDOWEVENT_FOCUS_GAINED:
					inFocus = true;
					break;

				case SDL_WINDOWEVENT_FOCUS_LOST:
					inFocus = false;
					break;
				}
				break;

			case SDL_KEYDOWN:
				globalKeyEvent(event);
				break;

			case SDL_MOUSEMOTION:
				event.motion.xrel *= MOUSE_SENSITIVITY_SCALE;
				event.motion.yrel *= MOUSE_SENSITIVITY_SCALE;
				break;
			}

			RW_PROFILE_BEGIN("State");
			state->handleEvent(event);
			RW_PROFILE_END()
		}
		RW_PROFILE_END();

		auto now = clock.now();
		float timer = std::chrono::duration<float>(now - last_clock_time).count();
		last_clock_time = now;
		accum += timer * timescale;

		RW_PROFILE_BEGIN("Update");
		if ( accum >= GAME_TIMESTEP ) {
			RW_PROFILE_BEGIN("state");
			StateManager::get().tick(GAME_TIMESTEP);
			RW_PROFILE_END();

			if (StateManager::get().states.size() == 0) {
				break;
			}

			RW_PROFILE_BEGIN("engine");
			tick(GAME_TIMESTEP);
			RW_PROFILE_END();
			
			accum -= GAME_TIMESTEP;
			
			// Throw away time if the accumulator reaches too high.
			if ( accum > GAME_TIMESTEP * 5.f )
			{
				accum = 0.f;
			}
		}
		RW_PROFILE_END();

		float alpha = fmod(accum, GAME_TIMESTEP) / GAME_TIMESTEP;
		if( ! state->shouldWorldUpdate() )
		{
			alpha = 1.f;
		}

		RW_PROFILE_BEGIN("Render");
		RW_PROFILE_BEGIN("engine");
		render(alpha, timer);
		RW_PROFILE_END();

		RW_PROFILE_BEGIN("state");
		if (StateManager::get().states.size() > 0) {
			StateManager::get().draw(renderer);
		}
		RW_PROFILE_END();
		RW_PROFILE_END();

		renderProfile();

		window.swap();
	}

    if( httpserver_thread )
    {
        httpserver_thread->join();
    }

	return 0;
}
Example #3
0
int RWGame::run()
{
	clock.restart();
	
	// Loop until the window is closed or we run out of state.
	while (window.isOpen() && StateManager::get().states.size()) {
		State* state = StateManager::get().states.back();

		RW_PROFILE_FRAME_BOUNDARY();
		
		RW_PROFILE_BEGIN("Input");
		sf::Event event;
		while (window.pollEvent(event)) {
			switch (event.type) {
			case sf::Event::GainedFocus:
				inFocus = true;
				break;
			case sf::Event::LostFocus:
				inFocus = false;
				break;
			case sf::Event::KeyPressed:
				globalKeyEvent(event);
				break;
			case sf::Event::Closed:
				return 0;
			default: break;
			}

			RW_PROFILE_BEGIN("State");
			state->handleEvent(event);
			RW_PROFILE_END()
		}
		RW_PROFILE_END();
		
		if(! window.isOpen() )
		{
			break;
		}

		float timer = clock.restart().asSeconds();
		accum += timer * timescale;

		RW_PROFILE_BEGIN("Update");
		if ( accum >= GAME_TIMESTEP ) {
			RW_PROFILE_BEGIN("state");
			StateManager::get().tick(GAME_TIMESTEP);
			RW_PROFILE_END();

			if (StateManager::get().states.size() == 0) {
				break;
			}

			RW_PROFILE_BEGIN("engine");
			tick(GAME_TIMESTEP);
			RW_PROFILE_END();
			
			accum -= GAME_TIMESTEP;
			
			// Throw away time if the accumulator reaches too high.
			if ( accum > GAME_TIMESTEP * 5.f )
			{
				accum = 0.f;
			}
		}
		RW_PROFILE_END();

		float alpha = fmod(accum, GAME_TIMESTEP) / GAME_TIMESTEP;
		if( ! state->shouldWorldUpdate() )
		{
			alpha = 1.f;
		}

		RW_PROFILE_BEGIN("Render");
		RW_PROFILE_BEGIN("engine");
		render(alpha, timer);
		RW_PROFILE_END();

		RW_PROFILE_BEGIN("state");
		if (StateManager::get().states.size() > 0) {
			StateManager::get().draw(renderer);
		}
		RW_PROFILE_END();
		RW_PROFILE_END();

		renderProfile();

		window.display();
	}

    if( httpserver_thread )
    {
        httpserver_thread->join();
    }

	return 0;
}
Example #4
0
void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float alpha)
{
	_renderAlpha = alpha;
	_renderWorld = world;

	// Store the input camera,
	_camera = camera;

	setupRender();

	glBindVertexArray( vao );

	float tod = world->getHour() + world->getMinute()/60.f;

	// Requires a float 0-24
	auto weatherID = static_cast<WeatherLoader::WeatherCondition>(world->state->basic.nextWeather * 24);
	auto weather = world->data->weatherLoader.getWeatherData(weatherID, tod);

	glm::vec3 skyTop = weather.skyTopColor;
	glm::vec3 skyBottom = weather.skyBottomColor;
	glm::vec3 ambient = weather.ambientColor;
	glm::vec3 dynamic = weather.directLightColor;

	float theta = (tod/(60.f * 24.f) - 0.5f) * 2 * 3.14159265;
	glm::vec3 sunDirection{
		sin(theta),
		0.0,
		cos(theta),
	};
	sunDirection = glm::normalize(sunDirection);

	_camera.frustum.near = world->state->cameraNear;
	_camera.frustum.far = weather.farClipping;

	auto view = _camera.getView();
	auto proj = _camera.frustum.projection();

	Renderer::SceneUniformData sceneParams {
		proj,
		view,
		glm::vec4{ambient, 0.0f},
		glm::vec4{dynamic, 0.0f},
		glm::vec4(skyBottom, 1.f),
		glm::vec4(camera.position, 0.f),
		weather.fogStart,
		camera.frustum.far
	};

	renderer->setSceneParameters(sceneParams);
	
	renderer->clear(glm::vec4(skyBottom, 1.f));

	_camera.frustum.update(proj * view);
	if (cullOverride)
	{
		cullingCamera.frustum.update(
					cullingCamera.frustum.projection() * cullingCamera.getView());
	}
	
	culled = 0;

	renderer->useProgram(worldProg);

	//===============================================================
	//	Render List Construction
	//---------------------------------------------------------------

	RW_PROFILE_BEGIN("RenderList");

	// This is sequential at the moment, it should be easy to make it
	// run in parallel with a good threading system.
	RenderList renderList;
	// Naive optimisation, assume 10% hitrate
	renderList.reserve(world->allObjects.size() * 0.5f);

	RW_PROFILE_BEGIN("Build");

	ObjectRenderer objectRenderer(_renderWorld,
					  (cullOverride ? cullingCamera : _camera),
					  _renderAlpha,
					  getMissingTexture());

	// World Objects
	for (auto object : world->allObjects) {
		objectRenderer.buildRenderList(object, renderList);
	}
	RW_PROFILE_END();

	renderer->pushDebugGroup("Objects");
	renderer->pushDebugGroup("RenderList");

	// Also parallelizable
	RW_PROFILE_BEGIN("Sort");
	std::sort(renderList.begin(), renderList.end(),
			  [](const Renderer::RenderInstruction& a,
				 const Renderer::RenderInstruction&b) {
					return a.sortKey < b.sortKey;
				});
	RW_PROFILE_END();

	RW_PROFILE_BEGIN("Draw");
	renderer->drawBatched(renderList);
	RW_PROFILE_END();

	renderer->popDebugGroup();
	profObjects = renderer->popDebugGroup();

	RW_PROFILE_END();

	// Render arrows above anything that isn't radar only (or hidden)
	ModelRef& arrowModel = world->data->models["arrow"];
	if( arrowModel && arrowModel->resource )
	{
		auto arrowTex = world->data->textures[{"copblue",""}];
		auto arrowFrame = arrowModel->resource->findFrame( "arrow" );
		for( auto& blip : world->state->radarBlips )
		{
			if( blip.second.display == BlipData::Show )
			{
				glm::mat4 model;

				if( blip.second.target > 0 )
				{
					// TODO restore arrows
					/*auto& pool = world->getTypeObjectPool(blip.second.target);
					auto object = pool.find(blip.second.target);
					if( object )
					{
						model = object->getTimeAdjustedTransform( _renderAlpha );
					}*/
				}
				else
				{
					model = glm::translate( model, blip.second.coord );
				}

				float a = world->getGameTime() * glm::pi<float>();
				model = glm::translate( model, glm::vec3(0.f, 0.f, 2.5f + glm::sin( a ) * 0.5f) );
				model = glm::rotate( model, a, glm::vec3(0.f, 0.f, 1.f) );
				model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) );

				Renderer::DrawParameters dp;
				dp.textures = {arrowTex->getName()};
				dp.ambient = 1.f;
				dp.colour = glm::u8vec4(255, 255, 255, 255);

				auto geom = arrowModel->resource->geometries[arrowFrame->getGeometries()[0]];
				Model::SubGeometry& sg = geom->subgeom[0];

				dp.start = sg.start;
				dp.count = sg.numIndices;
				dp.diffuse = 1.f;

				renderer->draw( model, &geom->dbuff, dp );
			}
		}
	}

	// Draw goal indicators
	glDepthMask(GL_FALSE);
	renderer->useProgram( particleProg );
	for(auto& i : world->getAreaIndicators())
	{
		renderAreaIndicator( &i );
	}
	glDepthMask(GL_TRUE);

	renderer->pushDebugGroup("Water");

	water.render(this, world);

	profWater = renderer->popDebugGroup();

	renderer->pushDebugGroup("Sky");

	glBindVertexArray( vao );

	Renderer::DrawParameters dp;
	dp.start = 0;
	dp.count = skydomeSegments * skydomeRows * 6;

	renderer->useProgram(skyProg);
	renderer->setUniform(skyProg, "TopColor", glm::vec4(skyTop, 1.f));
	renderer->setUniform(skyProg, "BottomColor", glm::vec4(skyBottom, 1.f));

	renderer->draw(glm::mat4(), &skyDbuff, dp);

	profSky = renderer->popDebugGroup();

	renderer->pushDebugGroup("Effects");
	renderEffects(world);
	profEffects = renderer->popDebugGroup();

	glDisable(GL_DEPTH_TEST);

	GLuint splashTexName = 0;
	auto fc = world->state->fadeColour;
	if((fc.r + fc.g + fc.b) == 0 && world->state->currentSplash.size() > 0) {
		auto splash = world->data->findTexture(world->state->currentSplash);
		if ( splash )
		{
			splashTexName = splash->getName();
		}
	}

	if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName != 0 ) {
		renderLetterbox();
	}

	float fadeTimer = world->getGameTime() - world->state->fadeStart;
	if( fadeTimer < world->state->fadeTime || !world->state->fadeOut ) {
		glUseProgram(ssRectProgram);
		glUniform2f(ssRectOffset, 0.f, 0.f);
		glUniform2f(ssRectSize, 1.f, 1.f);

		glUniform1i(ssRectTexture, 0);

		if(splashTexName != 0) {
			glBindTexture(GL_TEXTURE_2D, splashTexName);
			fc = glm::u16vec3(0, 0, 0);
		}
		else {
			glBindTexture(GL_TEXTURE_2D, 0);
		}

		float fadeFrac = 0.f;
		if( world->state->fadeTime > 0.f ) {
			fadeFrac = std::min(fadeTimer / world->state->fadeTime, 1.f);
		}

		float a = world->state->fadeOut ? 1.f - fadeFrac : fadeFrac;

		glm::vec4 fadeNormed(fc.r / 255.f, fc.g/ 255.f, fc.b/ 255.f, a);

		glUniform4fv(ssRectColour, 1, glm::value_ptr(fadeNormed));

		glBindVertexArray( ssRectDraw.getVAOName() );
		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	}

	if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) {
		renderLetterbox();
	}

	renderPostProcess();

	glUseProgram(0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glBindVertexArray( 0 );
}