예제 #1
0
CRenderTarget::CRenderTarget		()
{
	param_blur			= 0.f;
	param_gray			= 0.f;
	param_noise			= 0.f;
	param_duality_h		= 0.f;
	param_duality_v		= 0.f;
	param_noise_fps		= 25.f;
	param_noise_scale	= 1.f;

	im_noise_time		= 1/100;
	im_noise_shift_w	= 0;
	im_noise_shift_h	= 0;

	param_color_base	= color_rgba(127,127,127,	0);
	param_color_gray	= color_rgba(85,85,85,		0);
	param_color_add.set( 0.0f, 0.0f, 0.0f );

	dwAccumulatorClearMark			= 0;
	dxRenderDeviceRender::Instance().Resources->Evict			();

	// Blenders
	b_occq							= new CBlender_light_occq();
	b_accum_mask					= new CBlender_accum_direct_mask();
	b_accum_direct					= new CBlender_accum_direct();
	b_accum_point					= new CBlender_accum_point();
	b_accum_spot					= new CBlender_accum_spot();
	b_accum_reflected				= new CBlender_accum_reflected();
	b_bloom							= new CBlender_bloom_build();
	b_ssao							= new CBlender_SSAO();
	b_luminance						= new CBlender_luminance();
	b_combine						= new CBlender_combine();

	//	NORMAL
	{
		u32		w=Device.dwWidth, h=Device.dwHeight;
		rt_Position.create			(r2_RT_P,		w,h,D3DFMT_A16B16G16R16F);
		rt_Normal.create			(r2_RT_N,		w,h,D3DFMT_A16B16G16R16F);

		// select albedo & accum
		if (RImplementation.o.mrtmixdepth)	
		{
			// NV50
			rt_Color.create			(r2_RT_albedo,	w,h,D3DFMT_A8R8G8B8		);
			rt_Accumulator.create	(r2_RT_accum,	w,h,D3DFMT_A16B16G16R16F);
		}
		else		
		{
			// can't - mix-depth
			if (RImplementation.o.fp16_blend) {
				// NV40
				rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A16B16G16R16F);	// expand to full
				rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F);
			} else {
				// R4xx, no-fp-blend,-> albedo_wo
				VERIFY						(RImplementation.o.albedo_wo);
				rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A8R8G8B8		);	// normal
				rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F);
				rt_Accumulator_temp.create	(r2_RT_accum_temp,	w,h,D3DFMT_A16B16G16R16F);
			}
		}

		// generic(LDR) RTs
		rt_Generic_0.create			(r2_RT_generic0,w,h,D3DFMT_A8R8G8B8		);
		rt_Generic_1.create			(r2_RT_generic1,w,h,D3DFMT_A8R8G8B8		);
		//	Igor: for volumetric lights
		//rt_Generic_2.create			(r2_RT_generic2,w,h,D3DFMT_A8R8G8B8		);
		//	temp: for higher quality blends
		if (RImplementation.o.advancedpp)
			rt_Generic_2.create			(r2_RT_generic2,w,h,D3DFMT_A16B16G16R16F);
	}

	// OCCLUSION
	s_occq.create					(b_occq,		"r2\\occq");

	// DIRECT (spot)
	D3DFORMAT						depth_format	= (D3DFORMAT)RImplementation.o.HW_smap_FORMAT;

	if (RImplementation.o.HW_smap)
	{
		D3DFORMAT	nullrt				= D3DFMT_R5G6B5;
		if (RImplementation.o.nullrt)	nullrt	= (D3DFORMAT)MAKEFOURCC('N','U','L','L');

		u32	size					=RImplementation.o.smapsize	;
		rt_smap_depth.create		(r2_RT_smap_depth,			size,size,depth_format	);
		rt_smap_surf.create			(r2_RT_smap_surf,			size,size,nullrt		);
		rt_smap_ZB					= NULL;
		s_accum_mask.create			(b_accum_mask,				"r2\\accum_mask");
		s_accum_direct.create		(b_accum_direct,			"r2\\accum_direct");
		if (RImplementation.o.advancedpp)
			s_accum_direct_volumetric.create("accum_volumetric_sun");
	}
	else
	{
		u32	size					=RImplementation.o.smapsize	;
		rt_smap_surf.create			(r2_RT_smap_surf,			size,size,D3DFMT_R32F);
		rt_smap_depth				= NULL;
		R_CHK						(HW.pDevice->CreateDepthStencilSurface	(size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL));
		s_accum_mask.create			(b_accum_mask,				"r2\\accum_mask");
		s_accum_direct.create		(b_accum_direct,			"r2\\accum_direct");
		if (RImplementation.o.advancedpp)
			s_accum_direct_volumetric.create("accum_volumetric_sun");
	}

	// POINT
	{
		s_accum_point.create		(b_accum_point,				"r2\\accum_point_s");
		accum_point_geom_create		();
		g_accum_point.create		(D3DFVF_XYZ,				g_accum_point_vb, g_accum_point_ib);
		accum_omnip_geom_create		();
		g_accum_omnipart.create		(D3DFVF_XYZ,				g_accum_omnip_vb, g_accum_omnip_ib);
	}

	// SPOT
	{
		s_accum_spot.create			(b_accum_spot,				"r2\\accum_spot_s",	"lights\\lights_spot01");
		accum_spot_geom_create		();
		g_accum_spot.create			(D3DFVF_XYZ,				g_accum_spot_vb, g_accum_spot_ib);
	}

	{
		s_accum_volume.create("accum_volumetric", "lights\\lights_spot01");
		accum_volumetric_geom_create();
		g_accum_volumetric.create( D3DFVF_XYZ, g_accum_volumetric_vb, g_accum_volumetric_ib);
	}
			

	// REFLECTED
	{
		s_accum_reflected.create	(b_accum_reflected,			"r2\\accum_refl");
	}

	// BLOOM
	{
		D3DFORMAT	fmt				= D3DFMT_A8R8G8B8;			//;		// D3DFMT_X8R8G8B8
		u32	w=BLOOM_size_X, h=BLOOM_size_Y;
		u32 fvf_build				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
		u32 fvf_filter				= (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7);
		rt_Bloom_1.create			(r2_RT_bloom1,	w,h,		fmt);
		rt_Bloom_2.create			(r2_RT_bloom2,	w,h,		fmt);
		g_bloom_build.create		(fvf_build,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_bloom_filter.create		(fvf_filter,	RCache.Vertex.Buffer(), RCache.QuadIB);
		s_bloom_dbg_1.create		("effects\\screen_set",		r2_RT_bloom1);
		s_bloom_dbg_2.create		("effects\\screen_set",		r2_RT_bloom2);
		s_bloom.create				(b_bloom,					"r2\\bloom");
		f_bloom_factor				= 0.5f;
	}

	//HBAO
	if (RImplementation.o.ssao_opt_data)
	{
		u32		w = 0;
		u32		h = 0;
		if (RImplementation.o.ssao_half_data)
		{
			w = Device.dwWidth / 2;
			h = Device.dwHeight / 2;
		}
		else
		{
			w = Device.dwWidth;
			h = Device.dwHeight;
		}
		D3DFORMAT	fmt = HW.Caps.id_vendor==0x10DE?D3DFMT_R32F:D3DFMT_R16F;

		rt_half_depth.create		(r2_RT_half_depth, w, h, fmt);
		s_ssao.create				(b_ssao, "r2\\ssao");
	}

	//SSAO
	if (RImplementation.o.ssao_blur_on)
	{
		u32		w = Device.dwWidth, h = Device.dwHeight;
		rt_ssao_temp.create			(r2_RT_ssao_temp, w, h, D3DFMT_G16R16F);
		s_ssao.create				(b_ssao, "r2\\ssao");
	}

	// TONEMAP
	{
		rt_LUM_64.create			(r2_RT_luminance_t64,	64, 64,	D3DFMT_A16B16G16R16F	);
		rt_LUM_8.create				(r2_RT_luminance_t8,	8,	8,	D3DFMT_A16B16G16R16F	);
		s_luminance.create			(b_luminance,				"r2\\luminance");
		f_luminance_adapt			= 0.5f;

		t_LUM_src.create			(r2_RT_luminance_src);
		t_LUM_dest.create			(r2_RT_luminance_cur);

		// create pool
		for (u32 it=0; it<HW.Caps.iGPUNum*2; it++)	{
			string256					name;
			sprintf						(name,"%s_%d",	r2_RT_luminance_pool,it	);
			rt_LUM_pool[it].create		(name,	1,	1,	D3DFMT_R32F				);
			u_setrt						(rt_LUM_pool[it],	0,	0,	0			);
			CHK_DX						(HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,	0x7f7f7f7f,	1.0f, 0L));
		}
		u_setrt						( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB);
	}

	// COMBINE
	{
		static D3DVERTEXELEMENT9 dwDecl[] =
		{
			{ 0, 0,  D3DDECLTYPE_FLOAT4,	D3DDECLMETHOD_DEFAULT, 	D3DDECLUSAGE_POSITION,	0 },	// pos+uv
			{ 0, 16, D3DDECLTYPE_D3DCOLOR,	D3DDECLMETHOD_DEFAULT, 	D3DDECLUSAGE_COLOR,		0 },
			{ 0, 20, D3DDECLTYPE_FLOAT2,	D3DDECLMETHOD_DEFAULT, 	D3DDECLUSAGE_TEXCOORD,	0 },
			D3DDECL_END()
		};
		s_combine.create					(b_combine,					"r2\\combine");
		s_combine_volumetric.create			("combine_volumetric");
		s_combine_dbg_0.create				("effects\\screen_set",		r2_RT_smap_surf		);	
		s_combine_dbg_1.create				("effects\\screen_set",		r2_RT_luminance_t8	);
		s_combine_dbg_Accumulator.create	("effects\\screen_set",		r2_RT_accum			);
		g_combine_VP.create					(dwDecl,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_combine.create					(FVF::F_TL,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_combine_2UV.create				(FVF::F_TL2uv,	RCache.Vertex.Buffer(), RCache.QuadIB);

		u32 fvf_aa_blur				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
		g_aa_blur.create			(fvf_aa_blur,	RCache.Vertex.Buffer(), RCache.QuadIB);

		u32 fvf_aa_AA				= D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6);
		g_aa_AA.create				(fvf_aa_AA,		RCache.Vertex.Buffer(), RCache.QuadIB);

		t_envmap_0.create			(r2_T_envs0);
		t_envmap_1.create			(r2_T_envs1);
	}

	// Build textures
	{
		// Build material(s)
		{
			// Surface
			R_CHK						(D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf));
			t_material					= dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material);
			t_material->surface_set		(t_material_surf);

			// Fill it (addr: x=dot(L,N),y=dot(L,H))
			D3DLOCKED_BOX				R;
			R_CHK						(t_material_surf->LockBox	(0,&R,0,0));
			for (u32 slice=0; slice<4; slice++)
			{
				for (u32 y=0; y<TEX_material_LdotH; y++)
				{
					for (u32 x=0; x<TEX_material_LdotN; x++)
					{
						u16*	p	=	(u16*)		(LPBYTE (R.pBits) + slice*R.SlicePitch + y*R.RowPitch + x*2);
						float	ld	=	float(x)	/ float	(TEX_material_LdotN-1);
						float	ls	=	float(y)	/ float	(TEX_material_LdotH-1) + EPS_S;
						ls			*=	powf(ld,1/32.f);
						float	fd,fs;

						switch	(slice)
						{
						case 0:	{ // looks like OrenNayar
							fd	= powf(ld,0.75f);		// 0.75
							fs	= powf(ls,16.f)*.5f;
								}	break;
						case 1:	{// looks like Blinn
							fd	= powf(ld,0.90f);		// 0.90
							fs	= powf(ls,24.f);
								}	break;
						case 2:	{ // looks like Phong
							fd	= ld;					// 1.0
							fs	= powf(ls*1.01f,128.f	);
								}	break;
						case 3:	{ // looks like Metal
							float	s0	=	_abs	(1-_abs	(0.05f*_sin(33.f*ld)+ld-ls));
							float	s1	=	_abs	(1-_abs	(0.05f*_cos(33.f*ld*ls)+ld-ls));
							float	s2	=	_abs	(1-_abs	(ld-ls));
							fd		=	ld;				// 1.0
							fs		=	powf	(_max(_max(s0,s1),s2), 24.f);
							fs		*=	powf	(ld,1/7.f);
								}	break;
						default:
							fd	= fs = 0;
						}
						s32		_d	=	clampr	(iFloor	(fd*255.5f),	0,255);
						s32		_s	=	clampr	(iFloor	(fs*255.5f),	0,255);
						if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1)))	{ _d = 255; _s=255;	}
						*p			=	u16		(_s*256 + _d);
					}
				}
			}
			R_CHK		(t_material_surf->UnlockBox	(0));
			// #ifdef DEBUG
			// R_CHK	(D3DXSaveTextureToFile	("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0));
			// #endif
		}

		// Build noise table
		if (1)
		{
			// Surfaces
			D3DLOCKED_RECT				R[TEX_jitter_count];
			for (int it1=0; it1<TEX_jitter_count-1; it1++)
			{
				string_path					name;
				sprintf						(name,"%s%d",r2_jitter,it1);
				R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it1]));
				t_noise[it1]					= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(name);
				t_noise[it1]->surface_set	(t_noise_surf[it1]);
				R_CHK						(t_noise_surf[it1]->LockRect	(0,&R[it1],0,0));
			}	

			// Fill it,
			for (u32 y=0; y<TEX_jitter; y++)
			{
				for (u32 x=0; x<TEX_jitter; x++)
				{
					DWORD	data	[TEX_jitter_count-1];
					generate_jitter	(data,TEX_jitter_count-1);
					for (u32 it2=0; it2<TEX_jitter_count-1; it2++)
					{
						u32*	p	=	(u32*)	(LPBYTE (R[it2].pBits) + y*R[it2].Pitch + x*4);
								*p	=	data	[it2];
					}
				}
			}
			
			for (int it3=0; it3<TEX_jitter_count-1; it3++)	{
				R_CHK						(t_noise_surf[it3]->UnlockRect(0));
			}		

			// generate HBAO jitter texture (last)
			int it = TEX_jitter_count - 1;
			string_path					name;
			sprintf						(name,"%s%d",r2_jitter,it);
			R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_A32B32G32R32F,D3DPOOL_MANAGED,&t_noise_surf[it]));
			t_noise[it]					= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(name);
			t_noise[it]->surface_set	(t_noise_surf[it]);
			R_CHK						(t_noise_surf[it]->LockRect	(0,&R[it],0,0));
			
			// Fill it,
			for (u32 y=0; y<TEX_jitter; y++)
			{
				for (u32 x=0; x<TEX_jitter; x++)
				{
					float numDir = 1.0f;
					switch (ps_r_ssao)
					{
						case 1: numDir = 4.0f; break;
						case 2: numDir = 6.0f; break;
						case 3: numDir = 8.0f; break;
					}
					float angle = 2 * PI * ::Random.randF(0.0f, 1.0f) / numDir;
					float dist = ::Random.randF(0.0f, 1.0f);
					//float dest[4];
					
					float*	p	=	(float*)	(LPBYTE (R[it].pBits) + y*R[it].Pitch + x*4*sizeof(float));
					*p = (float)(_cos(angle));
					*(p+1) = (float)(_sin(angle));
					*(p+2) = (float)(dist);
					*(p+3) = 0;
					
					//generate_hbao_jitter	(data,TEX_jitter*TEX_jitter);
				}
			}			
			R_CHK						(t_noise_surf[it]->UnlockRect(0));
		}
	}

	// PP
	s_postprocess.create				("postprocess");
	g_postprocess.create				(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB);

	// Menu
	s_menu.create						("distort");
	g_menu.create						(FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB);

	//	Igor: TMP
	//	Create an RT for online screenshot makining
	//u32		w = Device.dwWidth, h = Device.dwHeight;
	//HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&pFB,NULL);
	//HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,rt_Color->fmt,D3DPOOL_SYSTEMMEM,&pFB,NULL);
	D3DSURFACE_DESC	desc;
	HW.pBaseRT->GetDesc(&desc);
	HW.pDevice->CreateOffscreenPlainSurface(Device.dwWidth,Device.dwHeight,desc.Format,D3DPOOL_SYSTEMMEM,&pFB,NULL);

	// 
	dwWidth		= Device.dwWidth;
	dwHeight	= Device.dwHeight;
}
예제 #2
0
CRenderTarget::CRenderTarget		()
{
	param_blur			= 0.f;
	param_gray			= 0.f;
	param_noise			= 0.f;
	param_duality_h		= 0.f;
	param_duality_v		= 0.f;
	param_noise_fps		= 25.f;
	param_noise_scale	= 1.f;

	im_noise_time		= 1/100;
	im_noise_shift_w	= 0;
	im_noise_shift_h	= 0;

	param_color_base	= color_rgba(127,127,127,	0);
	param_color_gray	= color_rgba(85,85,85,		0);
	param_color_add		= color_rgba(0,0,0,			0);

	dwAccumulatorClearMark			= 0;
	Device.Resources->Evict			();

	// Blenders
	b_occq							= xr_new<CBlender_light_occq>			();
	b_accum_mask					= xr_new<CBlender_accum_direct_mask>	();
	b_accum_direct					= xr_new<CBlender_accum_direct>			();
	b_accum_point					= xr_new<CBlender_accum_point>			();
	b_accum_spot					= xr_new<CBlender_accum_spot>			();
	b_accum_reflected				= xr_new<CBlender_accum_reflected>		();
	b_bloom							= xr_new<CBlender_bloom_build>			();
	b_luminance						= xr_new<CBlender_luminance>			();
	b_combine						= xr_new<CBlender_combine>				();

	//	NORMAL
	{
		u32		w=Device.dwWidth, h=Device.dwHeight;
		rt_Position.create			(r2_RT_P,		w,h,D3DFMT_A16B16G16R16F);
		rt_Normal.create			(r2_RT_N,		w,h,D3DFMT_A16B16G16R16F);

		// select albedo & accum
		if (RImplementation.o.mrtmixdepth)	
		{
			// NV50
			rt_Color.create			(r2_RT_albedo,	w,h,D3DFMT_A8R8G8B8		);
			rt_Accumulator.create	(r2_RT_accum,	w,h,D3DFMT_A16B16G16R16F);
		}
		else		
		{
			// can't - mix-depth
			if (RImplementation.o.fp16_blend) {
				// NV40
				rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A16B16G16R16F);	// expand to full
				rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F);
			} else {
				// R4xx, no-fp-blend,-> albedo_wo
				VERIFY						(RImplementation.o.albedo_wo);
				rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A8R8G8B8		);	// normal
				rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F);
				rt_Accumulator_temp.create	(r2_RT_accum_temp,	w,h,D3DFMT_A16B16G16R16F);
			}
		}

		// generic(LDR) RTs
		rt_Generic_0.create			(r2_RT_generic0,w,h,D3DFMT_A8R8G8B8		);
		rt_Generic_1.create			(r2_RT_generic1,w,h,D3DFMT_A8R8G8B8		);
	}

	// OCCLUSION
	s_occq.create					(b_occq,		"r2\\occq");

	// DIRECT (spot)
	D3DFORMAT						depth_format	= (D3DFORMAT)RImplementation.o.HW_smap_FORMAT;

	if (RImplementation.o.HW_smap)
	{
		D3DFORMAT	nullrt				= D3DFMT_R5G6B5;
		if (RImplementation.o.nullrt)	nullrt	= (D3DFORMAT)MAKEFOURCC('N','U','L','L');

		u32	size					=RImplementation.o.smapsize	;
		rt_smap_depth.create		(r2_RT_smap_depth,			size,size,depth_format	);
		rt_smap_surf.create			(r2_RT_smap_surf,			size,size,nullrt		);
		rt_smap_ZB					= NULL;
		s_accum_mask.create			(b_accum_mask,				"r2\\accum_mask");
		s_accum_direct.create		(b_accum_direct,			"r2\\accum_direct");
	}
	else
	{
		u32	size					=RImplementation.o.smapsize	;
		rt_smap_surf.create			(r2_RT_smap_surf,			size,size,D3DFMT_R32F);
		rt_smap_depth				= NULL;
		R_CHK						(HW.pDevice->CreateDepthStencilSurface	(size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL));
		s_accum_mask.create			(b_accum_mask,				"r2\\accum_mask");
		s_accum_direct.create		(b_accum_direct,			"r2\\accum_direct");
	}

	// POINT
	{
		s_accum_point.create		(b_accum_point,				"r2\\accum_point_s");
		accum_point_geom_create		();
		g_accum_point.create		(D3DFVF_XYZ,				g_accum_point_vb, g_accum_point_ib);
		accum_omnip_geom_create		();
		g_accum_omnipart.create		(D3DFVF_XYZ,				g_accum_omnip_vb, g_accum_omnip_ib);
	}

	// SPOT
	{
		s_accum_spot.create			(b_accum_spot,				"r2\\accum_spot_s",	"lights\\lights_spot01");
		accum_spot_geom_create		();
		g_accum_spot.create			(D3DFVF_XYZ,				g_accum_spot_vb, g_accum_spot_ib);
	}

	// REFLECTED
	{
		s_accum_reflected.create	(b_accum_reflected,			"r2\\accum_refl");
	}

	// BLOOM
	{
		D3DFORMAT	fmt				= D3DFMT_A8R8G8B8;			//;		// D3DFMT_X8R8G8B8
		u32	w=BLOOM_size_X, h=BLOOM_size_Y;
		u32 fvf_build				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
		u32 fvf_filter				= (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7);
		rt_Bloom_1.create			(r2_RT_bloom1,	w,h,		fmt);
		rt_Bloom_2.create			(r2_RT_bloom2,	w,h,		fmt);
		g_bloom_build.create		(fvf_build,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_bloom_filter.create		(fvf_filter,	RCache.Vertex.Buffer(), RCache.QuadIB);
		s_bloom_dbg_1.create		("effects\\screen_set",		r2_RT_bloom1);
		s_bloom_dbg_2.create		("effects\\screen_set",		r2_RT_bloom2);
		s_bloom.create				(b_bloom,					"r2\\bloom");
		f_bloom_factor				= 0.5f;
	}

	// TONEMAP
	{
		rt_LUM_64.create			(r2_RT_luminance_t64,	64, 64,	D3DFMT_A16B16G16R16F	);
		rt_LUM_8.create				(r2_RT_luminance_t8,	8,	8,	D3DFMT_A16B16G16R16F	);
		s_luminance.create			(b_luminance,				"r2\\luminance");
		f_luminance_adapt			= 0.5f;

		t_LUM_src.create			(r2_RT_luminance_src);
		t_LUM_dest.create			(r2_RT_luminance_cur);

		// create pool
		for (u32 it=0; it<4; it++)	{
			string256					name;
			sprintf						(name,"%s_%d",	r2_RT_luminance_pool,it	);
			rt_LUM_pool[it].create		(name,	1,	1,	D3DFMT_R32F				);
			u_setrt						(rt_LUM_pool[it],	0,	0,	0			);
			CHK_DX						(HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,	0x7f7f7f7f,	1.0f, 0L));
		}
		u_setrt						( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB);
	}

	// COMBINE
	{
		static D3DVERTEXELEMENT9 dwDecl[] =
		{
			{ 0, 0,  D3DDECLTYPE_FLOAT4,	D3DDECLMETHOD_DEFAULT, 	D3DDECLUSAGE_POSITION,	0 },	// pos+uv
			D3DDECL_END()
		};
		s_combine.create					(b_combine,					"r2\\combine");
		s_combine_dbg_0.create				("effects\\screen_set",		r2_RT_smap_surf		);	
		s_combine_dbg_1.create				("effects\\screen_set",		r2_RT_luminance_t8	);
		s_combine_dbg_Accumulator.create	("effects\\screen_set",		r2_RT_accum			);
		g_combine_VP.create					(dwDecl,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_combine.create					(FVF::F_TL,		RCache.Vertex.Buffer(), RCache.QuadIB);
		g_combine_2UV.create				(FVF::F_TL2uv,	RCache.Vertex.Buffer(), RCache.QuadIB);

		u32 fvf_aa_blur				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
		g_aa_blur.create			(fvf_aa_blur,	RCache.Vertex.Buffer(), RCache.QuadIB);

		u32 fvf_aa_AA				= D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6);
		g_aa_AA.create				(fvf_aa_AA,		RCache.Vertex.Buffer(), RCache.QuadIB);

		t_envmap_0.create			(r2_T_envs0);
		t_envmap_1.create			(r2_T_envs1);
	}

	// Build textures
	{
		// Build material(s)
		{
			// Surface
			R_CHK						(D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf));
			t_material					= Device.Resources->_CreateTexture(r2_material);
			t_material->surface_set		(t_material_surf);

			// Fill it (addr: x=dot(L,N),y=dot(L,H))
			D3DLOCKED_BOX				R;
			R_CHK						(t_material_surf->LockBox	(0,&R,0,0));
			for (u32 slice=0; slice<4; slice++)
			{
				for (u32 y=0; y<TEX_material_LdotH; y++)
				{
					for (u32 x=0; x<TEX_material_LdotN; x++)
					{
						u16*	p	=	(u16*)		(LPBYTE (R.pBits) + slice*R.SlicePitch + y*R.RowPitch + x*2);
						float	ld	=	float(x)	/ float	(TEX_material_LdotN-1);
						float	ls	=	float(y)	/ float	(TEX_material_LdotH-1) + EPS_S;
						ls			*=	powf(ld,1/32.f);
						float	fd,fs;

						switch	(slice)
						{
						case 0:	{ // looks like OrenNayar
							fd	= powf(ld,0.75f);		// 0.75
							fs	= powf(ls,16.f)*.5f;
								}	break;
						case 1:	{// looks like Blinn
							fd	= powf(ld,0.90f);		// 0.90
							fs	= powf(ls,24.f);
								}	break;
						case 2:	{ // looks like Phong
							fd	= ld;					// 1.0
							fs	= powf(ls*1.01f,128.f	);
								}	break;
						case 3:	{ // looks like Metal
							float	s0	=	_abs	(1-_abs	(0.05f*_sin(33.f*ld)+ld-ls));
							float	s1	=	_abs	(1-_abs	(0.05f*_cos(33.f*ld*ls)+ld-ls));
							float	s2	=	_abs	(1-_abs	(ld-ls));
							fd		=	ld;				// 1.0
							fs		=	powf	(_max(_max(s0,s1),s2), 24.f);
							fs		*=	powf	(ld,1/7.f);
								}	break;
						default:
							fd	= fs = 0;
						}
						s32		_d	=	clampr	(iFloor	(fd*255.5f),	0,255);
						s32		_s	=	clampr	(iFloor	(fs*255.5f),	0,255);
						if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1)))	{ _d = 255; _s=255;	}
						*p			=	u16		(_s*256 + _d);
					}
				}
			}
			R_CHK		(t_material_surf->UnlockBox	(0));
			// #ifdef DEBUG
			// R_CHK	(D3DXSaveTextureToFile	("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0));
			// #endif
		}

		// Build noise table
		if (1)
		{
			// Surfaces
			D3DLOCKED_RECT				R[TEX_jitter_count];
			for (int it=0; it<TEX_jitter_count; it++)
			{
				string_path					name;
				sprintf						(name,"%s%d",r2_jitter,it);
				R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it]));
				t_noise[it]					= Device.Resources->_CreateTexture	(name);
				t_noise[it]->surface_set	(t_noise_surf[it]);
				R_CHK						(t_noise_surf[it]->LockRect	(0,&R[it],0,0));
			}

			// Fill it,
			for (u32 y=0; y<TEX_jitter; y++)
			{
				for (u32 x=0; x<TEX_jitter; x++)
				{
					DWORD	data	[TEX_jitter_count];
					generate_jitter	(data,TEX_jitter_count);
					for (u32 it=0; it<TEX_jitter_count; it++)
					{
						u32*	p	=	(u32*)	(LPBYTE (R[it].pBits) + y*R[it].Pitch + x*4);
								*p	=	data	[it];
					}
				}
			}
			for (int it=0; it<TEX_jitter_count; it++)	{
				R_CHK						(t_noise_surf[it]->UnlockRect(0));
			}
		}
	}

	// PP
	s_postprocess.create				("postprocess");
	g_postprocess.create				(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB);

	// Menu
	s_menu.create						("distort");
	g_menu.create						(FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB);

	// 
	dwWidth		= Device.dwWidth;
	dwHeight	= Device.dwHeight;
}
예제 #3
0
CRenderTarget::CRenderTarget		()
{
    u32 SampleCount = 1;

    if (ps_r_ssao_mode!=2/*hdao*/)
        ps_r_ssao = _min(ps_r_ssao, 3);

    if( RImplementation.o.dx10_msaa )
        SampleCount    = RImplementation.o.dx10_msaa_samples;

#ifdef DEBUG
    Msg			("MSAA samples = %d", SampleCount );
    if( RImplementation.o.dx10_msaa_opt )
        Msg		("dx10_MSAA_opt = on" );
    if( RImplementation.o.dx10_gbuffer_opt )
        Msg		("dx10_gbuffer_opt = on" );
#endif // DEBUG
    param_blur			= 0.f;
    param_gray			= 0.f;
    param_noise			= 0.f;
    param_duality_h		= 0.f;
    param_duality_v		= 0.f;
    param_noise_fps		= 25.f;
    param_noise_scale	= 1.f;

    im_noise_time		= 1/100;
    im_noise_shift_w	= 0;
    im_noise_shift_h	= 0;

    param_color_base	= color_rgba(127,127,127,	0);
    param_color_gray	= color_rgba(85,85,85,		0);
    //param_color_add		= color_rgba(0,0,0,			0);
    param_color_add.set( 0.0f, 0.0f, 0.0f );

    dwAccumulatorClearMark			= 0;
    dxRenderDeviceRender::Instance().Resources->Evict			();

    // Blenders
    b_occq					= xr_new<CBlender_light_occq>			();
    b_accum_mask			= xr_new<CBlender_accum_direct_mask>	();
    b_accum_direct			= xr_new<CBlender_accum_direct>			();
    b_accum_point			= xr_new<CBlender_accum_point>			();
    b_accum_spot			= xr_new<CBlender_accum_spot>			();
    b_accum_reflected		= xr_new<CBlender_accum_reflected>		();
    b_bloom					= xr_new<CBlender_bloom_build>			();
    if( RImplementation.o.dx10_msaa )
    {
        b_bloom_msaa			= xr_new<CBlender_bloom_build_msaa>		();
        b_postprocess_msaa	= xr_new<CBlender_postprocess_msaa>	();
    }
    b_luminance				= xr_new<CBlender_luminance>			();
    b_combine				= xr_new<CBlender_combine>				();
    b_ssao					= xr_new<CBlender_SSAO_noMSAA>			();

    if( RImplementation.o.dx10_msaa )
    {
        int bound = RImplementation.o.dx10_msaa_samples;

        if( RImplementation.o.dx10_msaa_opt )
            bound = 1;

        for( int i = 0; i < bound; ++i )
        {
            static LPCSTR SampleDefs[] = { "0","1","2","3","4","5","6","7" };
            b_combine_msaa[i]							= xr_new<CBlender_combine_msaa>					();
            b_accum_mask_msaa[i]						= xr_new<CBlender_accum_direct_mask_msaa>		();
            b_accum_direct_msaa[i]					= xr_new<CBlender_accum_direct_msaa>			();
            b_accum_direct_volumetric_msaa[i]			= xr_new<CBlender_accum_direct_volumetric_msaa>	();
            //b_accum_direct_volumetric_sun_msaa[i]	= xr_new<CBlender_accum_direct_volumetric_sun_msaa>			();
            b_accum_spot_msaa[i]		 				= xr_new<CBlender_accum_spot_msaa>			();
            b_accum_volumetric_msaa[i]				= xr_new<CBlender_accum_volumetric_msaa>	();
            b_accum_point_msaa[i]						= xr_new<CBlender_accum_point_msaa>			();
            b_accum_reflected_msaa[i]					= xr_new<CBlender_accum_reflected_msaa>		();
            b_ssao_msaa[i]							= xr_new<CBlender_SSAO_MSAA>				();
            static_cast<CBlender_accum_direct_mask_msaa*>( b_accum_mask_msaa[i] )->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_direct_volumetric_msaa*>(b_accum_direct_volumetric_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            //static_cast<CBlender_accum_direct_volumetric_sun_msaa*>(b_accum_direct_volumetric_sun_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_direct_msaa*>(b_accum_direct_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_volumetric_msaa*>(b_accum_volumetric_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_spot_msaa*>(b_accum_spot_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_point_msaa*>(b_accum_point_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_accum_reflected_msaa*>(b_accum_reflected_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_combine_msaa*>(b_combine_msaa[i])->SetDefine( "ISAMPLE", SampleDefs[i]);
            static_cast<CBlender_SSAO_MSAA*>(b_ssao_msaa[i])->SetDefine("ISAMPLE", SampleDefs[i]);
        }
    }
    //	NORMAL
    {
        u32		w=Device.dwWidth, h=Device.dwHeight;
        rt_Position.create			(r2_RT_P,		w,h,D3DFMT_A16B16G16R16F, SampleCount );

        if( RImplementation.o.dx10_msaa )
            rt_MSAADepth.create( r2_RT_MSAAdepth, w, h, D3DFMT_D24S8, SampleCount );

        if( !RImplementation.o.dx10_gbuffer_opt )
            rt_Normal.create			(r2_RT_N,		w,h,D3DFMT_A16B16G16R16F, SampleCount );

        // select albedo & accum
        if (RImplementation.o.mrtmixdepth)
        {
            // NV50
            rt_Color.create			(r2_RT_albedo,	w,h,D3DFMT_A8R8G8B8		, SampleCount );
            rt_Accumulator.create	(r2_RT_accum,	w,h,D3DFMT_A16B16G16R16F, SampleCount );
        }
        else
        {
            // can't - mix-depth
            if (RImplementation.o.fp16_blend) {
                // NV40
                if( !RImplementation.o.dx10_gbuffer_opt )
                {
                    rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A16B16G16R16F, SampleCount );	// expand to full
                    rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F, SampleCount );
                }
                else
                {
                    rt_Color.create				(r2_RT_albedo,		w,h,D3DFMT_A8R8G8B8,       SampleCount );	// expand to full
                    rt_Accumulator.create		(r2_RT_accum,		w,h,D3DFMT_A16B16G16R16F,  SampleCount );
                }
            } else {
                // R4xx, no-fp-blend,-> albedo_wo
                VERIFY						(RImplementation.o.albedo_wo);
                rt_Color.create				(r2_RT_albedo,		   w,h,D3DFMT_A8R8G8B8		, SampleCount );	// normal
                rt_Accumulator.create		(r2_RT_accum,		   w,h,D3DFMT_A16B16G16R16F, SampleCount );
                rt_Accumulator_temp.create	(r2_RT_accum_temp,	w,h,D3DFMT_A16B16G16R16F, SampleCount );
            }
        }

        // generic(LDR) RTs
        rt_Generic_0.create		(r2_RT_generic0,w,h,D3DFMT_A8R8G8B8, 1		);
        rt_Generic_1.create		(r2_RT_generic1,w,h,D3DFMT_A8R8G8B8, 1		);
        if( RImplementation.o.dx10_msaa )
        {
            rt_Generic_0_r.create(r2_RT_generic0_r,w,h,D3DFMT_A8R8G8B8, SampleCount	);
            rt_Generic_1_r.create(r2_RT_generic1_r,w,h,D3DFMT_A8R8G8B8, SampleCount		);
            rt_Generic.create	 (r2_RT_generic,w,h,   D3DFMT_A8R8G8B8, 1		);
        }
        //	Igor: for volumetric lights
        //rt_Generic_2.create			(r2_RT_generic2,w,h,D3DFMT_A8R8G8B8		);
        //	temp: for higher quality blends
        if (RImplementation.o.advancedpp)
            rt_Generic_2.create			(r2_RT_generic2,w,h,D3DFMT_A16B16G16R16F, SampleCount );
    }

    // OCCLUSION
    s_occq.create					(b_occq,		"r2\\occq");

    // DIRECT (spot)
    D3DFORMAT						depth_format	= (D3DFORMAT)RImplementation.o.HW_smap_FORMAT;

    if (RImplementation.o.HW_smap)
    {
        D3DFORMAT	nullrt				= D3DFMT_R5G6B5;
        if (RImplementation.o.nullrt)	nullrt	= (D3DFORMAT)MAKEFOURCC('N','U','L','L');

        u32	size					=RImplementation.o.smapsize	;
        rt_smap_depth.create		(r2_RT_smap_depth,			size,size,depth_format	);

        if (RImplementation.o.dx10_minmax_sm)
        {
            rt_smap_depth_minmax.create( r2_RT_smap_depth_minmax,	size/4,size/4, D3DFMT_R32F	);
            CBlender_createminmax TempBlender;
            s_create_minmax_sm.create( &TempBlender, "null" );
        }

        //rt_smap_surf.create			(r2_RT_smap_surf,			size,size,nullrt		);
        //rt_smap_ZB					= NULL;
        s_accum_mask.create			(b_accum_mask,				"r3\\accum_mask");
        s_accum_direct.create		(b_accum_direct,			"r3\\accum_direct");


        if( RImplementation.o.dx10_msaa )
        {
            int bound = RImplementation.o.dx10_msaa_samples;

            if( RImplementation.o.dx10_msaa_opt )
                bound = 1;

            for( int i = 0; i < bound; ++i )
            {
                s_accum_direct_msaa[i].create		(b_accum_direct_msaa[i],			"r3\\accum_direct");
                s_accum_mask_msaa[i].create		(b_accum_mask_msaa[i],			"r3\\accum_direct");
            }
        }
        if (RImplementation.o.advancedpp)
        {
            s_accum_direct_volumetric.create("accum_volumetric_sun_nomsaa");

            if (RImplementation.o.dx10_minmax_sm)
                s_accum_direct_volumetric_minmax.create("accum_volumetric_sun_nomsaa_minmax");

            if( RImplementation.o.dx10_msaa )
            {
                static LPCSTR snames[] = { "accum_volumetric_sun_msaa0",
                                           "accum_volumetric_sun_msaa1",
                                           "accum_volumetric_sun_msaa2",
                                           "accum_volumetric_sun_msaa3",
                                           "accum_volumetric_sun_msaa4",
                                           "accum_volumetric_sun_msaa5",
                                           "accum_volumetric_sun_msaa6",
                                           "accum_volumetric_sun_msaa7"
                                         };
                int bound = RImplementation.o.dx10_msaa_samples;

                if( RImplementation.o.dx10_msaa_opt )
                    bound = 1;

                for( int i = 0; i < bound; ++i )
                {
                    //s_accum_direct_volumetric_msaa[i].create		(b_accum_direct_volumetric_sun_msaa[i],			"r3\\accum_direct");
                    s_accum_direct_volumetric_msaa[i].create		(snames[i]);
                }
            }
        }
    }
    else
    {
        //	TODO: DX10: Check if we need old-style SMap
        VERIFY(!"Use HW SMAPs only!");
        //u32	size					=RImplementation.o.smapsize	;
        //rt_smap_surf.create			(r2_RT_smap_surf,			size,size,D3DFMT_R32F);
        //rt_smap_depth				= NULL;
        //R_CHK						(HW.pDevice->CreateDepthStencilSurface	(size,size,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&rt_smap_ZB,NULL));
        //s_accum_mask.create			(b_accum_mask,				"r2\\accum_mask");
        //s_accum_direct.create		(b_accum_direct,			"r2\\accum_direct");
        //if (RImplementation.o.advancedpp)
        //	s_accum_direct_volumetric.create("accum_volumetric_sun");
    }

    //	RAIN
    //	TODO: DX10: Create resources only when DX10 rain is enabled.
    //	Or make DX10 rain switch dynamic?
    {
        CBlender_rain	TempBlender;
        s_rain.create( &TempBlender, "null");

        if( RImplementation.o.dx10_msaa )
        {
            static LPCSTR SampleDefs[] = { "0","1","2","3","4","5","6","7" };
            CBlender_rain_msaa	TempBlender[8];

            int bound = RImplementation.o.dx10_msaa_samples;

            if( RImplementation.o.dx10_msaa_opt )
                bound = 1;

            for( int i = 0; i < bound; ++i )
            {
                TempBlender[i].SetDefine( "ISAMPLE", SampleDefs[i] );
                s_rain_msaa[i].create( &TempBlender[i], "null");
                s_accum_spot_msaa[i].create			(b_accum_spot_msaa[i],				"r2\\accum_spot_s",	"lights\\lights_spot01");
                s_accum_point_msaa[i].create		(b_accum_point_msaa[i],			"r2\\accum_point_s");
                //s_accum_volume_msaa[i].create(b_accum_direct_volumetric_msaa[i], "lights\\lights_spot01");
                s_accum_volume_msaa[i].create(b_accum_volumetric_msaa[i], "lights\\lights_spot01");
                s_combine_msaa[i].create					(b_combine_msaa[i],					"r2\\combine");
            }
        }
    }

    if( RImplementation.o.dx10_msaa )
    {
        CBlender_msaa TempBlender;

        s_mark_msaa_edges.create( &TempBlender, "null" );
    }

    // POINT
    {
        s_accum_point.create		(b_accum_point,				"r2\\accum_point_s");
        accum_point_geom_create		();
        g_accum_point.create		(D3DFVF_XYZ,				g_accum_point_vb, g_accum_point_ib);
        accum_omnip_geom_create		();
        g_accum_omnipart.create		(D3DFVF_XYZ,				g_accum_omnip_vb, g_accum_omnip_ib);
    }

    // SPOT
    {
        s_accum_spot.create			(b_accum_spot,				"r2\\accum_spot_s",	"lights\\lights_spot01");
        accum_spot_geom_create		();
        g_accum_spot.create			(D3DFVF_XYZ,				g_accum_spot_vb, g_accum_spot_ib);
    }

    {
        s_accum_volume.create("accum_volumetric", "lights\\lights_spot01");
        accum_volumetric_geom_create();
        g_accum_volumetric.create( D3DFVF_XYZ, g_accum_volumetric_vb, g_accum_volumetric_ib);
    }


    // REFLECTED
    {
        s_accum_reflected.create	(b_accum_reflected,			"r2\\accum_refl");
        if( RImplementation.o.dx10_msaa )
        {
            int bound = RImplementation.o.dx10_msaa_samples;

            if( RImplementation.o.dx10_msaa_opt )
                bound = 1;

            for( int i = 0; i < bound; ++i )
            {
                s_accum_reflected_msaa[i].create( b_accum_reflected_msaa[i], "null");
            }
        }
    }

    // BLOOM
    {
        D3DFORMAT	fmt				= D3DFMT_A8R8G8B8;			//;		// D3DFMT_X8R8G8B8
        u32	w=BLOOM_size_X, h=BLOOM_size_Y;
        u32 fvf_build				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
        u32 fvf_filter				= (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7);
        rt_Bloom_1.create			(r2_RT_bloom1,	w,h,		fmt);
        rt_Bloom_2.create			(r2_RT_bloom2,	w,h,		fmt);
        g_bloom_build.create		(fvf_build,		RCache.Vertex.Buffer(), RCache.QuadIB);
        g_bloom_filter.create		(fvf_filter,	RCache.Vertex.Buffer(), RCache.QuadIB);
        s_bloom_dbg_1.create		("effects\\screen_set",		r2_RT_bloom1);
        s_bloom_dbg_2.create		("effects\\screen_set",		r2_RT_bloom2);
        s_bloom.create				(b_bloom,					"r2\\bloom");
        if( RImplementation.o.dx10_msaa )
        {
            s_bloom_msaa.create		 (b_bloom_msaa,					"r2\\bloom");
            s_postprocess_msaa.create(b_postprocess_msaa,			"r2\\post");
        }
        f_bloom_factor				= 0.5f;
    }

    // TONEMAP
    {
        rt_LUM_64.create			(r2_RT_luminance_t64,	64, 64,	D3DFMT_A16B16G16R16F	);
        rt_LUM_8.create				(r2_RT_luminance_t8,	8,	8,	D3DFMT_A16B16G16R16F	);
        s_luminance.create			(b_luminance,				"r2\\luminance");
        f_luminance_adapt			= 0.5f;

        t_LUM_src.create			(r2_RT_luminance_src);
        t_LUM_dest.create			(r2_RT_luminance_cur);

        // create pool
        for (u32 it=0; it<HW.Caps.iGPUNum*2; it++)	{
            string256					name;
            xr_sprintf						(name,"%s_%d",	r2_RT_luminance_pool,it	);
            rt_LUM_pool[it].create		(name,	1,	1,	D3DFMT_R32F				);
            //u_setrt						(rt_LUM_pool[it],	0,	0,	0			);
            //CHK_DX						(HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,	0x7f7f7f7f,	1.0f, 0L));
            FLOAT ColorRGBA[4] = { 127.0f/255.0f, 127.0f/255.0f, 127.0f/255.0f, 127.0f/255.0f};
            HW.pDevice->ClearRenderTargetView(rt_LUM_pool[it]->pRT, ColorRGBA);
        }
        u_setrt						( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB);
    }

    // HBAO
    if (RImplementation.o.ssao_opt_data)
    {
        u32		w = 0;
        u32		h = 0;
        if (RImplementation.o.ssao_half_data)
        {
            w = Device.dwWidth / 2;
            h = Device.dwHeight / 2;
        }
        else
        {
            w = Device.dwWidth;
            h = Device.dwHeight;
        }

        D3DFORMAT	fmt = HW.Caps.id_vendor==0x10DE?D3DFMT_R32F:D3DFMT_R16F;
        rt_half_depth.create		(r2_RT_half_depth, w, h, fmt);

        s_ssao.create				(b_ssao, "r2\\ssao");
    }

    if (RImplementation.o.ssao_blur_on)
    {
        u32		w = Device.dwWidth, h = Device.dwHeight;
        rt_ssao_temp.create			(r2_RT_ssao_temp, w, h, D3DFMT_G16R16F, SampleCount);
        s_ssao.create				(b_ssao, "r2\\ssao");

        if( RImplementation.o.dx10_msaa )
        {
            int bound = RImplementation.o.dx10_msaa_opt ? 1 : RImplementation.o.dx10_msaa_samples;

            for( int i = 0; i < bound; ++i )
            {
                s_ssao_msaa[i].create( b_ssao_msaa[i], "null");
            }
        }
    }

    // COMBINE
    {
        static D3DVERTEXELEMENT9 dwDecl[] =
        {
            { 0, 0,  D3DDECLTYPE_FLOAT4,	D3DDECLMETHOD_DEFAULT, 	D3DDECLUSAGE_POSITION,	0 },	// pos+uv
            D3DDECL_END()
        };
        s_combine.create					(b_combine,					"r2\\combine");
        s_combine_volumetric.create			("combine_volumetric");
        s_combine_dbg_0.create				("effects\\screen_set",		r2_RT_smap_surf		);
        s_combine_dbg_1.create				("effects\\screen_set",		r2_RT_luminance_t8	);
        s_combine_dbg_Accumulator.create	("effects\\screen_set",		r2_RT_accum			);
        g_combine_VP.create					(dwDecl,		RCache.Vertex.Buffer(), RCache.QuadIB);
        g_combine.create					(FVF::F_TL,		RCache.Vertex.Buffer(), RCache.QuadIB);
        g_combine_2UV.create				(FVF::F_TL2uv,	RCache.Vertex.Buffer(), RCache.QuadIB);
        g_combine_cuboid.create				(dwDecl,	RCache.Vertex.Buffer(), RCache.Index.Buffer());

        u32 fvf_aa_blur				= D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3);
        g_aa_blur.create			(fvf_aa_blur,	RCache.Vertex.Buffer(), RCache.QuadIB);

        u32 fvf_aa_AA				= D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6);
        g_aa_AA.create				(fvf_aa_AA,		RCache.Vertex.Buffer(), RCache.QuadIB);

        t_envmap_0.create			(r2_T_envs0);
        t_envmap_1.create			(r2_T_envs1);
    }

    // Build textures
    {
        // Testure for async sreenshots
        {
            D3D10_TEXTURE2D_DESC	desc;
            desc.Width = Device.dwWidth;
            desc.Height = Device.dwHeight;
            desc.MipLevels = 1;
            desc.ArraySize = 1;
            desc.SampleDesc.Count = 1;
            desc.SampleDesc.Quality = 0;
            desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM;
            desc.Usage = D3D10_USAGE_STAGING;
            desc.BindFlags = 0;
            desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
            desc.MiscFlags = 0;

            R_CHK( HW.pDevice->CreateTexture2D(&desc, 0, &t_ss_async) );
        }
        // Build material(s)
        {
            //	Create immutable texture.
            //	So we need to init data _before_ the creation.
            // Surface
            //R_CHK						(D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf));
            //t_material					= dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material);
            //t_material->surface_set		(t_material_surf);
            //	Use DXGI_FORMAT_R8G8_UNORM

            u16	tempData[TEX_material_LdotN*TEX_material_LdotH*TEX_material_Count];

            D3D10_TEXTURE3D_DESC	desc;
            desc.Width = TEX_material_LdotN;
            desc.Height = TEX_material_LdotH;
            desc.Depth	= TEX_material_Count;
            desc.MipLevels = 1;
            desc.Format = DXGI_FORMAT_R8G8_UNORM;
            desc.Usage = D3D10_USAGE_IMMUTABLE;
            desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
            desc.CPUAccessFlags = 0;
            desc.MiscFlags = 0;

            D3D10_SUBRESOURCE_DATA	subData;

            subData.pSysMem = tempData;
            subData.SysMemPitch = desc.Width*2;
            subData.SysMemSlicePitch = desc.Height*subData.SysMemPitch;

            // Fill it (addr: x=dot(L,N),y=dot(L,H))
            //D3DLOCKED_BOX				R;
            //R_CHK						(t_material_surf->LockBox	(0,&R,0,0));
            for (u32 slice=0; slice<TEX_material_Count; slice++)
            {
                for (u32 y=0; y<TEX_material_LdotH; y++)
                {
                    for (u32 x=0; x<TEX_material_LdotN; x++)
                    {
                        u16*	p	=	(u16*)
                                        (LPBYTE (subData.pSysMem)
                                         + slice*subData.SysMemSlicePitch
                                         + y*subData.SysMemPitch + x*2);
                        float	ld	=	float(x)	/ float	(TEX_material_LdotN-1);
                        float	ls	=	float(y)	/ float	(TEX_material_LdotH-1) + EPS_S;
                        ls			*=	powf(ld,1/32.f);
                        float	fd,fs;

                        switch	(slice)
                        {
                        case 0:	{ // looks like OrenNayar
                            fd	= powf(ld,0.75f);		// 0.75
                            fs	= powf(ls,16.f)*.5f;
                        }
                        break;
                        case 1:	{// looks like Blinn
                            fd	= powf(ld,0.90f);		// 0.90
                            fs	= powf(ls,24.f);
                        }
                        break;
                        case 2:	{ // looks like Phong
                            fd	= ld;					// 1.0
                            fs	= powf(ls*1.01f,128.f	);
                        }
                        break;
                        case 3:	{ // looks like Metal
                            float	s0	=	_abs	(1-_abs	(0.05f*_sin(33.f*ld)+ld-ls));
                            float	s1	=	_abs	(1-_abs	(0.05f*_cos(33.f*ld*ls)+ld-ls));
                            float	s2	=	_abs	(1-_abs	(ld-ls));
                            fd		=	ld;				// 1.0
                            fs		=	powf	(_max(_max(s0,s1),s2), 24.f);
                            fs		*=	powf	(ld,1/7.f);
                        }
                        break;
                        default:
                            fd	= fs = 0;
                        }
                        s32		_d	=	clampr	(iFloor	(fd*255.5f),	0,255);
                        s32		_s	=	clampr	(iFloor	(fs*255.5f),	0,255);
                        if ((y==(TEX_material_LdotH-1)) && (x==(TEX_material_LdotN-1)))	{
                            _d = 255;
                            _s=255;
                        }
                        *p			=	u16		(_s*256 + _d);
                    }
                }
            }
            //R_CHK		(t_material_surf->UnlockBox	(0));

            R_CHK(HW.pDevice->CreateTexture3D(&desc, &subData, &t_material_surf));
            t_material					= dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material);
            t_material->surface_set		(t_material_surf);
            //R_CHK						(D3DXCreateVolumeTexture(HW.pDevice,TEX_material_LdotN,TEX_material_LdotH,4,1,0,D3DFMT_A8L8,D3DPOOL_MANAGED,&t_material_surf));
            //t_material					= dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material);
            //t_material->surface_set		(t_material_surf);

            // #ifdef DEBUG
            // R_CHK	(D3DXSaveTextureToFile	("x:\\r2_material.dds",D3DXIFF_DDS,t_material_surf,0));
            // #endif
        }

        // Build noise table
        if (1)
        {
            // Surfaces
            //D3DLOCKED_RECT				R[TEX_jitter_count];

            //for (int it=0; it<TEX_jitter_count; it++)
            //{
            //	string_path					name;
            //	xr_sprintf						(name,"%s%d",r2_jitter,it);
            //	R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it]));
            //	t_noise[it]					= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(name);
            //	t_noise[it]->surface_set	(t_noise_surf[it]);
            //	R_CHK						(t_noise_surf[it]->LockRect	(0,&R[it],0,0));
            //}
            //	Use DXGI_FORMAT_R8G8B8A8_SNORM

            static const int sampleSize = 4;
            u32	tempData[TEX_jitter_count][TEX_jitter*TEX_jitter];

            D3D10_TEXTURE2D_DESC	desc;
            desc.Width = TEX_jitter;
            desc.Height = TEX_jitter;
            desc.MipLevels = 1;
            desc.ArraySize = 1;
            desc.SampleDesc.Count = 1;
            desc.SampleDesc.Quality = 0;
            desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM;
            //desc.Usage = D3D10_USAGE_IMMUTABLE;
            desc.Usage = D3D10_USAGE_DEFAULT;
            desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
            desc.CPUAccessFlags = 0;
            desc.MiscFlags = 0;

            D3D10_SUBRESOURCE_DATA	subData[TEX_jitter_count];

            for (int it=0; it<TEX_jitter_count-1; it++)
            {
                subData[it].pSysMem = tempData[it];
                subData[it].SysMemPitch = desc.Width*sampleSize;
            }

            // Fill it,
            for (u32 y=0; y<TEX_jitter; y++)
            {
                for (u32 x=0; x<TEX_jitter; x++)
                {
                    DWORD	data	[TEX_jitter_count-1];
                    generate_jitter	(data,TEX_jitter_count-1);
                    for (u32 it=0; it<TEX_jitter_count-1; it++)
                    {
                        u32*	p	=	(u32*)
                                        (LPBYTE (subData[it].pSysMem)
                                         + y*subData[it].SysMemPitch
                                         + x*4);

                        *p	=	data	[it];
                    }
                }
            }

            //for (int it=0; it<TEX_jitter_count; it++)	{
            //	R_CHK						(t_noise_surf[it]->UnlockRect(0));
            //}

            for (int it=0; it<TEX_jitter_count-1; it++)
            {
                string_path					name;
                xr_sprintf						(name,"%s%d",r2_jitter,it);
                //R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it]));
                R_CHK( HW.pDevice->CreateTexture2D(&desc, &subData[it], &t_noise_surf[it]) );
                t_noise[it]					= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(name);
                t_noise[it]->surface_set	(t_noise_surf[it]);
                //R_CHK						(t_noise_surf[it]->LockRect	(0,&R[it],0,0));
            }

            float tempDataHBAO[TEX_jitter*TEX_jitter*4];

            // generate HBAO jitter texture (last)
            D3D10_TEXTURE2D_DESC	descHBAO;
            descHBAO.Width = TEX_jitter;
            descHBAO.Height = TEX_jitter;
            descHBAO.MipLevels = 1;
            descHBAO.ArraySize = 1;
            descHBAO.SampleDesc.Count = 1;
            descHBAO.SampleDesc.Quality = 0;
            descHBAO.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
            //desc.Usage = D3D10_USAGE_IMMUTABLE;
            descHBAO.Usage = D3D10_USAGE_DEFAULT;
            descHBAO.BindFlags = D3D10_BIND_SHADER_RESOURCE;
            descHBAO.CPUAccessFlags = 0;
            descHBAO.MiscFlags = 0;

            it = TEX_jitter_count-1;
            subData[it].pSysMem = tempDataHBAO;
            subData[it].SysMemPitch = descHBAO.Width*sampleSize * sizeof(float);

            // Fill it,
            for (u32 y=0; y<TEX_jitter; y++)
            {
                for (u32 x=0; x<TEX_jitter; x++)
                {
                    float numDir = 1.0f;
                    switch (ps_r_ssao)
                    {
                    case 1:
                        numDir = 4.0f;
                        break;
                    case 2:
                        numDir = 6.0f;
                        break;
                    case 3:
                        numDir = 8.0f;
                        break;
                    case 4:
                        numDir = 8.0f;
                        break;
                    }
                    float angle = 2 * PI * ::Random.randF(0.0f, 1.0f) / numDir;
                    float dist = ::Random.randF(0.0f, 1.0f);

                    float *p	=	(float*)
                                    (LPBYTE (subData[it].pSysMem)
                                     + y*subData[it].SysMemPitch
                                     + x*4*sizeof(float));
                    *p = (float)(_cos(angle));
                    *(p+1) = (float)(_sin(angle));
                    *(p+2) = (float)(dist);
                    *(p+3) = 0;
                }
            }

            string_path					name;
            xr_sprintf						(name,"%s%d",r2_jitter,it);
            //R_CHK	(D3DXCreateTexture	(HW.pDevice,TEX_jitter,TEX_jitter,1,0,D3DFMT_Q8W8V8U8,D3DPOOL_MANAGED,&t_noise_surf[it]));
            R_CHK( HW.pDevice->CreateTexture2D(&descHBAO, &subData[it], &t_noise_surf[it]) );
            t_noise[it]					= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(name);
            t_noise[it]->surface_set	(t_noise_surf[it]);


            //	Create noise mipped
            {
                //	Autogen mipmaps
                desc.MipLevels = 0;
                R_CHK( HW.pDevice->CreateTexture2D(&desc, 0, &t_noise_surf_mipped) );
                t_noise_mipped = dxRenderDeviceRender::Instance().Resources->_CreateTexture(r2_jitter_mipped);
                t_noise_mipped->surface_set(t_noise_surf_mipped);

                //	Update texture. Generate mips.

                HW.pDevice->CopySubresourceRegion( t_noise_surf_mipped, 0, 0, 0, 0, t_noise_surf[0], 0, 0 );

                D3DX10FilterTexture(t_noise_surf_mipped, 0, D3DX10_FILTER_POINT);
            }
        }
    }

    // PP
    s_postprocess.create				("postprocess");
    g_postprocess.create				(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX3,RCache.Vertex.Buffer(),RCache.QuadIB);

    // Menu
    s_menu.create						("distort");
    g_menu.create						(FVF::F_TL,RCache.Vertex.Buffer(),RCache.QuadIB);

    //
    dwWidth		= Device.dwWidth;
    dwHeight	= Device.dwHeight;
}