Jump to content

  • Log In with Google      Sign In   
  • Create Account


Alpha Channel makes opaque objects disappear


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 03 June 2011 - 10:19 AM

Hi,
When I enable alpha channel, some opaque objects gone missing
m_pDevice->SetRenderState (D3DRS_ALPHABLENDENABLE, true);
m_pDevice->SetRenderState (D3DRS_ZENABLE, true);

when I turn off the depth buffer, everything appears in the scene
but transparency was lost.
I have optimized the mesh with Optimize( ATTRSORT....
And using an attribute table, The materials buffer should be correct, otherwise the main object won't appear
when I disable z-buffer.
Any thoughts.. (Post pics later)
Thanks
Jack

Sponsor:

#2 Paul65   Members   -  Reputation: 126

Like
1Likes
Like

Posted 04 June 2011 - 02:59 AM

Alpha blending has no effect on z buffer. So if a transparent face is in front of something solid but is drawn before it in the rendering, the solid object wont be drawn. Is this maybe your problem? When I've written rendering code before that uses alpha transparency, I've done the rendering in 2 passes, first of all the solid stuff then the transparent.

Hi,
When I enable alpha channel, some opaque objects gone missing

m_pDevice->SetRenderState (D3DRS_ALPHABLENDENABLE, true);
m_pDevice->SetRenderState (D3DRS_ZENABLE, true);

when I turn off the depth buffer, everything appears in the scene
but transparency was lost.
I have optimized the mesh with Optimize( ATTRSORT....
And using an attribute table, The materials buffer should be correct, otherwise the main object won't appear
when I disable z-buffer.
Any thoughts.. (Post pics later)
Thanks
Jack



#3 GreaseMonkey   Members   -  Reputation: 102

Like
1Likes
Like

Posted 04 June 2011 - 03:47 AM

m_pDevice->SetRenderState (D3DRS_ALPHABLENDENABLE, true);
m_pDevice->SetRenderState (D3DRS_ZENABLE, true);


Can you post some more code than this? the problem no doubt lies in how you are setting your render states

#4 kauna   Crossbones+   -  Reputation: 2290

Like
1Likes
Like

Posted 04 June 2011 - 04:23 AM

These opaque objects disappearing don't happen to have alpha component in their texture or perhaps the material values contain zero alpha values?

- basically you should turn on alpha blending just for objects requiring it. So "global" alpha blend enable for every object isn't good approach.
- also, keep in mind that alpha transparency is draw order dependent procedure.

Cheers!





#5 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 04 June 2011 - 05:55 AM

u32 CPerfectSimView::Draw(float fElapsedTime)
{
	CPerfectSimDoc *pDoc = GetDocument();
	m_fElapsedTime = fElapsedTime;



	pDoc->GetCamera()->Update(m_fElapsedTime, false);

//	SetPerspective();
//	SetWorld2View();
	
	m_pDevice->SetRenderState(D3DRS_FORCE_DWORD , true);
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
	m_pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, true );
	

	m_pDevice->SetRenderState( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA) ;
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
	m_pDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );

	m_pDevice->SetRenderState(D3DRS_ZENABLE, false);
	m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
 
	m_pDevice->SetRenderState(D3DRS_ALPHAREF, 0x00000001);
	m_pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_FORCE_DWORD | D3DCMP_ALWAYS );
		m_pDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.5, 0.5, 0.5, 1.0));
		
   m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

 	
	// normalize since objects are being scaled therefore normals aren't correct anymore
	m_pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);

	

	m_pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
	m_pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
	m_pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
	m_pDevice->SetRenderState(D3DRS_LIGHTING, true);

   

	m_pDevice->LightEnable(DIRECTIONAL, true);

	mFX->SetValue(mhLight, &mLight, sizeof(DirLight));
	mFX->SetValue(mAmbientLight, &mLight.ambient, sizeof(D3DXCOLOR));
	mFX->SetValue(mDiffuseLight, &mLight.diffuse, sizeof(D3DXCOLOR));
	D3DXVECTOR3 v(0.0f, -1.0f, 0.0);
	mFX->SetValue(mLightVecW, &v, sizeof(D3DXVECTOR3));


 	

	ProcessTask();
	 
	pDoc->WHObj->Render();


The code is very likely to be wrong. Had no ideas how to correct this mess :) Thanks Jack

#6 kauna   Crossbones+   -  Reputation: 2290

Like
1Likes
Like

Posted 04 June 2011 - 03:38 PM

Hi,

I took a quick look in your code and I got impression that you are mixing fixed function pipeline stuff and effect stuff. Are you using vertex/pixel shaders?

