Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Shadow implementation...problems

Started by axelfr74 Jul 4, 2004 at 3:47 AM 0 replies 400+ views
Original Post
axelfr74
axelfr74
Hi, I'm trying to implement the SDK shadow volume demo in my own application and...nothing works. :) I'm new to stencil shadows and understand not much at the moment. But I'm trying! Here is what I'm doing and what work's and what not: 1. I render the background of my scene - some cubes - OK 2. I render my player mesh - OK 3. I build with the BuildFromMesh function the shadow volume from my player mesh - ERROR - after some seconds the application crashes. Ok, so I'm doing it once when the application starts and now it is OK 4. I call RenderShadow() - OK 5. I call DrawShadow() - OK .. but after DrawShadow I can still se my player mesh but the whole other scene is black! Simply black. Only the player mesh is drawn like it should. Strange. Here ar the slightly changed SDK sample functions and how I'm using them in my app: BuildFromMesh():

HRESULT BuildFromMesh( LPD3DXMESH pMesh, D3DXVECTOR3 vLight )
{
    // Note: the MESHVERTEX format depends on the FVF of the mesh
    struct MESHVERTEX { D3DXVECTOR3 p, n; FLOAT tu, tv; };

    MESHVERTEX* pVertices;
    WORD*       pIndices;

    // Lock the geometry buffers
    pMesh->LockVertexBuffer( 0L, (LPVOID*)&pVertices );
    pMesh->LockIndexBuffer( 0L, (LPVOID*)&pIndices );
    DWORD dwNumFaces    = pMesh->GetNumFaces();

    // Allocate a temporary edge list
    WORD* pEdges = new WORD[dwNumFaces*[[[6]]]];
    if( pEdges == NULL )
    {
        pMesh->UnlockVertexBuffer();
        pMesh->UnlockIndexBuffer();
        return E_OUTOFMEMORY;
    }
    DWORD dwNumEdges = [[[0]]];

    // For each face
    for( DWORD i=[[[0]]]; i<dwNumFaces; i++ )
    {
        WORD wFace0 = pIndices[[[[3]]]*i+[[[0]]]];
        WORD wFace1 = pIndices[[[[3]]]*i+[[[1]]]];
        WORD wFace2 = pIndices[[[[3]]]*i+[[[2]]]];

        D3DXVECTOR3 v0 = pVertices[wFace0].p;
        D3DXVECTOR3 v1 = pVertices[wFace1].p;
        D3DXVECTOR3 v2 = pVertices[wFace2].p;

        // Transform vertices or transform light?
        D3DXVECTOR3 vCross1(v2-v1);
        D3DXVECTOR3 vCross2(v1-v0);
        D3DXVECTOR3 vNormal;
        D3DXVec3Cross( &vNormal, &vCross1, &vCross2 );

        if( D3DXVec3Dot( &vNormal, &vLight ) >= [[[0]]].0f )
        {
            AddEdge( pEdges, dwNumEdges, wFace0, wFace1 );
            AddEdge( pEdges, dwNumEdges, wFace1, wFace2 );
            AddEdge( pEdges, dwNumEdges, wFace2, wFace0 );
        }
    }

    for( i=[[[0]]]; i<dwNumEdges; i++ )
    {
        D3DXVECTOR3 v1 = pVertices[pEdges[[[[2]]]*i+[[[0]]]]].p;
        D3DXVECTOR3 v2 = pVertices[pEdges[[[[2]]]*i+[[[1]]]]].p;
        D3DXVECTOR3 v3 = v1 - vLight*[[[10]]];
        D3DXVECTOR3 v4 = v2 - vLight*[[[10]]];

        // Add a quad (two triangles) to the vertex list
        m_pVertices[m_dwNumVertices++] = v1;
        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v3;

        m_pVertices[m_dwNumVertices++] = v2;
        m_pVertices[m_dwNumVertices++] = v4;
        m_pVertices[m_dwNumVertices++] = v3;
    }
    // Delete the temporary edge list
    delete[] pEdges;

    // Unlock the geometry buffers
    pMesh->UnlockVertexBuffer();
    pMesh->UnlockIndexBuffer();

    return S_OK;
}
RenderShadow():

