// ----------------------------------------------------------------------------- // // 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 }
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 }