My knowledge of the old SetRenderState functions start to get rusty, but "D3DCMP_FORCE_DWORD" flag is definetely wrong. You seem to use it in several occasions. It is a enum for the compilers. However, it shouldn't have significance here or anywhere.




m_pDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );


The above line doesn't have meaning unless you set D3DRS_COLORVERTEX to true.


As you said, it is a mess. Especially if you mix effect files and shaders with ffp processing. Can you show more code perhaps? Show some shaders?


Cheers!

#7 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 12:15 AM

This is the shader code i am using
thanks very much
  

struct Mtrl
{
	float4 ambient;
	float4 diffuse;
	float4 spec;
	float  specPower;
};

struct DirLight
{
	float4 ambient;
	float4 diffuse;
	float4 spec;
	float3 dirW;  
};

uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInvTrans;
uniform extern float4x4 gWVP;
uniform extern Mtrl 	gMtrl;
uniform extern DirLight gLight;
uniform extern float3   gEyePosW;
uniform extern texture  gTex;

 

sampler TexS = sampler_state
{
	Texture = <gTex>;
	MinFilter = Anisotropic;
	MagFilter = LINEAR;
	MipFilter = Point;
	MaxAnisotropy = 8;
	AddressU  = WRAP;
	AddressV  = WRAP;
 };

 
struct OutputVS
{
	float4 posH	: POSITION0;
	float3 normalW : TEXCOORD0;
	float3 toEyeW  : TEXCOORD1;
	float2 tex0	: TEXCOORD2;
	float4 color   : COLOR0;
};

OutputVS PhongDirLtTexVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
{
	// Zero out our output.
	OutputVS outVS = (OutputVS)0;
	
	// Transform normal to world space.
	outVS.normalW = mul(float4(normalL, 0.0f), gWorldInvTrans).xyz;
	
	// Transform vertex position to world space.
	float3 posW  = mul(float4(posL, 1.0f), gWorld).xyz;
	
	// Compute the unit vector from the vertex to the eye.
	outVS.toEyeW = gEyePosW - posW;


	// Transform normal to world space.
	float3 normalW = mul(float4(normalL, 0.0f), gWVP).xyz;
	normalW = normalize(normalW);

	// Compute the color: Equation 10.2.
	//float s = max(dot(gLightVecW, normalW), 0.0f);
	//float3 diffuse = s*(gDiffuseMtrl*gDiffuseLight).rgb;
	//float3 ambient = gAmbientMtrl*gAmbientLight;
//	outVS.color.rgb = ambient + diffuse;
//	outVS.color.a   = gDiffuseMtrl.a;
	
	// Transform to homogeneous clip space.
	outVS.posH = mul(float4(posL, 1.0f), gWVP);
	
	// Pass on texture coordinates to be interpolated in rasterization.
	outVS.tex0 = tex0;

	// Done--return the output.
	return outVS;
}

float4 PhongDirLtTexPS(float3 normalW : TEXCOORD0, float3 toEyeW  : TEXCOORD1, float2 tex0 : TEXCOORD2) : COLOR
{
	// Interpolated normals can become unnormal--so normalize.
	normalW = normalize(normalW);
	toEyeW  = normalize(toEyeW);
	
	// Light vector is opposite the direction of the light.
	float3 lightVecW = -gLight.dirW;
	
	// Compute the reflection vector.
	float3 r = reflect(-lightVecW, normalW);
	
	// Determine how much (if any) specular light makes it into the eye.
	float t  = pow(max(dot(r, toEyeW), 0.0f), gMtrl.specPower);
	
	// Determine the diffuse light intensity that strikes the vertex.
	float s = max(dot(lightVecW, normalW), 0.0f);
	
	// Compute the ambient, diffuse and specular terms separatly. 
	float3 spec = t*(gMtrl.spec*gLight.spec).rgb;
	float3 diffuse = s*(gMtrl.diffuse*gLight.diffuse).rgb;
	float3 ambient = gMtrl.ambient*gLight.ambient;
	
	// Get the texture color.
 	float4 texColor = tex2D(TexS, tex0);
 
	
	// Combine the color from lighting with the texture color.
	//float3 color = (ambient + diffuse)*texColor.rgb + spec;
//	float3 color = (ambient + diffuse) + spec;
    	float3 color = (ambient + diffuse);
  //  	if (texColor != 0) {
	// 	color = gMtrl.diffuse*texColor.rgb;
    	// }
 		
	// Sum all the terms together and copy over the diffuse alpha.
  	//  float3 outcolor = color.rgb * 0.5f;
	//return float4(color, gMtrl.diffuse.a*texColor.a);
 	return float4(color, gMtrl.diffuse.a); 
}

