Ejemplo n.º 1
0
void Overlay::RenderMeshes()
{
    if(g_Globals.UsingOverlay && _Meshes.Length() > 0)
	{
        IDirect3DStateBlock9* pStateBlock = NULL;
        _Device->CreateStateBlock( D3D9Base::D3DSBT_ALL, &pStateBlock );

        const UINT MaxTextureSlots = 8;
        for(UINT TextureIndex = 0; TextureIndex < MaxTextureSlots; TextureIndex++)
        {
            _Device->SetTexture(TextureIndex, NULL);
        }

        D3D9Base::D3DXMATRIXA16 NewTransformWorld, NewTransformView, NewTransformProjection;
        NewTransformWorld = Matrix4ToD3DXMATRIX(Matrix4::Identity());
        NewTransformView = Matrix4ToD3DXMATRIX(Matrix4::Identity());
        NewTransformProjection = Matrix4ToD3DXMATRIX(_MeshTransform);

        _Device->SetTransform(D3DTS_WORLD, &NewTransformWorld);
        _Device->SetTransform(D3D9Base::D3DTS_VIEW, &NewTransformView);
        _Device->SetTransform(D3D9Base::D3DTS_PROJECTION, &NewTransformProjection);

        _Device->SetRenderState(D3D9Base::D3DRS_ALPHABLENDENABLE, FALSE);
        //_Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_TRUE);
        _Device->SetRenderState(D3D9Base::D3DRS_ZENABLE, D3D9Base::D3DZB_FALSE);
        _Device->SetRenderState(D3D9Base::D3DRS_LIGHTING, FALSE);
        _Device->SetRenderState(D3D9Base::D3DRS_ZFUNC, D3D9Base::D3DCMP_ALWAYS);
        _Device->SetRenderState(D3D9Base::D3DRS_ALPHATESTENABLE, FALSE);
        _Device->SetRenderState(D3D9Base::D3DRS_CULLMODE, D3D9Base::D3DCULL_NONE);

        const DWORD D3DMeshFlags = D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1;
        _Device->SetFVF(D3DMeshFlags);
        
        _Device->SetVertexShader(NULL);
        _Device->SetPixelShader(NULL);
        
        for(UINT MeshIndex = 0; MeshIndex < _Meshes.Length(); MeshIndex++)
        {
            Mesh &CurMesh = *(_Meshes[MeshIndex]);
            _Device->DrawIndexedPrimitiveUP(D3D9Base::D3DPT_TRIANGLELIST, 0, CurMesh.VertexCount(), CurMesh.FaceCount(), CurMesh.Indices(), D3D9Base::D3DFMT_INDEX32, CurMesh.Vertices(), sizeof(MeshVertex));
        }

        pStateBlock->Apply();
        pStateBlock->Release();
    }
}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------------
// Name: XBUtil_DeclaratorFromFVF()
// Desc: Create a vertex declaration from an FVF. Registers are assigned as
//       follows:
//          v0     = Vertex position
//          v1     = Vertex blend weights
//          v2     = Vertex normal
//          v3     = Vertex diffuse color
//          v4     = Vertex specular color
//       // v5     = Vertex fog (no FVF code)
//       // v6     = Vertex pointsize (no FVF code)
//       // v7     = Vertex back diffuse color (no FVF code)
//       // v8     = Vertex back specular color (no FVF code)
//          v9-v12 = Vertex texture coords
//-----------------------------------------------------------------------------
HRESULT XBUtil_DeclaratorFromFVF( DWORD dwFVF, 
                                  DWORD Declaration[MAX_FVF_DECL_SIZE] )
{
    // Start the declaration
    DWORD decl = 0;
    Declaration[decl++] = D3DVSD_STREAM(0);

    // Handle position
    DWORD dwPositionFVF = ( dwFVF & D3DFVF_POSITION_MASK );
    if( dwPositionFVF == D3DFVF_XYZRHW ) Declaration[decl++] = D3DVSD_REG( 0, D3DVSDT_FLOAT4 ); 
    else                                 Declaration[decl++] = D3DVSD_REG( 0, D3DVSDT_FLOAT3 ); 

    // Handle blend weights
    if( dwPositionFVF == D3DFVF_XYZB1 )  Declaration[decl++] = D3DVSD_REG( 1, D3DVSDT_FLOAT1 ); 
    if( dwPositionFVF == D3DFVF_XYZB2 )  Declaration[decl++] = D3DVSD_REG( 1, D3DVSDT_FLOAT2 ); 
    if( dwPositionFVF == D3DFVF_XYZB3 )  Declaration[decl++] = D3DVSD_REG( 1, D3DVSDT_FLOAT3 ); 
    if( dwPositionFVF == D3DFVF_XYZB4 )  Declaration[decl++] = D3DVSD_REG( 1, D3DVSDT_FLOAT4 ); 

    // Handle normal, diffuse, and specular
    if( dwFVF & D3DFVF_NORMAL )          Declaration[decl++] = D3DVSD_REG( 2, D3DVSDT_FLOAT3 );
    if( dwFVF & D3DFVF_DIFFUSE )         Declaration[decl++] = D3DVSD_REG( 3, D3DVSDT_D3DCOLOR );
    if( dwFVF & D3DFVF_SPECULAR )        Declaration[decl++] = D3DVSD_REG( 4, D3DVSDT_D3DCOLOR );

    // Handle texture coordinates
    DWORD dwNumTextures = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;

    for( DWORD i=0; i<dwNumTextures; i++ )
    {
        DWORD dwTexCoordSize = ( dwFVF & (0x00030000<<(i*2)) );

        DWORD dwNumTexCoords = 0;
        if( dwTexCoordSize == D3DFVF_TEXCOORDSIZE1(i) ) dwNumTexCoords = D3DVSDT_FLOAT1;
        if( dwTexCoordSize == D3DFVF_TEXCOORDSIZE2(i) ) dwNumTexCoords = D3DVSDT_FLOAT2;
        if( dwTexCoordSize == D3DFVF_TEXCOORDSIZE3(i) ) dwNumTexCoords = D3DVSDT_FLOAT3;
        if( dwTexCoordSize == D3DFVF_TEXCOORDSIZE4(i) ) dwNumTexCoords = D3DVSDT_FLOAT4;

        Declaration[decl++] = D3DVSD_REG( 9 + i, dwNumTexCoords );
    }

    // End the declarator
    Declaration[decl++] = D3DVSD_END();

    return S_OK;
}
Ejemplo n.º 3
0
Archivo: mesh.c Proyecto: bilboed/wine
static void D3DXGetFVFVertexSizeTest(void)
{
    UINT got;

    compare_vertex_sizes (D3DFVF_XYZ, 12);

    compare_vertex_sizes (D3DFVF_XYZB3, 24);

    compare_vertex_sizes (D3DFVF_XYZB5, 32);

    compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24);

    compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX1 |
        D3DFVF_TEXCOORDSIZE1(0), 16);
    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX2 |
        D3DFVF_TEXCOORDSIZE1(0) |
        D3DFVF_TEXCOORDSIZE1(1), 20);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX1 |
        D3DFVF_TEXCOORDSIZE2(0), 20);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX2 |
        D3DFVF_TEXCOORDSIZE2(0) |
        D3DFVF_TEXCOORDSIZE2(1), 28);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX6 |
        D3DFVF_TEXCOORDSIZE2(0) |
        D3DFVF_TEXCOORDSIZE2(1) |
        D3DFVF_TEXCOORDSIZE2(2) |
        D3DFVF_TEXCOORDSIZE2(3) |
        D3DFVF_TEXCOORDSIZE2(4) |
        D3DFVF_TEXCOORDSIZE2(5), 60);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX8 |
        D3DFVF_TEXCOORDSIZE2(0) |
        D3DFVF_TEXCOORDSIZE2(1) |
        D3DFVF_TEXCOORDSIZE2(2) |
        D3DFVF_TEXCOORDSIZE2(3) |
        D3DFVF_TEXCOORDSIZE2(4) |
        D3DFVF_TEXCOORDSIZE2(5) |
        D3DFVF_TEXCOORDSIZE2(6) |
        D3DFVF_TEXCOORDSIZE2(7), 76);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX1 |
        D3DFVF_TEXCOORDSIZE3(0), 24);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX4 |
        D3DFVF_TEXCOORDSIZE3(0) |
        D3DFVF_TEXCOORDSIZE3(1) |
        D3DFVF_TEXCOORDSIZE3(2) |
        D3DFVF_TEXCOORDSIZE3(3), 60);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX1 |
        D3DFVF_TEXCOORDSIZE4(0), 28);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX2 |
        D3DFVF_TEXCOORDSIZE4(0) |
        D3DFVF_TEXCOORDSIZE4(1), 44);

    compare_vertex_sizes (
        D3DFVF_XYZ |
        D3DFVF_TEX3 |
        D3DFVF_TEXCOORDSIZE4(0) |
        D3DFVF_TEXCOORDSIZE4(1) |
        D3DFVF_TEXCOORDSIZE4(2), 60);

    compare_vertex_sizes (
        D3DFVF_XYZB5 |
        D3DFVF_NORMAL |
        D3DFVF_DIFFUSE |
        D3DFVF_SPECULAR |
        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), 180);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
