Пример #1
0
void CLightProjector::calculate	()
{
	#ifdef _GPA_ENABLED	
		TAL_SCOPED_TASK_NAMED( "CLightProjector::calculate()" );
	#endif // _GPA_ENABLED

	if (receivers.empty())		return;

	// perform validate / markup
	for (u32 r_it=0; r_it<receivers.size(); r_it++)
	{
		// validate
		BOOL				bValid	= TRUE;
		IRenderable*		O		= receivers[r_it];
		CROS_impl*			LT		= (CROS_impl*)O->renderable_ROS();
		int					slot	= LT->shadow_recv_slot;
		if (slot<0 || slot>=P_o_count)								bValid = FALSE;	// invalid slot
		else if (cache[slot].O!=O)									bValid = FALSE;	// not the same object
		else {
			// seems to be valid
			Fbox	bb;		bb.xform		(O->renderable.visual->getVisData().box,O->renderable.xform);
			if (cache[slot].BB.contains(bb))	{
				// inside, but maybe timelimit exceeded?
				if (Device.dwTimeGlobal > cache[slot].dwTimeValid)	bValid = FALSE;	// timeout
			} else													bValid = FALSE;	// out of bounds
		}

		// 
		if (bValid)			{
			// Ok, use cached version
			cache[slot].dwFrame	= Device.dwFrame;
		} else {
			taskid.push_back	(r_it);
		}
	}
	if (taskid.empty())			return;

	// Begin
	Device.Statistic->RenderDUMP_Pcalc.Begin	();
	RCache.set_RT				(RT->pRT);
	RCache.set_ZB				(RImplementation.Target->pTempZB);
	CHK_DX(HW.pDevice->Clear	(0,0, D3DCLEAR_ZBUFFER | (HW.Caps.bStencil?D3DCLEAR_STENCIL:0), 0,1,0 ));
	RCache.set_xform_world		(Fidentity);

	// reallocate/reassociate structures + perform all the work
	for (u32 c_it=0; c_it<cache.size(); c_it++)
	{
		if (taskid.empty())							break;
		if (Device.dwFrame==cache[c_it].dwFrame)	continue;

		// found not used slot
		int				tid		= taskid.back();	taskid.pop_back();
		recv&			R		= cache		[c_it];
		IRenderable*	O		= receivers	[tid];
		const vis_data& vis = O->renderable.visual->getVisData();
		CROS_impl*	LT		= (CROS_impl*)O->renderable_ROS();
		VERIFY2			(_valid(O->renderable.xform),"Invalid object transformation");
		VERIFY2			(_valid(vis.sphere.P),"Invalid object's visual sphere");

		Fvector			C;		O->renderable.xform.transform_tiny		(C,vis.sphere.P);
		R.O						= O;
		R.C						= C;
		R.C.y					+= vis.sphere.R*0.1f;		//. YURA: 0.1 can be more
		R.BB.xform				(vis.box,O->renderable.xform).scale(0.1f);
		R.dwTimeValid			= Device.dwTimeGlobal + ::Random.randI(time_min,time_max);
		LT->shadow_recv_slot	= c_it; 

		// Msg					("[%f,%f,%f]-%f",C.C.x,C.C.y,C.C.z,C.O->renderable.visual->vis.sphere.R);
		// calculate projection-matrix
		Fmatrix		mProject;
		float		p_R			=	R.O->renderable.visual->getVisData().sphere.R * 1.1f;
		//VERIFY2		(p_R>EPS_L,"Object has no physical size");
		VERIFY3		(p_R>EPS_L,"Object has no physical size", R.O->renderable.visual->getDebugName().c_str());
		float		p_hat		=	p_R/P_cam_dist;
		float		p_asp		=	1.f;
		float		p_near		=	P_cam_dist-EPS_L;									
		float		p_far		=	P_cam_dist+p_R+P_cam_range;	
		mProject.build_projection_HAT	(p_hat,p_asp,p_near,p_far);
		RCache.set_xform_project		(mProject);
		
		// calculate view-matrix
		Fmatrix		mView;
		Fvector		v_C, v_Cs, v_N;
		v_C.set					(R.C);
		v_Cs					= v_C;
		v_C.y					+=	P_cam_dist;
		v_N.set					(0,0,1);
		VERIFY					(_valid(v_C) && _valid(v_Cs) && _valid(v_N));

		// validate
		Fvector		v;
		v.sub		(v_Cs,v_C);;
#ifdef DEBUG
		if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero)	{
			CObject* OO = dynamic_cast<CObject*>(R.O);
			Msg("Object[%s] Visual[%s] has invalid position. ",*OO->cName(),*OO->cNameVisual());
			Fvector cc;
			OO->Center(cc);
			Log("center=",cc);

			Log("visual_center=",OO->Visual()->getVisData().sphere.P);
			
			Log("full_matrix=",OO->XFORM());

			Log	("v_N",v_N);
			Log	("v_C",v_C);
			Log	("v_Cs",v_Cs);

			Log("all bones transform:--------");
			CKinematics* K = dynamic_cast<CKinematics*>(OO->Visual());
			
			for(u16 ii=0; ii<K->LL_BoneCount();++ii){
				Fmatrix tr;

				tr = K->LL_GetTransform(ii);
				Log("bone ",K->LL_BoneName_dbg(ii));
				Log("bone_matrix",tr);
			}
			Log("end-------");
		}
#endif
		// handle invalid object-bug
		if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero)	{
			// invalidate record, so that object will be unshadowed, but doesn't crash
			R.dwTimeValid			= Device.dwTimeGlobal;
			LT->shadow_recv_frame	= Device.dwFrame-1;
			LT->shadow_recv_slot	= -1; 
			continue				;
		}

		mView.build_camera		(v_C,v_Cs,v_N);
		RCache.set_xform_view	(mView);

		// Select slot, set viewport
		int		s_x				=	c_it%P_o_line;
		int		s_y				=	c_it/P_o_line;
		D3DVIEWPORT9 VP			=	{s_x*P_o_size,s_y*P_o_size,P_o_size,P_o_size,0,1 };
		CHK_DX					(HW.pDevice->SetViewport(&VP));

		// Clear color to ambience
		Fvector&	cap			=	LT->get_approximate();
		CHK_DX					(HW.pDevice->Clear(0,0, D3DCLEAR_TARGET, color_rgba_f(cap.x,cap.y,cap.z, (cap.x+cap.y+cap.z)/4.f), 1, 0 ));

		// calculate uv-gen matrix and clamper
		Fmatrix					mCombine;		mCombine.mul	(mProject,mView);
		Fmatrix					mTemp;
		float					fSlotSize		= float(P_o_size)/float(P_rt_size);
		float					fSlotX			= float(s_x*P_o_size)/float(P_rt_size);
		float					fSlotY			= float(s_y*P_o_size)/float(P_rt_size);
		float					fTexelOffs		= (.5f / P_rt_size);
		Fmatrix					m_TexelAdjust	= 
		{
			0.5f/*x-scale*/,	0.0f,							0.0f,				0.0f,
			0.0f,				-0.5f/*y-scale*/,				0.0f,				0.0f,
			0.0f,				0.0f,							1.0f/*z-range*/,	0.0f,
			0.5f/*x-bias*/,		0.5f + fTexelOffs/*y-bias*/,	0.0f/*z-bias*/,		1.0f
		};
		R.UVgen.mul				(m_TexelAdjust,mCombine);
		mTemp.scale				(fSlotSize,fSlotSize,1);
		R.UVgen.mulA_44			(mTemp);
		mTemp.translate			(fSlotX+fTexelOffs,fSlotY+fTexelOffs,0);
		R.UVgen.mulA_44			(mTemp);

		// Build bbox and render
		Fvector					min,max;
		Fbox					BB;
		min.set					(R.C.x-p_R,	R.C.y-(p_R+P_cam_range),	R.C.z-p_R);
		max.set					(R.C.x+p_R,	R.C.y+0,					R.C.z+p_R);
		BB.set					(min,max);
		R.UVclamp_min.set		(min).add	(.05f);	// shrink a little
		R.UVclamp_max.set		(max).sub	(.05f);	// shrink a little
		ISpatial*	spatial		= dynamic_cast<ISpatial*>	(O);
		if (spatial)			{
			spatial->spatial_updatesector			();
			if (spatial->spatial.sector)			RImplementation.r_dsgraph_render_R1_box	(spatial->spatial.sector,BB,SE_R1_LMODELS);
		}
		//if (spatial)		RImplementation.r_dsgraph_render_subspace	(spatial->spatial.sector,mCombine,v_C,FALSE);
	}

	// Blur
	/*
	{
		// Fill vertex buffer
		u32							Offset;
		FVF::TL4uv* pv				= (FVF::TL4uv*) RCache.Vertex.Lock	(4,geom_Blur.stride(),Offset);
		RImplementation.ApplyBlur4	(pv,P_rt_size,P_rt_size,P_blur_kernel);
		RCache.Vertex.Unlock		(4,geom_Blur.stride());

		// Actual rendering (pass0, temp2real)
		RCache.set_RT				(RT->pRT);
		RCache.set_ZB				(NULL);
		RCache.set_Shader			(sh_BlurTR	);
		RCache.set_Geometry			(geom_Blur	);
		RCache.Render				(D3DPT_TRIANGLELIST,Offset,0,4,0,2);
	}
	*/

	// Finita la comedia
	Device.Statistic->RenderDUMP_Pcalc.End	();
	
	RCache.set_xform_project	(Device.mProject);
	RCache.set_xform_view		(Device.mView);
}
Пример #2
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	();
}
Пример #3
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
	}
}