technique PhongDirLtTexTech
{
	pass P0
	{
    	// Specify the vertex and pixel shader associated with this pass.
    	vertexShader = compile vs_2_0 PhongDirLtTexVS();
    	pixelShader  = compile ps_2_0 PhongDirLtTexPS();
	}
}


#8 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 01:21 AM

Here are the pics. I enable and disable z-buffering in these 2 trials
http://img220.imageshack.us/i/beforeh.png/
http://img217.imageshack.us/i/afteruo.png/
Thanks
Jack

#9 kauna   Crossbones+   -  Reputation: 2290

Like
1Likes
Like

Posted 05 June 2011 - 01:23 AM

Hi,

I took another quick look to your code and the lines below are "no no" when using vertex/pixel shaders, although they shouldn't matter
m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
m_pDevice
->LightEnable(DIRECTIONAL, true);


Also, you are setting sampler states in your code and you also define a sampler in the shader code.

I'd get rid most of the SetRenderStates and move what's necessary to your fx-file.

What you can test is to manually set the alpha value in your shader output and then try the alphablending.

I don't see you setting your gMtrl value anywhere in the code.

Good luck!

#10 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 01:46 AM

Hi,
Thanks for your help first. Really appreciate it :)
I actually set gMtrl inside the render method
for (int j = 0; j < m_pMesh->m_cAttributes; ++j)
	{
		int mtrlIndex = m_pMesh->attTable[j].AttribId;
		Mtrl m = m_pMesh->GetMaterial()[mtrlIndex];
		mFX->SetValue(mhMtrl, &m, sizeof(Mtrl));
.....

I am not sure how to set individual pixels to alpha (is that what you meant?) to the mesh
because the mesh is a large chunk by itself. Could you please give me more hints on that?
Thanks
Jack

#11 kauna   Crossbones+   -  Reputation: 2290

Like
1Likes
Like

Posted 05 June 2011 - 01:51 AM

float4 PhongDirLtTexPS(float3 normalW : TEXCOORD0, float3 toEyeW : TEXCOORD1, float2 tex0 : TEXCOORD2) : COLOR
{
....
return float4(color, gMtrl.diffuse.a); // 1.0f
}



Your pixel shader outputs individual fragments. In your shader code, the alpha is coming from "gMtrl.diffuse.a", which you seem to assume to be 1.0 (?).


Basically, if you put 1.0f instead of "gMtrl.diffuse.a" you are saying that all pixels are fully opaque. So no object should go missing when alphablending is enabled.

Cheers!

#12 lucky6969b   Members   -  Reputation: 572

Like
1Likes
Like

Posted 05 June 2011 - 01:55 AM

Hmmm..... At first blush, the 1.0 doesn't mean anything.. I just commented out the original code.... According to the debugger, the materials were actually correct, as you see in the pictures
Sorry for the misleading comment..... :)
Thanks very much
Jack

#13 kauna   Crossbones+   -  Reputation: 2290

Like
1Likes
Like

Posted 05 June 2011 - 01:58 AM

"- also, keep in mind that alpha transparency is draw order dependent procedure. "


Sorry I didn't notice your pictures.


- How about trying to draw the opaque meshes first
- and the draw the alpha blended meshes


Cheers!

#14 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 02:01 AM

Yes, I get your point. That's also the problem I have. As the mesh (the main object) is opaque in some parts, and some of them are transparent.
I am not sure how to display them apart.
Thanks... have fun
Jack

#15 kauna   Crossbones+   -  Reputation: 2290

Like
0Likes
Like

Posted 05 June 2011 - 02:54 AM

Hi,

Do you have one big mesh or lots of different meshes?

If you have one big mesh, try to draw first the opaque parts. Something like " if (mtrl.ambient.a == 1.0f)Render()"

After that, draw it again with a different rule " if (mtrl.ambient.a < 1.0f)Render()"

Without seeing your drawing code I can't give more precise hint.

Cheers!

#16 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 03:08 AM

The warehouse is one big mesh, some parts of it has alpha value less than 1.0, others objects include the trucks and the counter balances and the pallets in yellow

