Using D3DXMatrixShadow

Started by
4 comments, last by Armadon 18 years, 6 months ago
Hello, I am having trouble implementing a shadow correctly. Here's my code:
void SceneObject::RenderShadow( D3DXPLANE* plane, D3DXVECTOR4* lightDirection, D3DXMATRIX *world )
{
	// Ignore the object if it has no mesh.
	if( m_mesh == NULL )
		return;
/*
	g_device->SetRenderState(D3DRS_STENCILENABLE,    true);
    g_device->SetRenderState(D3DRS_STENCILFUNC,      D3DCMP_EQUAL);
    g_device->SetRenderState(D3DRS_STENCILREF,       0x0);
    g_device->SetRenderState(D3DRS_STENCILMASK,      0xffffffff);
    g_device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
    g_device->SetRenderState(D3DRS_STENCILZFAIL,     D3DSTENCILOP_KEEP);
    g_device->SetRenderState(D3DRS_STENCILFAIL,      D3DSTENCILOP_KEEP);
    g_device->SetRenderState(D3DRS_STENCILPASS,      D3DSTENCILOP_INCR); // increment to 1
*/
	D3DXMATRIX S;
	D3DXMatrixShadow( &S, lightDirection, plane);
/*
	// Check if the object's world tranformation matrix has been overridden.
	if( world == NULL )
		g_device->SetTransform( D3DTS_WORLD, &m_worldMatrix );
	else
		g_device->SetTransform( D3DTS_WORLD, world );
*/
	D3DXMATRIX* T = GetTranslationMatrix();
	D3DXMATRIX W = *T * S;

	g_device->SetTransform( D3DTS_WORLD, &W );

	//g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
	g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

	D3DMATERIAL9 mtrl;
	mtrl.Ambient  = BLACK;
	mtrl.Diffuse  = BLACK;
	mtrl.Specular = BLACK;
	mtrl.Emissive = BLACK;
	mtrl.Power    = BLACK;
	mtrl.Diffuse.a = 1.0f;

	g_device->SetMaterial( &mtrl );
	g_device->SetTexture( 0, NULL );

//	g_device->SetRenderState(D3DRS_ZENABLE, false);
	
	m_mesh->Render( false );

//	g_device->SetRenderState(D3DRS_ZENABLE, true);
	g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	g_device->SetRenderState(D3DRS_STENCILENABLE,    false);

	
If I comment out the stencilling, as above, I see the shadow by my object, pancaked correctly, but it flickers like a bugger! If I turn on the stencilling I can only make out the outline of the shadow.... The code above is taken from chapter 8, of luna's book, introduction to DX9. Seems to work well for him! This line: m_mesh->Render( false ); Simply renders the mesh without changing any materials. Is this a problem with my stencilling? I'm not sure how Frank Lunas code works, because when I've used stencilling before, I've rendered to the stencil buffer, to create a mask , then render the masked object. Yet luna renders only once. Please Help! Simon
Advertisement
There's not enough information to diagnose this but it sounds kind of like a Z fight. Try enabling Z-bias on it or project it upwards along the plane's normal a smidgeon. Unless of course you're not even rendering anything on the plane in which case it'd have nothing to z-fight with.
I'm afraid I have nothing to zfight. Even when I strip the scene down to the lone object and its shadow, it still flickers.
Is culling enabled? If not that could cause the triangles of one side to zfight with triangles on the other. Just a thought. Does it happen when you render the shadow without the object? I see you've messed with disabling the zbuffer. Have you also tried it with ZWRITEENABLE disabled too?
Unfortunately, turning off ztesting and writing still has no effect!

I am using D3DFMT24_S8, (off the top of my head) - Is that okay?

Simon
Hi there sipickles,
How are you doing?

The Problem
Depth/Stencil Format and ZFighting.

The Solution
I think you are having an issue with your z buffer.For the purpose of your exercise I would set an AutoDepthStencilFormat of D3DFMT_D24S8, this will give you 24 bits for the depth buffer (zbuffer) and 8 bits for the stencil buffer.
i.e.
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
and then create your device as per normal.

Should suffice for your purposes. When you are rendering objects like a shadow very close to another plane you might see the flickering as the 2 objects are fighting for z dominance. What you can do to reduce this or remove this is to turn of the z testing.
i.e.
d3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);

This might reduce your problem.

PS: remember to switch it back on after you have rendered your shadow.

I hope this helps.
Take care buddy.

This topic is closed to new replies.

Advertisement