//
// Populate a D3DGeometry object from a Maya mesh
//
bool D3DGeometry::Populate( const MDagPath& dagPath, LPDIRECT3DDEVICE9 D3D)
{
	Release();
	MFnMesh mesh( dagPath.node());

	// Figure out texturing
	//
	bool haveTexture = false;
	int	numUVsets = mesh.numUVSets();
	MString uvSetName;
	MObjectArray textures;
	if (numUVsets > 0)
	{
		mesh.getCurrentUVSetName( uvSetName );
		// Always send down uvs for now, since we don't dirty the populate
		// based on material texture connection.
		//
		//MStatus status = mesh.getAssociatedUVSetTextures(uvSetName, textures);
		//if (status == MS::kSuccess && textures.length())
		{
			haveTexture = true;
		}
	}

	bool haveColors = false;
	int	numColors = mesh.numColorSets();
	MString colorSetName;
	if (numColors > 0)
	{
		haveColors = true;
		mesh.getCurrentColorSetName(colorSetName);
	}

	bool useNormals = true;

	// Setup our requirements needs.
	MGeometryRequirements requirements;
	requirements.addPosition();
	if (useNormals)
		requirements.addNormal();
	if (haveTexture)
		requirements.addTexCoord( uvSetName );
	if (haveColors)
		requirements.addColor( colorSetName );

	// Test for tangents and binormals
	bool testBinormal = false;
	if (testBinormal)
		requirements.addBinormal( uvSetName );
	bool testTangent= false;
	if (testTangent)
		requirements.addTangent( uvSetName );

	MGeometry geom = MGeometryManager::getGeometry( dagPath, requirements, NULL );

	unsigned int numPrims = geom.primitiveArrayCount();
	if( numPrims)
	{
		const MGeometryPrimitive prim = geom.primitiveArray(0);

		NumIndices = prim.elementCount();
		if( NumIndices)
		{
			//MGeometryData::ElementType primType = prim.dataType();
			unsigned int *idx = (unsigned int *) prim.data();

			// Get the position data
			const MGeometryData pos = geom.position();
			float * posPtr = (float * )pos.data();
			if( !idx || !posPtr) return false;
			NumVertices = pos.elementCount();

			// Start building our vertex format. We always have position, so
			// start with that and add in all the elements we find along the way
			FVF = D3DFVF_XYZ;
			Stride = sizeof( float) * 3;

			// Get the normals data
			float * normPtr = NULL;
			if( useNormals)
			{
				const MGeometryData norm = geom.normal();				
				normPtr = (float * )norm.data();
				Stride += sizeof( float) * 3;
				FVF |= D3DFVF_NORMAL;
			}

			// Get the texture coordinate data
			float *uvPtr = NULL;
			if( haveTexture)
			{
				const MGeometryData uvs = geom.texCoord( uvSetName );
				uvPtr = (float *)uvs.data();
				Stride += sizeof( float) * 2;
				FVF |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
			}

			unsigned int numColorComponents = 4;
			float *clrPtr = NULL;
			if (haveColors)
			{
				const MGeometryData clrs = geom.color( colorSetName );
				clrPtr = (float *)clrs.data();
			}
			else if (testBinormal)
			{
				const MGeometryData binorm = geom.binormal( uvSetName );
				clrPtr = (float *)binorm.data();
				numColorComponents = 3;
			}
			else if (testTangent)
			{
				const MGeometryData tang = geom.tangent( uvSetName );
				clrPtr = (float *)tang.data();
				numColorComponents = 3;
			}

			// Allocate our vertex buffer
			//
			if( D3D->CreateVertexBuffer( Stride * NumVertices, D3DUSAGE_WRITEONLY, FVF, 
											D3DPOOL_DEFAULT, &VertexBuffer, NULL) != D3D_OK)
			{
				MGlobal::displayWarning( "Direct3D renderer : Unable to allocate vertex buffer\n");
				return false;
			}

			// Copy our vertex data into the buffer
			//
			float* VertexData = NULL;
			int FloatsPerVertex = Stride / sizeof( float);
			int StrideOffset = FloatsPerVertex - 3;
			//MGlobal::displayInfo( MString( "Allocating buffers for ") + NumVertices + MString( " verts and ") + NumIndices + MString( " indices\n"));
			VertexBuffer->Lock( 0, 0, (void**)&VertexData, D3DLOCK_DISCARD);
			for( unsigned int i = 0; i < NumVertices; i++)
			{
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				*VertexData++ = *posPtr++;
				VertexData += StrideOffset;
			}
			VertexData -= NumVertices * FloatsPerVertex - 3;

			if( normPtr)
			{
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					*VertexData++ = *normPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 3;
			}

			if( uvPtr)
			{
				StrideOffset = FloatsPerVertex - 2;
				for( unsigned int i = 0; i < NumVertices; i++)
				{
					*VertexData++ = *uvPtr++;
					*VertexData++ = 1.0f - *uvPtr++;
					VertexData += StrideOffset;
				}
				VertexData -= NumVertices * FloatsPerVertex - 2;
			}

			VertexBuffer->Unlock();

			// Allocate our index buffer
			//
			if( D3D->CreateIndexBuffer( NumIndices * sizeof( DWORD), 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &IndexBuffer, NULL) != D3D_OK)
			{
				MGlobal::displayWarning( "Direct3D renderer : Unable to allocate index buffer\n");
				return false;
			}

			// Copy our index data into the buffer
			//
			unsigned int* IndexData = NULL;
			IndexBuffer->Lock( 0, 0, (void**)&IndexData, D3DLOCK_DISCARD);
			memcpy( IndexData, idx, NumIndices * sizeof(DWORD));
			IndexBuffer->Unlock();
		}
	}
	return IndexBuffer && VertexBuffer;
}
Ejemplo n.º 7
0
void CXboxParticleShaded::plat_render( void )
{
	// Draw the particles.
	if( m_num_particles > 0 )
	{
		// Used to figure the right and up vectors for creating screen-aligned particle quads.
		D3DXMATRIX *p_matrix = (D3DXMATRIX*)&NxXbox::EngineGlobals.view_matrix;

		// Concatenate p_matrix with the emmission angle to create the direction.
		Mth::Vector up( 0.0f, 1.0f, 0.0f );

		// Get the 'right' vector as the cross product of camera 'at and world 'up'.
		Mth::Vector at( p_matrix->m[0][2], p_matrix->m[1][2], p_matrix->m[2][2] );
		Mth::Vector screen_right	= Mth::CrossProduct( at, up );
		Mth::Vector screen_up		= Mth::CrossProduct( screen_right, at );

		screen_right.Normalize();
		screen_up.Normalize();

		int				lp;
		CParticleEntry	*p_particle;
		float			*p_v;
//		Mth::Vector		min, max;	// For dynamic bounding box calculation.
	
		// Obtain push buffer lock.
		DWORD *p_push; 
		DWORD dwords_per_particle	= 24;
		DWORD dword_count			= dwords_per_particle * m_num_particles;

		// Submit particle material.
		mp_engine_particle->mp_material->Submit();
		
		// Set up correct vertex and pixel shader.
		NxXbox::set_vertex_shader( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2( 0 ));
		NxXbox::set_pixel_shader( PixelShader0 );
		
		// The additional number (+5 is minimum) is to reserve enough overhead for the encoding parameters. It can safely be more, but no less.
		p_push = D3DDevice_BeginPush( dword_count + 16 );

		// Note that p_push is returned as a pointer to write-combined memory. Writes to write-combined memory should be
		// consecutive and in increasing order. Reads should be avoided. Additionally, any CPU reads from memory or the
		// L2 cache can force expensive partial flushes of the 32-byte write-combine cache.
		p_push[0]	= D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );
		p_push[1]	= D3DPT_QUADLIST;
		p_push		+= 2;

		// Set up loop variables here, since we be potentially enetering the loop more than once.
		lp			= 0;
		p_particle	= mp_particle_array;
		p_v			= mp_vertices;

		while( dword_count > 0 )
		{
			int dwords_written = 0;

			// NOTE: A maximum of 2047 DWORDs can be specified to D3DPUSH_ENCODE. If there is more than 2047 DWORDs of vertex
			// data, simply split the data into multiple D3DPUSH_ENCODE( D3DPUSH_INLINE_ARRAY ) sections.
			p_push[0] = D3DPUSH_ENCODE( D3DPUSH_NOINCREMENT_FLAG | D3DPUSH_INLINE_ARRAY, ( dword_count > 2047 ) ? ((int)( 2047 / dwords_per_particle )) * dwords_per_particle: dword_count );
			++p_push;
		
			for( ; lp < m_num_particles; lp++, p_particle++, p_v += 3 )
			{
				// Check to see if writing another particle will take us over the edge.
				if(( dwords_written + dwords_per_particle ) > 2047 )
				{
					break;
				}

				float terp	= p_particle->m_time / p_particle->m_life;
				float w		= p_particle->m_sw + ( ( p_particle->m_ew - p_particle->m_sw ) * terp );
				float h		= p_particle->m_sh + ( ( p_particle->m_eh - p_particle->m_sh ) * terp );

				// Todo: Move hook to matrix/emitter code to cut down on per particle calculation.
				Mth::Vector	pos( p_v[0] + m_pos[X], p_v[1] + m_pos[Y], p_v[2] + m_pos[Z] );
				Mth::Vector	ss_right, ss_up, ss_pos;
				Mth::Vector tmp;
	
				// Dynamic bounding box calculation.
//				if( lp == 0 )
//				{
//					min = pos;
//					max = pos;
//				}
//				else
//				{
//					if( pos[X] < min[X] ) min[X] = pos[X]; else if( pos[X] > max[X] ) max[X] = pos[X];
//					if( pos[Y] < min[Y] ) min[Y] = pos[Y]; else if( pos[Y] > max[Y] ) max[Y] = pos[Y];
//					if( pos[Z] < min[Z] ) min[Z] = pos[Z]; else if( pos[Z] > max[Z] ) max[Z] = pos[Z];
//				}
		
				ss_right	= screen_right * w;
				ss_up		= screen_up * h;

				Image::RGBA color[4];
				Image::RGBA *p_col0;
				Image::RGBA *p_col1;
		
				if( m_mid_time >= 0.0f )
				{
					if( terp < m_mid_time )
					{
						p_col0 = m_start_color;
						p_col1 = m_mid_color;

						// Adjust interpolation for this half of the color blend.
						terp = terp / m_mid_time;
					}
					else
					{
						p_col0 = m_mid_color;
						p_col1 = m_end_color;

						// Adjust interpolation for this half of the color blend.
						terp = ( terp - m_mid_time ) / ( 1.0f - m_mid_time );
					}
				}
				else
				{
					// No mid color specified.
					p_col0 = m_start_color;
					p_col1 = m_end_color;
				}

				for ( int c = 0; c < 4; c++ )
				{
					Image::RGBA start = *p_col0++;
					Image::RGBA end = *p_col1++;

					// Swap red and blue here.
					color[c].b = start.r + (uint8)(( ((float)( end.r - start.r )) * terp ));
					color[c].g = start.g + (uint8)(( ((float)( end.g - start.g )) * terp ));
					color[c].r = start.b + (uint8)(( ((float)( end.b - start.b )) * terp ));
					color[c].a = start.a + (uint8)(( ((float)( end.a - start.a )) * terp ));
				}
		
				tmp			= pos - ss_right + ss_up;
				p_push[0]	= *((DWORD*)&tmp[X] );
				p_push[1]	= *((DWORD*)&tmp[Y] );
				p_push[2]	= *((DWORD*)&tmp[Z] );
				p_push[3]	= *((DWORD*)&color[0] );
				p_push[4]	= 0x00000000UL;
				p_push[5]	= 0x00000000UL;
				p_push		+= 6;
	
				tmp			= pos + ss_right + ss_up;		
				p_push[0]	= *((DWORD*)&tmp[X] );
				p_push[1]	= *((DWORD*)&tmp[Y] );
				p_push[2]	= *((DWORD*)&tmp[Z] );
				p_push[3]	= *((DWORD*)&color[1] );
				p_push[4]	= 0x3F800000UL;
				p_push[5]	= 0x00000000UL;
				p_push		+= 6;

				tmp			= pos + ss_right - ss_up;		
				p_push[0]	= *((DWORD*)&tmp[X] );
				p_push[1]	= *((DWORD*)&tmp[Y] );
				p_push[2]	= *((DWORD*)&tmp[Z] );
				p_push[3]	= *((DWORD*)&color[2] );
				p_push[4]	= 0x3F800000UL;
				p_push[5]	= 0x3F800000UL;
				p_push		+= 6;
		
				tmp			= pos - ss_right - ss_up;		
				p_push[0]	= *((DWORD*)&tmp[X] );
				p_push[1]	= *((DWORD*)&tmp[Y] );
				p_push[2]	= *((DWORD*)&tmp[Z] );
				p_push[3]	= *((DWORD*)&color[3] );
				p_push[4]	= 0x00000000UL;
				p_push[5]	= 0x3F800000UL;
				p_push		+= 6;

				dwords_written	+= dwords_per_particle;
				dword_count		-= dwords_per_particle;
			}
		}

		p_push[0] = D3DPUSH_ENCODE( D3DPUSH_SET_BEGIN_END, 1 );
		p_push[1] = 0;
		p_push += 2;
		D3DDevice_EndPush( p_push );

		// Set the mesh bounding box and sphere.
//		mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMin( min );
//		mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_bbox.SetMax( max );
//		mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center = D3DXVECTOR3( min[X] + (( max[X] - min[X] ) * 0.5f ), min[Y] + (( max[Y] - min[Y] ) * 0.5f ), min[Z] + (( max[Z] - min[Z] ) * 0.5f ));
//		mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius = 360.0f;

		// And the scene bounding sphere.
//		mp_engine_particle->mp_scene->m_sphere_center = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_center;
//		mp_engine_particle->mp_scene->m_sphere_radius = mp_engine_particle->mp_scene->m_semitransparent_meshes[0]->m_sphere_radius;
	}
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
/*
D3D9Mesh.cpp
Written by Matthew Fisher

D3D9Mesh is a DirectX instance of the BaseMesh class.
In general all these functions just call DirectX equivalents.
Most of the functionality is gained through the BaseMesh functions.
*/