Here is how I load the mesh
void CMesh::LoadMesh(TCHAR *filename....)
{
	D3DXLoadMeshFromX(filename, D3DXMESH_SYSTEMMEM, pDevice,
		&adjBuffer, &mtrlBuffer, NULL, &numMtrls, &meshSys);

 
	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	meshSys->GetDeclaration(elems);
	
	bool hasNormals = false;
	D3DVERTEXELEMENT9 term = D3DDECL_END();
	for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
	{
		// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
		if(elems[i].Stream == 0xff )
			break;

		if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
			elems[i].Usage == D3DDECLUSAGE_NORMAL &&
			elems[i].UsageIndex == 0 )
		{
			hasNormals = true;
			break;
		}
	}


	// Step 3: Change vertex format to VertexPNT.

	D3DVERTEXELEMENT9 elements[64];
	UINT numElements = 0;
	VertexPNT::Decl->GetDeclaration(elements, &numElements);

	ID3DXMesh* temp = 0;
	meshSys->CloneMesh(D3DXMESH_SYSTEMMEM | D3DXMESH_32BIT, 
		elements, pDevice, &temp);
	ReleaseCOM(meshSys);
	meshSys = temp;


	// Step 4: If the mesh did not have normals, generate them.

	if( hasNormals == false)
		D3DXComputeNormals(meshSys, 0);


	// Step 5: Optimize the mesh.
	meshSys->Optimize(D3DXMESH_MANAGED | 
		D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, 
		(DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, &mMesh);
	ReleaseCOM(meshSys); // Done w/ system mesh.
	ReleaseCOM(adjBuffer); // Done with buffer.

	// Step 6: Extract the materials and load the textures.
	attTable = new D3DXATTRIBUTERANGE[numMtrls];
	mMesh->GetAttributeTable(attTable, &m_cAttributes);

	if( mtrlBuffer != 0 && numMtrls != 0 )
	{
		D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

		for(DWORD i = 0; i < numMtrls; ++i)
		{
			// Save the ith material.  Note that the MatD3D property does not have an ambient
			// value set when its loaded, so just set it to the diffuse value.
 
			Mtrl m;
 		
	     	m.ambient   = d3dxmtrls[i].MatD3D.Diffuse; //Diffuse;
			m.diffuse   = d3dxmtrls[i].MatD3D.Diffuse;
			m.spec 	= d3dxmtrls[i].MatD3D.Specular;
			m.specPower = d3dxmtrls[i].MatD3D.Power;
	  	

			mMtrl.push_back( m );

			// Check if the ith material has an associative texture
			if( d3dxmtrls[i].pTextureFilename != 0 )
			{
				// Yes, load the texture for the ith subset
				IDirect3DTexture9* tex = 0;
				char* texFN = d3dxmtrls[i].pTextureFilename;
				D3DXCreateTextureFromFile(pDevice, texFN, &tex);

				// Save the loaded texture
				mTex.push_back( tex );
			}
			else
			{
				// No texture for the ith subset
				mTex.push_back( 0 );
			}
		}

	}
	ReleaseCOM(mtrlBuffer); // done w/ buffer
}


Here is how I render the static objects
void CStaticObject::RenderStaticMesh()
{
  
	mFX->SetMatrix(mhWVP, &(m_matWorld*g_View*g_Proj));
	D3DXMATRIX worldInvTrans;
	D3DXMatrixInverse(&worldInvTrans, 0, &m_matWorld);
	D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
	mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans);
	mFX->SetMatrix(mhWorld, &m_matWorld);

	mFX->SetTechnique(mhTech);
	UINT numPasses = 0;
	mFX->Begin(&numPasses,0);
	mFX->BeginPass(0);

	for (int j = 0; j < m_pMesh->m_cAttributes; ++j)
	{
		int mtrlIndex = m_pMesh->attTable[j].AttribId;
		Mtrl m = m_pMesh->GetMaterial()[mtrlIndex];
		mFX->SetValue(mhMtrl, &m, sizeof(Mtrl));

		if (m_pMesh->GetTexture()[j] != 0)
		{
			mFX->SetTexture(mhTex, m_pMesh->GetTexture()[j]);
		}
		else
		{
 			;
		}
		mFX->CommitChanges();
		m_pMesh->GetMesh()->DrawSubset(j);
	}
	mFX->EndPass();
	mFX->End();
	 
	
}


Thanks :)
Jack

#17 Tom KQT   Members   -  Reputation: 1544

Like
1Likes
Like

Posted 05 June 2011 - 03:10 AM

Yes, I get your point. That's also the problem I have. As the mesh (the main object) is opaque in some parts, and some of them are transparent.
I am not sure how to display them apart.
Thanks... have fun
Jack


It will be different subsets then, each subset has a different material, so the transparent subsets and opaque subsets will be separated.
That means that you'll have to for example go from rendering mesh by mesh (while for each mesh you iterate all its subsets) to some sort of a render queue where each entry is a subset of some mesh. You will be also able to sort the queue by materials (by shaders, textures, whatever) which could improve your performance a bit as you can minimise your shader and texture changes. When rendering mesh by mesh you're basically just sorting by a world transform.

I think the StateManager DirectX SDK sample has quite nice "engine" that does that.

#18 lucky6969b   Members   -  Reputation: 572

Like
0Likes
Like

Posted 05 June 2011 - 03:11 AM

Thanks Tom, I'll take a look at the sample
Jack




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS