Transparency + X-Files

Started by
14 comments, last by QuinnJohns 16 years ago
Alrighty, so if I'm not mistaken xfiles can have transparency, right? I believe I had seen before, that they were capable of being set to some transparent alpha value. Anyhow, how do I accomplish something such as that? I'm asking because I'm thinking about doing a simple single player RPG on the side, where I'll have the player models walking around a level on a specified camera angle. Now, the dilemna I'm going to be facing is that when the person walks under a tree, from the line of sight, how am I going to be able to handle some sort of transparency on-the-fly, of that xfile that he's hidden under? or near? ** I will mention, it doesn't have to be directly under, but anything I find obstructing the view of the player? Thanks in advance. -Quinn
[size="2"][size="1"][size="2"]- Quinn
[size="2"][size="1"][size="2"]Software Developer, Mintrus
Advertisement
Are you using fixed-function or shaders? For shaders having transparency is easy: simply output a color value with alpha < 0 and make sure alpha blending is enabled in the device render states. If you're using the effects framework you can include those render states right in the fx file, and keep everything wrapped up in one tidy package.

With FFP you will have to set texture stage states that use data from either vertices, materials, textures, or a constant value to determine the final alpha value. For your purposes using a constant alpha value is probably best, as it won't require you to dynamically modify vertices or textures.
	void MeshAlpha(LPDIRECT3DDEVICE9 p_d3dDevice, float Alpha)	{		D3DXMATRIX matRotation,matTranslation;		D3DXMatrixTranslation(&matTranslation,0,0,0);		p_d3dDevice->SetTransform(D3DTS_TEXTURE0,&(matTranslation));		p_d3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS,	D3DTTFF_COUNT2  );		for( DWORD i=0; i< NumMaterials; i++ )		{			// Set the material and texture for this subset			Materials.Diffuse.a = Alpha;			p_d3dDevice->SetMaterial( &Materials );			p_d3dDevice->SetTexture( 0, Textures );			p_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);		//alpha blending enabled			p_d3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);	//source blend factor			p_d3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);	//destination blend factor			// Draw the mesh subset			Mesh->DrawSubset( i );		}		D3DXMatrixIdentity(&matRotation);		p_d3dDevice->SetTransform(D3DTS_TEXTURE0,&(matRotation));		p_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,false);				p_d3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, 			D3DTTFF_DISABLE );	}


I basically copied my CMesh - MeshAlpha function in here. So, basically, what I did with my MeshAlpha function is all I need right? I'm not using shaders, I may learn shaders in the future, but this is something minimal I'm trying to accomplish for its uses.

Thanks for the help.
[size="2"][size="1"][size="2"]- Quinn
[size="2"][size="1"][size="2"]Software Developer, Mintrus
So, theoretically, if what I posted is what I need, how would I go about checking if the objects that need transparency are in my line of sight (behind my tree, for example)? and then when I call that draw function MeshAlpha(), I can just specify a new alpha value, so instead of my 1.0f do like 0.5f.


Does that sound right? Thanks for any help.
[size="2"][size="1"][size="2"]- Quinn
[size="2"][size="1"][size="2"]Software Developer, Mintrus
I don't think that code sets the texture stage state the way you want to. You need to specify that you're getting your alpha value from your diffuse albedo, which is where you're setting it. I believe you do that like this:

p_d3dDevice->SetTextureStageState( D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );p_d3dDevice->SetTextureStageState( D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );


This assumes you've set the current material as your source for lighting calculations, using IDirect3DDevice9::SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ).
So, what about finding out if the player model is behind the particular objects like trees, and such - to apply that transparency? I would think its something trivial, but I have no idea where to start.

-- added --
Like I posted earlier, my camera is gonna be on a fixed angle, basically like a tilted topdown view, so on the player can potentially be behind the object, so I'm just looking to find a way to 'determine' if its obstructing the view of my model and then give me an opportunity to apply my alpha to it.
[size="2"][size="1"][size="2"]- Quinn
[size="2"][size="1"][size="2"]Software Developer, Mintrus
I don't have much experience with that sort of thing, but I'd imagine you'd do it by representing objects like trees as simple bounding volumes (such as a box or a square) and then doing a visibility test to see if the volume occludes the area where the player character is. So the basic algorithm would be:

-Convert object position to view space-If object's view-space z is > 0 and < player's view-space x    -Calculate object's coverage in screen space    -If object's screen space height and width cover the player's height and width        -Make transparent
So, basically, what you are saying is.... have two bounding volumes and do a collision test, if it is within the bounding volume's collision range, then set transparency right? Just trying to clarify...


and umm...

Quote:
-Convert object position to view space


How do you do that, per-se?
[size="2"][size="1"][size="2"]- Quinn
[size="2"][size="1"][size="2"]Software Developer, Mintrus
Transform the object's world-space position by your view matrix.

D3DXVECTOR3 vObjectPosVS;D3DXVec3TransformCoord( &vObjectPosVS, &matView, &vObjectPosWS );
In response to your PM...

I wouldn't do a 3D collision test, I would instead do some kind of overlap test. Basically this would be like a collision test, but in 2D screen space. It would look something like this, assuming you've calculated a bounding radius for both the obstructing object and the player:

D3DXVECTOR3 vObjectPosVS, vPlayerPosVS;D3DXVec3TransformCoord( &vObjectPosVS, &matView, &vObjectPosWS );D3DXVec3TransformCoord( &vPlayerPosVS, &matView, &vPlayerPosWS );if ( ( vObjectPosVS.z + fObjectRadius > 0 ) && ( vObjectPosVS.z - fObjectRadius < vPlayerPosVS.z ) ){	D3DXVECTOR3 vPositionsVS [4];	D3DXVECTOR3 vPositionsSS [4];	D3DXVECTOR2 vObjectMaxSS;	D3DXVECTOR2 vObjectMinSS;	D3DXVECTOR2 vPlayerMaxSS;	D3DXVECTOR2 vPlayerMinSS;	// Calculate the area the object bounding volume takes up in view space	vPositionsVS[0] = D3DXVECTOR3( vObjectPosVS.x + fObjectRadius, vObjectPosVS.y, vObjectPosVS.z );	vPositionsVS[1] = D3DXVECTOR3( vObjectPosVS.x - fObjectRadius, vObjectPosVS.y, vObjectPosVS.z );	vPositionsVS[2] = D3DXVECTOR3( vObjectPosVS.x, vObjectPosVS.y + fObjectRadius, vObjectPosVS.z );	vPositionsVS[3] = D3DXVECTOR3( vObjectPosVS.x, vObjectPosVS.y - fObjectRadius, vObjectPosVS.z );	// Calculate the area the object bounding volume takes up in screen space	D3DXVec3TransformCoordArray( vPositionsSS, sizeof(D3DXVECTOR3), vPositionsVS, sizeof(D3DXVECTOR3), &matProjection, 4 ); 	vObjectMaxSS.x = vPositionsSS[0].x;	vObjectMinSS.x = vPositionsSS[1].x;	vObjectMaxSS.y = vPositionsSS[2].y;	vObjectMinSS.y = vPositionsSS[3].y;	// Calculate the area the player bounding volume takes up in view space	vPositionsVS[0] = D3DXVECTOR3( vPlayerPosVS.x + fPlayerRadius, vPlayerPosVS.y, vPlayerPosVS.z );	vPositionsVS[1] = D3DXVECTOR3( vPlayerPosVS.x - fPlayerRadius, vPlayerPosVS.y, vPlayerPosVS.z );	vPositionsVS[2] = D3DXVECTOR3( vPlayerPosVS.x, vPlayerPosVS.y + fPlayerRadius, vPlayerPosVS.z );	vPositionsVS[3] = D3DXVECTOR3( vPlayerPosVS.x, vPlayerPosVS.y - fPlayerRadius, vPlayerPosVS.z );	// Calculate the area the player bounding volume takes up in screen space	D3DXVec3TransformCoordArray( vPositionsSS, sizeof(D3DXVECTOR3), vPositionsVS, sizeof(D3DXVECTOR3), &matProjection, 4 ); 	vPlayerMaxSS.x = vPositionsSS[0].x;	vPlayerMinSS.x = vPositionsSS[1].x;	vPlayerMaxSS.y = vPositionsSS[2].y;	vPlayerMinSS.y = vPositionsSS[3].y;	// Check for overlap	if ( vObjectMaxSS.x < vPlayerMinSS.x )		return;	if ( vObjectMaxSS.y < vPlayerMinSS.y )		return;	if ( vObjectMinSS.x > vPlayerMaxSS.x )		return;	if ( vObjectMinSS.y < vPlayerMaxSS.y )		return;	// If we got here, the object is obstructing and should be made transparent}


Also this is obvious but you wouldn't need to re-calculate the player's screen-space bounding volume for every object, I just do it there for ease of understanding.

This topic is closed to new replies.

Advertisement