HRESULT RenderShadow()
{
    // Disable z-buffer writes (note: z-testing still occurs), and enable the
    // stencil-buffer
    lpd3d_device->SetRenderState( D3DRS_ZWRITEENABLE,  FALSE );
    lpd3d_device->SetRenderState( D3DRS_STENCILENABLE, TRUE );

    // Dont bother with interpolating color
    lpd3d_device->SetRenderState( D3DRS_SHADEMODE,     D3DSHADE_FLAT );

    // Set up stencil compare fuction, reference value, and masks.
    // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
    // Note: since we set up the stencil-test to always pass, the STENCILFAIL
    // renderstate is really not needed.
    lpd3d_device->SetRenderState( D3DRS_STENCILFUNC,  D3DCMP_ALWAYS );
    lpd3d_device->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
    lpd3d_device->SetRenderState( D3DRS_STENCILFAIL,  D3DSTENCILOP_KEEP );

    // If ztest passes, inc/decrement stencil buffer value
    lpd3d_device->SetRenderState( D3DRS_STENCILREF,       0x1 );
    lpd3d_device->SetRenderState( D3DRS_STENCILMASK,      0xffffffff );
    lpd3d_device->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
    lpd3d_device->SetRenderState( D3DRS_STENCILPASS,      D3DSTENCILOP_INCR );

    // Make sure that no pixels get drawn to the frame buffer
    lpd3d_device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
    lpd3d_device->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ZERO );
    lpd3d_device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );

       // With [[[2]]]-sided stencil, we can avoid rendering twice:
        lpd3d_device->SetRenderState( D3DRS_TWOSIDEDSTENCILMODE, TRUE );
        lpd3d_device->SetRenderState( D3DRS_CCW_STENCILFUNC,  D3DCMP_ALWAYS );
        lpd3d_device->SetRenderState( D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP );
        lpd3d_device->SetRenderState( D3DRS_CCW_STENCILFAIL,  D3DSTENCILOP_KEEP );
        lpd3d_device->SetRenderState( D3DRS_CCW_STENCILPASS, D3DSTENCILOP_DECR );

        lpd3d_device->SetRenderState( D3DRS_CULLMODE,  D3DCULL_NONE );

        // Draw both sides of shadow volume in stencil/z only
        lpd3d_device->SetTransform( D3DTS_WORLD, &m_matObjectMatrix );
        RenderShad( lpd3d_device );

        lpd3d_device->SetRenderState( D3DRS_TWOSIDEDSTENCILMODE, FALSE );

    // Restore render states
    lpd3d_device->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
    lpd3d_device->SetRenderState( D3DRS_CULLMODE,  D3DCULL_CCW );
    lpd3d_device->SetRenderState( D3DRS_ZWRITEENABLE,     TRUE );
    lpd3d_device->SetRenderState( D3DRS_STENCILENABLE,    FALSE );
    lpd3d_device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

    return S_OK;
}
DrawShadow():

HRESULT DrawShadow()
{
    // Set renderstates (disable z-buffering, enable stencil, disable fog, and
    // turn on alphablending)
    lpd3d_device->SetRenderState( D3DRS_ZENABLE,          FALSE );
    lpd3d_device->SetRenderState( D3DRS_STENCILENABLE,    TRUE );
    lpd3d_device->SetRenderState( D3DRS_FOGENABLE,        FALSE );
    lpd3d_device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
    lpd3d_device->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
    lpd3d_device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_COLORARG1, D3DTA_TEXTURE );
    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_COLOROP,   D3DTOP_MODULATE );
    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
    lpd3d_device->SetTextureStageState( [[[0]]], D3DTSS_ALPHAOP,   D3DTOP_MODULATE );

    // Only write where stencil val >= [[[1]]] (count indicates # of shadows that
    // overlap that pixel)
    lpd3d_device->SetRenderState( D3DRS_STENCILREF,  0x1 );
    lpd3d_device->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
    lpd3d_device->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );



    // Draw a big, gray square
    lpd3d_device->SetFVF( SHADOWVERTEX::FVF );
    lpd3d_device->SetStreamSource( [[[0]]], m_pBigSquareVB, [[[0]]], sizeof(SHADOWVERTEX) );
    lpd3d_device->DrawPrimitive( D3DPT_TRIANGLESTRIP, [[[0]]], [[[2]]] );

    // Restore render states
    lpd3d_device->SetRenderState( D3DRS_ZENABLE,          TRUE );
    lpd3d_device->SetRenderState( D3DRS_STENCILENABLE,    FALSE );
    lpd3d_device->SetRenderState( D3DRS_FOGENABLE,        TRUE );
    lpd3d_device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

    return S_OK;
}

RenderShad()..this draws the shadow volume:


HRESULT RenderShad( LPDIRECT3DDEVICE9 pd3dDevice )
{
    pd3dDevice->SetFVF( D3DFVF_XYZ );

    return pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, m_dwNumVertices/[[[3]]],
                                        m_pVertices, sizeof(D3DXVECTOR3) );
}
After that I'm drawing the shadow volume with: pd3dDevice->SetFVF( D3DFVF_XYZ ); pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST,m_dwNumVertices/3, m_pVertices, sizeof(D3DXVECTOR3) ); Maybe someone can see the "make-it-all-black"-error? Thanks! Axel

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.