#ifdef USE_D3D9

//our vertices have a color, normal, position, and two texture coordinates.  This is reflected in D3DMeshFVF
const DWORD D3DMeshFVF = D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1;

//our meshes have 32-bit indices (D3DXMESH_32BIT) and we want DirectX to handle moving them in and out of memory (D3DXMESH_MANAGED)
const DWORD D3DMeshOptions = D3DXMESH_32BIT | D3DXMESH_MANAGED;

//basic memory management...

D3D9Mesh::D3D9Mesh()
{
    _Mesh = NULL;
    _GD = NULL;
    _Vertices = NULL;
    _Indices = NULL;
}

D3D9Mesh::D3D9Mesh(GraphicsDevice &_GD)
{
    _Mesh = NULL;
    _Vertices = NULL;
Ejemplo n.º 10
0
static void test_fvf_decl_conversion(IDirect3DDevice9 *pDevice)
{

    HRESULT hr;
    unsigned int i;

    IDirect3DVertexDeclaration9* default_decl = NULL;
    DWORD default_fvf = D3DFVF_SPECULAR | D3DFVF_DIFFUSE;
    D3DVERTEXELEMENT9 default_elements[] =
        { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 },
          { 0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };

    /* Create a default declaration and FVF that does not match any of the tests */
    hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, default_elements, &default_decl );
    ok(SUCCEEDED(hr), "CreateVertexDeclaration returned %#x, expected %#x\n", hr, D3D_OK);
    if (FAILED(hr)) goto cleanup;

    /* Test conversions from vertex declaration to an FVF.
     * For some reason those seem to occur only for POSITION/POSITIONT,
     * Otherwise the FVF is forced to 0 - maybe this is configuration specific */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, D3DFVF_XYZ, TRUE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, D3DFVF_XYZRHW, TRUE));
    }
    for (i = 0; i < 4; i++) {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1+i, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] = 
            { { 0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* Make sure textures of different sizes work */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* Make sure the TEXCOORD index works correctly - try several textures */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
              { 0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 },
              { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2 },
              { 0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* No FVF mapping available */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* Try empty declaration */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] = { D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* Now try a combination test */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 },
              { 0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 },
              { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 },
              { 0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
              { 0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1 }, D3DDECL_END() };
        VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0, FALSE));
    }

    /* Test conversions from FVF to a vertex declaration 
     * These seem to always occur internally. A new declaration object is created if necessary */

    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZ, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZW, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
          { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZRHW, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
           D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB5, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB1, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR, test_buffer, 1));
    }
    {
         CONST D3DVERTEXELEMENT9 test_buffer[] =
             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
               { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB2, test_buffer, 1));
    }
    {
         CONST D3DVERTEXELEMENT9 test_buffer[] =
             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
               { 0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
               { 0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
             D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4, test_buffer, 1));
     }
     {
         CONST D3DVERTEXELEMENT9 test_buffer[] =
             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
               { 0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
               { 0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
             D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR, test_buffer, 1));
     }
     {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB3, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
              { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
              { 0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_NORMAL, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_PSIZE, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_DIFFUSE, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_SPECULAR, test_buffer, 1));
    }

    /* Make sure textures of different sizes work */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, test_buffer, 1));
    }
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1, test_buffer, 1));
    }

    /* Make sure the TEXCOORD index works correctly - try several textures */
    {
        CONST D3DVERTEXELEMENT9 test_buffer[] =
            { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
              { 0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 },
              { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2 },
              { 0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3 }, D3DDECL_END() };
        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
            D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2) |
            D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4, test_buffer, 1));
    }

    /* Now try a combination test  */
    {
       CONST D3DVERTEXELEMENT9 test_buffer[] =
                { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
                  { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
                  { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 },
                  { 0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 },
                  { 0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
                  { 0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 }, D3DDECL_END() };
       VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4 | D3DFVF_SPECULAR | D3DFVF_DIFFUSE |
           D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2, test_buffer, 1));
    }

    /* Setting the FVF to 0 should result in no change to the default decl */
    VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, 0, default_elements, 0));

    cleanup:
    IDirect3DDevice9_SetVertexDeclaration ( pDevice, NULL );
    if ( default_decl ) IUnknown_Release (default_decl);
}