Esempio n. 1
0
void CRender::Calculate				()
{
	#ifdef _GPA_ENABLED	
		TAL_SCOPED_TASK_NAMED( "CRender::Calculate()" );
	#endif // _GPA_ENABLED

	Device.Statistic->RenderCALC.Begin();

	// Transfer to global space to avoid deep pointer access
	IRender_Target* T				=	getTarget	();
	float	fov_factor				=	_sqr		(90.f / Device.fFOV);
	g_fSCREEN						=	float(T->get_width()*T->get_height())*fov_factor*(EPS_S+ps_r__LOD);
	r_ssaDISCARD					=	_sqr(ps_r__ssaDISCARD)		/g_fSCREEN;
	r_ssaDONTSORT					=	_sqr(ps_r__ssaDONTSORT/3)	/g_fSCREEN;
	r_ssaLOD_A						=	_sqr(ps_r1_ssaLOD_A/3)		/g_fSCREEN;
	r_ssaLOD_B						=	_sqr(ps_r1_ssaLOD_B/3)		/g_fSCREEN;
	r_ssaGLOD_start					=	_sqr(ps_r__GLOD_ssa_start/3)/g_fSCREEN;
	r_ssaGLOD_end					=	_sqr(ps_r__GLOD_ssa_end/3)	/g_fSCREEN;
	r_ssaHZBvsTEX					=	_sqr(ps_r__ssaHZBvsTEX/3)	/g_fSCREEN;

	// Frustum & HOM rendering
	ViewBase.CreateFromMatrix		(Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR);
	View							= 0;
	HOM.Enable						();
	HOM.Render						(ViewBase);
	gm_SetNearer					(FALSE);
	phase							= PHASE_NORMAL;

	// Detect camera-sector
	if (!vLastCameraPos.similar(Device.vCameraPosition,EPS_S)) 
	{
		CSector* pSector		= (CSector*)detectSector(Device.vCameraPosition);
		if (pSector && (pSector!=pLastSector))
			g_pGamePersistent->OnSectorChanged( translateSector(pSector) );

		if (0==pSector) pSector = pLastSector;
		pLastSector = pSector;
		vLastCameraPos.set(Device.vCameraPosition);
	}

	// Check if camera is too near to some portal - if so force DualRender
	if (rmPortals) 
	{
		Fvector box_radius;		box_radius.set(EPS_L*2,EPS_L*2,EPS_L*2);
		Sectors_xrc.box_options	(CDB::OPT_FULL_TEST);
		Sectors_xrc.box_query	(rmPortals,Device.vCameraPosition,box_radius);
		for (int K=0; K<Sectors_xrc.r_count(); K++)
		{
			CPortal*	pPortal		= (CPortal*) Portals[rmPortals->get_tris()[Sectors_xrc.r_begin()[K].id].dummy];
			pPortal->bDualRender	= TRUE;
		}
	}
	//
	if (L_DB)
		L_DB->Update();

	// Main process
	marker	++;
	if (pLastSector)
	{
		// Traverse sector/portal structure
		PortalTraverser.traverse	
			(
			pLastSector,
			ViewBase,
			Device.vCameraPosition,
			Device.mFullTransform,
			CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE
			);

		// Determine visibility for static geometry hierrarhy
		if  (psDeviceFlags.test(rsDrawStatic))	{
			for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++)
			{
				CSector*	sector		= (CSector*)PortalTraverser.r_sectors[s_it];
				dxRender_Visual*	root	= sector->root();
				for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++)
				{
					set_Frustum			(&(sector->r_frustums[v_it]));
					add_Geometry		(root);
				}
			}
		}

		// Traverse object database
		if  (psDeviceFlags.test(rsDrawDynamic))	{
			g_SpatialSpace->q_frustum
				(
				lstRenderables,
				ISpatial_DB::O_ORDERED,
				STYPE_RENDERABLE + STYPE_LIGHTSOURCE,
				ViewBase
				);

			// Exact sorting order (front-to-back)
			std::sort							(lstRenderables.begin(),lstRenderables.end(),pred_sp_sort);

			// Determine visibility for dynamic part of scene
			set_Object							(0);
			g_hud->Render_First					( );	// R1 shadows
			g_hud->Render_Last					( );	
			u32 uID_LTRACK						= 0xffffffff;
			if (phase==PHASE_NORMAL)			{
				uLastLTRACK	++;
				if (lstRenderables.size())		uID_LTRACK	= uLastLTRACK%lstRenderables.size();

				// update light-vis for current entity / actor
				CObject*	O					= g_pGameLevel->CurrentViewEntity();
				if (O)		{
					CROS_impl*	R					= (CROS_impl*) O->ROS();
					if (R)		R->update			(O);
				}
			}
			for (u32 o_it=0; o_it<lstRenderables.size(); o_it++)
			{
				ISpatial*	spatial		= lstRenderables[o_it];		spatial->spatial_updatesector	();
				CSector*	sector		= (CSector*)spatial->spatial.sector	;
				if	(0==sector)										
					continue;	// disassociated from S/P structure

				// Filter only not light spatial
				if	(PortalTraverser.i_marker != sector->r_marker && (spatial->spatial.type & STYPE_RENDERABLE) )	continue;	// inactive (untouched) sector

				if (spatial->spatial.type & STYPE_RENDERABLE)
				{
					for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++)
					{
						set_Frustum			(&(sector->r_frustums[v_it]));

						if (!View->testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) /*&& (spatial->spatial.type & STYPE_RENDERABLE)*/)	continue;
						// renderable
						IRenderable*	renderable		= spatial->dcast_Renderable	();
						if (0==renderable)	{
							// It may be an glow
							CGlow*		glow				= dynamic_cast<CGlow*>(spatial);
							VERIFY							(glow);
							L_Glows->add					(glow);
						} else {
							// Occlusiond
							vis_data&		v_orig			= renderable->renderable.visual->getVisData();
							vis_data		v_copy			= v_orig;
							v_copy.box.xform				(renderable->renderable.xform);
							BOOL			bVisible		= HOM.visible(v_copy);
							v_orig.accept_frame				= v_copy.accept_frame;
							v_orig.marker					= v_copy.marker;
							v_orig.hom_frame				= v_copy.hom_frame;
							v_orig.hom_tested				= v_copy.hom_tested;
							if (!bVisible)					break;	// exit loop on frustums

							// rendering
							if (o_it==uID_LTRACK && renderable->renderable_ROS())	{
								// track lighting environment
								CROS_impl*		T = (CROS_impl*)renderable->renderable_ROS();
								T->update			(renderable);
							}
							set_Object						(renderable);
							renderable->renderable_Render	();
							set_Object						(0);	//? is it needed at all
						}
						break;	// exit loop on frustums
					}
				} 
				else
				{
					if ( ViewBase.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R) )
					{
						VERIFY								(spatial->spatial.type & STYPE_LIGHTSOURCE);
						// lightsource
						light*			L					= (light*)	spatial->dcast_Light	();
						VERIFY								(L);
						if (L->spatial.sector)				{
							vis_data&		vis		= L->get_homdata	( );
							if	(HOM.visible(vis))	L_DB->add_light		(L);
						}
					}
				}
			}
		}

		// Calculate miscelaneous stuff
		L_Shadows->calculate								();
		L_Projector->calculate								();
	}
	else
	{
		set_Object											(0);
		/*
		g_pGameLevel->pHUD->Render_First					();	
		g_pGameLevel->pHUD->Render_Last						();	

		// Calculate miscelaneous stuff
		L_Shadows->calculate								();
		L_Projector->calculate								();
		*/
	}

	// End calc
	Device.Statistic->RenderCALC.End	();
}
Esempio n. 2
0
void	CROS_impl::update	(IRenderable* O)
{
	// clip & verify
	if					(dwFrame==Device.dwFrame)			return;
	dwFrame				= Device.dwFrame;
	if					(0==O)								return;
	if					(0==O->renderable.visual)			return;
	VERIFY				(dynamic_cast<CROS_impl*>			(O->renderable_ROS()));
	float	dt			=	Device.fTimeDelta;

	CObject*	_object	= dynamic_cast<CObject*>	(O);

	// select sample, randomize position inside object
	Fvector	position;	O->renderable.xform.transform_tiny	(position,O->renderable.visual->vis.sphere.P);
	float	radius;		radius	= O->renderable.visual->vis.sphere.R;
	position.y			+=  .3f * radius;
	Fvector	direction;	direction.random_dir();
//.			position.mad(direction,0.25f*radius);
//.			position.mad(direction,0.025f*radius);

	// sun-tracing
#if RENDER==R_R1
	light*	sun		=		(light*)RImplementation.L_DB->sun_adapted._get()	;
#else
	light*	sun		=		(light*)RImplementation.Lights.sun_adapted._get()	;
#endif
	if	(MODE & IRender_ObjectSpecific::TRACE_SUN)	{
		if  (--result_sun	< 0)	{
			result_sun		+=		::Random.randI(lt_hemisamples/4,lt_hemisamples/2)	;
			Fvector	direction;	direction.set	(sun->direction).invert().normalize	();
			sun_value		=	!(g_pGameLevel->ObjectSpace.RayTest(position,direction,500.f,collide::rqtBoth,&cache_sun,_object))?1.f:0.f;
		}
	}
	
	// hemi-tracing
	bool	bFirstTime	=	(0==result_count);
	if	(MODE & IRender_ObjectSpecific::TRACE_HEMI)	{
		for (u32 it=0; it<(u32)ps_r2_dhemi_count;	it++)		{	// five samples per one frame
			u32	sample		=	0				;
			if	(result_count<lt_hemisamples)	{ sample=result_count; result_count++;							}
			else								{ sample=(result_iterator%lt_hemisamples); result_iterator++;	}

			// take sample
			Fvector	direction;	direction.set	(hdir[sample][0],hdir[sample][1],hdir[sample][2]).normalize	();
//.			result[sample]	=	!g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtBoth,&cache[sample],_object);
			result[sample]	=	!g_pGameLevel->ObjectSpace.RayTest(position,direction,50.f,collide::rqtStatic,&cache[sample],_object);
			//	Msg				("%d:-- %s",sample,result[sample]?"true":"false");
		}
	}

	// hemi & sun: update and smooth
//	float	l_f				=	dt*lt_smooth;
//	float	l_i				=	1.f-l_f;
	int		_pass			=	0;
	for (int it=0; it<result_count; it++)	if (result[it])	_pass	++;
	hemi_value				=	float	(_pass)/float(result_count?result_count:1);
	hemi_value				*=	ps_r2_dhemi_scale;
	if (bFirstTime)			hemi_smooth		= hemi_value;
	update_smooth			()	;

	// light-tracing
	BOOL	bTraceLights	= MODE & IRender_ObjectSpecific::TRACE_LIGHTS;
	if		((!O->renderable_ShadowGenerate()) && (!O->renderable_ShadowReceive()))	bTraceLights = FALSE;
	if		(bTraceLights)	{
		// Select nearest lights
		Fvector					bb_size	=	{radius,radius,radius};
		g_SpatialSpace->q_box				(RImplementation.lstSpatial,0,STYPE_LIGHTSOURCE,position,bb_size);
		for (u32 o_it=0; o_it<RImplementation.lstSpatial.size(); o_it++)	{
			ISpatial*	spatial		= RImplementation.lstSpatial[o_it];
			light*		source		= (light*)	(spatial->dcast_Light());
			VERIFY		(source);	// sanity check
			float	R				= radius+source->range;
			if (position.distance_to(source->position) < R)		add	(source);
		}

		// Trace visibility
		lights.clear	();
		float traceR	= radius*.5f;
		for (s32 id=0; id<s32(track.size()); id++)
		{
			// remove untouched lights
			xr_vector<CROS_impl::Item>::iterator I	= track.begin()+id;
			if (I->frame_touched!=Device.dwFrame)	{ track.erase(I) ; id--	; continue ; }

			// Trace visibility
			Fvector				P,D;
			float		amount	= 0;
			light*		xrL		= I->source;
			Fvector&	LP		= xrL->position;
			P.mad				(position,P.random_dir(),traceR);		// Random point inside range

			// point/spot
			float	f			=	D.sub(P,LP).magnitude();
			if (g_pGameLevel->ObjectSpace.RayTest(LP,D.div(f),f,collide::rqtStatic,&I->cache,_object))	amount -=	lt_dec;
			else																						amount +=	lt_inc;
			I->test				+=	amount * dt;	clamp	(I->test,-.5f,1.f);
			I->energy			=	.9f*I->energy + .1f*I->test;

			// 
			float	E			=	I->energy * xrL->color.intensity	();
			if (E > EPS)		{
				// Select light
				lights.push_back			(CROS_impl::Light())		;
				CROS_impl::Light&	L		= lights.back()				;
				L.source					= xrL						;
				L.color.mul_rgb				(xrL->color,I->energy/2)	;
				L.energy					= I->energy/2				;
				if (!xrL->flags.bStatic)	{ L.color.mul_rgb(.5f); L.energy *= .5f; }
			}
		}

		// Sun
		float	E			=	sun_smooth * sun->color.intensity	();
		if (E > EPS)		{
			// Select light
			lights.push_back			(CROS_impl::Light())		;
			CROS_impl::Light&	L		= lights.back()				;
			L.source					= sun						;
			L.color.mul_rgb				(sun->color,sun_smooth/2)	;
			L.energy					= sun_smooth				;
		}

		// Sort lights by importance - important for R1-shadows
		std::sort	(lights.begin(),lights.end(), pred_energy);
	}

	// Process ambient lighting and approximate average lighting
	// Process our lights to find average luminiscense
	CEnvDescriptor&	desc	=	g_pGamePersistent->Environment().CurrentEnv;
	Fvector			accum	=	{ desc.ambient.x,		desc.ambient.y,		desc.ambient.z		};
	Fvector			hemi	=	{ desc.hemi_color.x,	desc.hemi_color.y,	desc.hemi_color.z	};
	Fvector			sun_	=	{ desc.sun_color.x,		desc.sun_color.y,	desc.sun_color.z	};
	if (MODE & IRender_ObjectSpecific::TRACE_HEMI	)	hemi.mul(hemi_smooth); else hemi.mul(.2f);
					accum.add	( hemi );
	if (MODE & IRender_ObjectSpecific::TRACE_SUN	)	sun_.mul(sun_smooth); else sun_.mul(.2f);
					accum.add	( sun_ );
	if (MODE & IRender_ObjectSpecific::TRACE_LIGHTS )	{
		Fvector		lacc	=	{ 0,0,0 };
		for (u32 lit=0; lit<lights.size(); lit++)	{
			float	d	=	lights[lit].source->position.distance_to(position);
			float	r	=	lights[lit].source->range;
			float	a	=	clampr(1.f - d/(r+EPS),0.f,1.f)*(lights[lit].source->flags.bStatic?1.f:2.f);
			lacc.x		+=	lights[lit].color.r*a;
			lacc.y		+=	lights[lit].color.g*a;
			lacc.z		+=	lights[lit].color.b*a;
		}
//		lacc.x		*= desc.lmap_color.x;
//		lacc.y		*= desc.lmap_color.y;
//		lacc.z		*= desc.lmap_color.z;
//		Msg				("- rgb[%f,%f,%f]",lacc.x,lacc.y,lacc.z);
		accum.add		(lacc);
	} else 			accum.set	( .1f, .1f, .1f );
	approximate				=	accum;
}
Esempio n. 3
0
void dx103DFluidRenderer::CalculateLighting(const dx103DFluidData &FluidData, FogLighting  &LightData)
{
	m_lstRenderables.clear_not_free();

	LightData.Reset();

	const dx103DFluidData::Settings &VolumeSettings = FluidData.GetSettings();

	Fvector4 hemi_color = g_pGamePersistent->Environment().CurrentEnv->hemi_color;
	//hemi_color.mul(0.2f);
	hemi_color.mul(VolumeSettings.m_fHemi);
	LightData.m_vLightIntencity.set(hemi_color.x, hemi_color.y, hemi_color.z);
	LightData.m_vLightIntencity.add(g_pGamePersistent->Environment().CurrentEnv->ambient);

	const Fmatrix &Transform = FluidData.GetTransform();

	Fbox	box;
	box.min = Fvector3().set(-0.5f, -0.5f, -0.5f);
	box.max = Fvector3().set( 0.5f,  0.5f,  0.5f);
	box.xform(Transform);
	Fvector3	center;
	Fvector3	size;
	box.getcenter(center);
	box.getradius(size);


	// Traverse object database
	g_SpatialSpace->q_box
		(
		m_lstRenderables,
		0, //ISpatial_DB::O_ORDERED,
		STYPE_LIGHTSOURCE,
		center,
		size
		);

	u32 iNumRenderables = m_lstRenderables.size();
	// Determine visibility for dynamic part of scene
	for (u32 i=0; i<iNumRenderables; ++i)
	{
		ISpatial*	spatial		= m_lstRenderables[i];

		// Light
		light*	pLight = (light*) spatial->dcast_Light();
		VERIFY(pLight);

		if (pLight->flags.bStatic) continue;

		float	d	=	pLight->position.distance_to(Transform.c);

		float	R				= pLight->range + _max( size.x, _max( size.y, size.z ) );
		if ( d >= R )
			continue;

		Fvector3	LightIntencity;

		LightIntencity.set(pLight->color.r, pLight->color.g, pLight->color.b);

		//LightIntencity.mul(0.5f);

		//if (!pLight->flags.bStatic)
		//	LightIntencity.mul(0.5f);

		float	r	=	pLight->range;
		float	a	=	clampr(1.f - d/(r+EPS),0.f,1.f)*(pLight->flags.bStatic?1.f:2.f);

		LightIntencity.mul(a);

		LightData.m_vLightIntencity.add(LightIntencity);
	}

	//LightData.m_vLightIntencity.set( 1.0f, 0.5f, 0.0f);
	//LightData.m_vLightIntencity.set( 1.0f, 1.0f, 1.0f);
}
Esempio n. 4
0
void CRender::render_main	(Fmatrix&	m_ViewProjection, bool _fportals)
{
//	Msg						("---begin");
	marker					++;

	// Calculate sector(s) and their objects
	if (pLastSector)		{
		//!!!
		//!!! BECAUSE OF PARALLEL HOM RENDERING TRY TO DELAY ACCESS TO HOM AS MUCH AS POSSIBLE
		//!!!
		{
			// Traverse object database
			g_SpatialSpace->q_frustum
				(
				lstRenderables,
				ISpatial_DB::O_ORDERED,
				STYPE_RENDERABLE + STYPE_LIGHTSOURCE,
				ViewBase
				);

			// (almost) Exact sorting order (front-to-back)
			std::sort			(lstRenderables.begin(),lstRenderables.end(),pred_sp_sort);

			// Determine visibility for dynamic part of scene
			set_Object							(0);
			u32 uID_LTRACK						= 0xffffffff;
			if (phase==PHASE_NORMAL)			{
				uLastLTRACK	++;
				if (lstRenderables.size())		uID_LTRACK	= uLastLTRACK%lstRenderables.size();

				// update light-vis for current entity / actor
				CObject*	O					= g_pGameLevel->CurrentViewEntity();
				if (O)		{
					CROS_impl*	R					= (CROS_impl*) O->ROS();
					if (R)		R->update			(O);
				}

				// update light-vis for selected entity
				// track lighting environment
				if (lstRenderables.size())		{
					IRenderable*	renderable		= lstRenderables[uID_LTRACK]->dcast_Renderable	();
					if (renderable)	{
						CROS_impl*		T = (CROS_impl*)renderable->renderable_ROS	();
						if (T)			T->update	(renderable);
					}
				}
			}
		}

		// Traverse sector/portal structure
		PortalTraverser.traverse	
			(
			pLastSector,
			ViewBase,
			Device.vCameraPosition,
			m_ViewProjection,
			CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE
			//. disabled scissoring (HW.Caps.bScissor?CPortalTraverser::VQ_SCISSOR:0)	// generate scissoring info
			);

		// Determine visibility for static geometry hierrarhy
		for (u32 s_it=0; s_it<PortalTraverser.r_sectors.size(); s_it++)
		{
			CSector*	sector		= (CSector*)PortalTraverser.r_sectors[s_it];
			IRender_Visual*	root	= sector->root();
			for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++)	{
				set_Frustum			(&(sector->r_frustums[v_it]));
				add_Geometry		(root);
			}
		}

		// Traverse frustums
		for (u32 o_it=0; o_it<lstRenderables.size(); o_it++)
		{
			ISpatial*	spatial		= lstRenderables[o_it];		spatial->spatial_updatesector	();
			CSector*	sector		= (CSector*)spatial->spatial.sector;
			if	(0==sector)										continue;	// disassociated from S/P structure

			if (spatial->spatial.type & STYPE_LIGHTSOURCE)		{
				// lightsource
				light*			L				= (light*)	(spatial->dcast_Light());
				VERIFY							(L);
				float	lod		= L->get_LOD	();
				if (lod>EPS_L)	{
					vis_data&		vis		= L->get_homdata	( );
					if	(HOM.visible(vis))	Lights.add_light	(L);
				}
				continue					;
			}

			if	(PortalTraverser.i_marker != sector->r_marker)	continue;	// inactive (untouched) sector
			for (u32 v_it=0; v_it<sector->r_frustums.size(); v_it++)	{
				CFrustum&	view	= sector->r_frustums[v_it];
				if (!view.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R))	continue;

				if (spatial->spatial.type & STYPE_RENDERABLE)
				{
					// renderable
					IRenderable*	renderable		= spatial->dcast_Renderable	();
					VERIFY							(renderable);

					// Occlusion
					vis_data&		v_orig			= renderable->renderable.visual->vis;
					vis_data		v_copy			= v_orig;
					v_copy.box.xform				(renderable->renderable.xform);
					BOOL			bVisible		= HOM.visible(v_copy);
					v_orig.marker					= v_copy.marker;
					v_orig.accept_frame				= v_copy.accept_frame;
					v_orig.hom_frame				= v_copy.hom_frame;
					v_orig.hom_tested				= v_copy.hom_tested;
					if (!bVisible)					break;	// exit loop on frustums

					// Rendering
					set_Object						(renderable);
					renderable->renderable_Render	();
					set_Object						(0);
				}
				break;	// exit loop on frustums
			}
		}
		if (g_pGameLevel && (phase==PHASE_NORMAL))	g_pGameLevel->pHUD->Render_Last();		// HUD
	}
	else
	{
		set_Object									(0);
		if (g_pGameLevel && (phase==PHASE_NORMAL))	g_pGameLevel->pHUD->Render_Last();		// HUD
	}
}