Original Post
This is my shadow volume demo programmed by DX9. As you can see, it is not good, there is a lot of black noise on the occluder which really confuse me. Could anyone help me out? Below is my render() function(maybe it is a little long :) ):
void CShadowVolumeApplication::Render()
{
//setup some variables
D3DXVECTOR4 EyePos(0.0f, 60.0f, -60.0f, 0.0f);
D3DXMatrixLookAtLH(&m_ViewMatrix, &(D3DXVECTOR3)EyePos,
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
float Time = (float)GetTickCount() / 2000.0f;
D3DXVECTOR4 LightPos(150.0f * sin(Time), 90.0f, 0.0f, 1.0f);
D3DXVECTOR4 LightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - LightPos;
D3DXVec4Normalize(&LightDir, &LightDir);
D3DXVECTOR4 Ambient(0.0f, 0.0f, 0.0f, 0.0f);
m_pD3DDevice->SetVertexShaderConstantF(5, (float*)&Ambient, 1);
D3DXVECTOR4 PushDistance(100.0f, 0.0f, 0.0f, 0.0f);
m_pD3DDevice->SetVertexShaderConstantF(8, (float*)&PushDistance, 1);
m_pD3DDevice->SetVertexDeclaration(m_pDeclaration);
m_pD3DDevice->SetVertexShader(m_pBasicShader);
//if I comment out this line, the noise will disappear,
//but as you can expect, stippling effect will occur,
//but I also think the noise also have something to do with this
m_pD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, 10);
//draw the white plane
RenderPlane();
//draw the occluder
D3DXMATRIX Rotation;
D3DXMATRIX Translation;
D3DXMatrixTranslation(&m_WorldMatrix, 20.0f, 10.0f, 0.0f);
D3DXMATRIX ShaderMatrix = m_WorldMatrix * m_ViewMatrix * m_ProjectionMatrix;
D3DXMatrixTranspose(&ShaderMatrix, &ShaderMatrix);
m_pD3DDevice->SetVertexShaderConstantF(0, (float*)&ShaderMatrix, 4);
D3DXMATRIX InverseWorld;
float Det;
D3DXMatrixInverse(&InverseWorld, &Det, &m_WorldMatrix);
D3DXVec4Transform(&LightDir, &LightDir, &InverseWorld);
D3DXVec4Normalize(&LightDir, &LightDir);
m_pD3DDevice->SetVertexShaderConstantF(4, (float*)&LightDir, 1);
D3DXVec4Transform(&LightPos, &LightPos, &InverseWorld);
m_pD3DDevice->SetVertexShaderConstantF(7, (float*)&LightPos, 1);
D3DXMatrixRotationY(&Rotation, (float)GetTickCount() / 1000.0f);
D3DXMatrixTranslation(&Translation, 0.0f, 20.0f, 0.0f);
m_WorldMatrix = Rotation * Translation;
ShaderMatrix = m_WorldMatrix * m_ViewMatrix * m_ProjectionMatrix;
D3DXMatrixTranspose(&ShaderMatrix, &ShaderMatrix);
m_pD3DDevice->SetVertexShaderConstantF(0, (float*)&ShaderMatrix, 4);
D3DXMatrixInverse(&InverseWorld, &Det, &m_WorldMatrix);
D3DXVec4Transform(&LightDir, &LightDir, &InverseWorld);
D3DXVec4Normalize(&LightDir, &LightDir);
m_pD3DDevice->SetVertexShaderConstantF(4, (float*)&LightDir, 1);
D3DXVec4Transform(&LightPos, &LightPos, &InverseWorld);
m_pD3DDevice->SetVertexShaderConstantF(7, (float*)&LightPos, 1);
m_pD3DDevice->SetStreamSource(0, m_pMeshVertexBuffer, 0, sizeof(MESH_VERTEX));
m_pD3DDevice->SetIndices(m_pMeshIndexBuffer);
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_pMesh->GetNumVertices(), 0,
m_pMesh->GetNumFaces());//end draw of occluder
//draw shadow volume in stencil buffer
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_STENCIL, 0, 1.0f, 0);
m_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
m_pD3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
m_pD3DDevice->SetRenderState(D3DRS_STENCILREF, 1);
m_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
m_pD3DDevice->SetVertexShader(m_pVolumeShader);
m_pD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
//two pass:
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_pMesh->GetNumVertices(), 0,
m_pMesh->GetNumFaces());
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
m_pD3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR);
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_pMesh->GetNumVertices(), 0,
m_pMesh->GetNumFaces());//end draw of shadow volume
//draw the screen rectangle that make the shadow
m_pD3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL);
m_pD3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
m_pD3DDevice->SetRenderState(D3DRS_STENCILREF, 1);
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDevice->SetVertexShader(NULL);
m_pD3DDevice->SetFVF(D3DFVF_MASKVERTEX);
m_pD3DDevice->SetStreamSource(0, m_pMaskVertexBuffer, 0, sizeof(MASK_VERTEX));
m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);//end draw of the screen rect
//switch everythig back
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(100, 100, 200), 1.0f, 0);