Пример #1
0
// ----------------------------------------------------------------------------- //
// Adds shadow rendering data to a particular mesh builder
// ----------------------------------------------------------------------------- //
int DispInfo_AddShadowsToMeshBuilder( CMeshBuilder& meshBuilder,
                                      DispShadowHandle_t h, int baseIndex )
{
#ifndef SWDS
    if ( !r_DrawDisp.GetBool() )
    {
        return baseIndex;
    }

    CDispShadowDecal* pShadowDecal = &s_DispShadowDecals[h];
    int shadow = pShadowDecal->m_Shadow;
    ShadowInfo_t const& info = g_pShadowMgr->GetInfo( shadow );

    // It had better be computed by now...
    Assert( pShadowDecal->m_Flags & CDispDecalBase::FRAGMENTS_COMPUTED );

#ifdef _DEBUG
    int triCount = 0;
    int vertCount = 0;
#endif

    DispShadowFragmentHandle_t f = pShadowDecal->m_FirstFragment;
    while ( f != DISP_SHADOW_FRAGMENT_HANDLE_INVALID )
    {
        CDispShadowFragment& fragment = s_DispShadowFragments[f];

        // Add in the vertices + indices, use two loops to minimize tests...
        int i;
        for ( i = 0; i < fragment.m_nVerts - 2; ++i )
        {
            meshBuilder.Position3fv( fragment.m_Verts[i].Base() );

            // Transform + offset the texture coords
            Vector2D texCoord;
            Vector2DMultiply( fragment.m_TCoords[i].AsVector2D(), info.m_TexSize, texCoord );
            texCoord += info.m_TexOrigin;
            meshBuilder.TexCoord2fv( 0, texCoord.Base() );

            unsigned char c = g_pShadowMgr->ComputeDarkness( fragment.m_TCoords[i].z, info );
            meshBuilder.Color4ub( c, c, c, c );

            meshBuilder.AdvanceVertex();

            meshBuilder.Index( baseIndex );
            meshBuilder.AdvanceIndex();
            meshBuilder.Index( i + baseIndex + 1 );
            meshBuilder.AdvanceIndex();
            meshBuilder.Index( i + baseIndex + 2 );
            meshBuilder.AdvanceIndex();

#ifdef _DEBUG
            ++triCount;
            ++vertCount;
#endif
        }

        for ( ; i < fragment.m_nVerts; ++i )
        {
            meshBuilder.Position3fv( fragment.m_Verts[i].Base() );

            // Transform + offset the texture coords
            Vector2D texCoord;
            Vector2DMultiply( fragment.m_TCoords[i].AsVector2D(), info.m_TexSize, texCoord );
            texCoord += info.m_TexOrigin;
            meshBuilder.TexCoord2fv( 0, texCoord.Base() );

            unsigned char c = g_pShadowMgr->ComputeDarkness( fragment.m_TCoords[i].z, info );
            meshBuilder.Color4ub( c, c, c, c );

            meshBuilder.AdvanceVertex();

#ifdef _DEBUG
            ++vertCount;
#endif
        }

        baseIndex += fragment.m_nVerts;

        f = s_DispShadowFragments.Next(f);
    }

#ifdef _DEBUG
    Assert( triCount == pShadowDecal->m_nTris );
    Assert( vertCount == pShadowDecal->m_nVerts );
#endif

    return baseIndex;
#else
    return 0;
#endif
}
Пример #2
0
void DispInfo_DrawDecals( CDispInfo *visibleDisps[MAX_MAP_DISPINFO], int nVisibleDisps )
{
#ifndef SWDS
    VPROF("DispInfo_DrawDecals");
    if( !nVisibleDisps )
        return;

    int nTrisDrawn = 0;

    // FIXME: We should bucket all decals (displacement + otherwise)
    // and sort them by material enum id + lightmap
    // To do this, we need to associate a sort index from 0-n for all
    // decals we've seen this level. Then we add those decals to the
    // appropriate search list, (sorted by lightmap id)?

    for( int i=0; i < nVisibleDisps; i++ )
    {
        CDispInfo *pDisp = visibleDisps[i];

        // Don't bother if there's no decals
        if( pDisp->m_FirstDecal == DISP_DECAL_HANDLE_INVALID )
            continue;

        materialSystemInterface->BindLightmapPage( pDisp->m_pMesh->m_pGroup->m_LightmapPageID );

        // At the moment, all decals in a single displacement are sorted by material
        // so we get a little batching at least
        DispDecalHandle_t d = pDisp->m_FirstDecal;
        while( d != DISP_DECAL_HANDLE_INVALID )
        {
            CDispDecal& decal = s_DispDecals[d];

            // Compute decal fragments if we haven't already....
            if ((decal.m_Flags & CDispDecalBase::FRAGMENTS_COMPUTED) == 0)
            {
                pDisp->GenerateDecalFragments( pDisp->m_pPowerInfo->m_RootNode, 0, d, &decal );
            }

            // Don't draw if there's no triangles
            if (decal.m_nTris == 0)
            {
                d = s_DispDecals.Next(d);
                continue;
            }

            // Now draw all the fragments with this material.
            IMaterial* pMaterial = decal.m_pDecal->material;

            IMesh *pMesh = materialSystemInterface->GetDynamicMesh( true, NULL, NULL, pMaterial );

            CMeshBuilder meshBuilder;
            meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, decal.m_nVerts, decal.m_nTris * 3 );

            int baseIndex = 0;
            DispDecalFragmentHandle_t f = decal.m_FirstFragment;
            while (f != DISP_DECAL_FRAGMENT_HANDLE_INVALID)
            {
                CDispDecalFragment& fragment = s_DispDecalFragments[f];
                int v;
                for ( v = 0; v < fragment.m_nVerts - 2; ++v)
                {
                    meshBuilder.Position3fv( fragment.m_pVerts[v].m_vPos.Base() );
                    meshBuilder.TexCoord2fv( 0, fragment.m_pVerts[v].m_tCoords.Base() );
                    meshBuilder.TexCoord2fv( 1, fragment.m_pVerts[v].m_LMCoords.Base() );
                    meshBuilder.AdvanceVertex();

                    meshBuilder.Index( baseIndex );
                    meshBuilder.AdvanceIndex();
                    meshBuilder.Index( v + baseIndex + 1 );
                    meshBuilder.AdvanceIndex();
                    meshBuilder.Index( v + baseIndex + 2 );
                    meshBuilder.AdvanceIndex();
                }

                meshBuilder.Position3fv( fragment.m_pVerts[v].m_vPos.Base() );
                meshBuilder.TexCoord2fv( 0, fragment.m_pVerts[v].m_tCoords.Base() );
                meshBuilder.TexCoord2fv( 1, fragment.m_pVerts[v].m_LMCoords.Base() );
                meshBuilder.AdvanceVertex();

                ++v;
                meshBuilder.Position3fv( fragment.m_pVerts[v].m_vPos.Base() );
                meshBuilder.TexCoord2fv( 0, fragment.m_pVerts[v].m_tCoords.Base() );
                meshBuilder.TexCoord2fv( 1, fragment.m_pVerts[v].m_LMCoords.Base() );
                meshBuilder.AdvanceVertex();

                baseIndex += fragment.m_nVerts;

                f = s_DispDecalFragments.Next(f);
            }
            meshBuilder.End( false, true );

            nTrisDrawn += decal.m_nTris * pMaterial->GetNumPasses();

            d = s_DispDecals.Next(d);
        }
    }
    g_EngineStats.IncrementCountedStat( ENGINE_STATS_DECAL_TRIANGLES, nTrisDrawn );
#endif
}