/// Efficiently render multiple imposter billboards in one DirectX draw call. void ImposterSystem::RenderImposterBillboards( RenderTexture* pImposterRenderTexture, const D3DXVECTOR3& curCameraPos, bool enableFog, D3DCOLOR fogColor, float fogDensity) { if (m_NumImposters == 0) { // No imposters to render. return; } int numActiveImposters = DepthSortImposters(curCameraPos); if (numActiveImposters == 0) { // There are no active imposters. return; } // Bind the imposter texture. LPDIRECT3DDEVICE9 pD3DDevice = DXUTGetD3DDevice(); pD3DDevice->SetTexture(0, pImposterRenderTexture->GetD3DTexture()); // Set world-tranform to identity (imposter billboard is already in world-space). D3DXMATRIX identity; D3DXMatrixIdentity(&identity); pD3DDevice->SetTransform(D3DTS_WORLD, &identity); // Setup render state. pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); pD3DDevice->SetRenderState(D3DRS_FOGENABLE, enableFog); pD3DDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_EXP2); pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, fogColor); pD3DDevice->SetRenderState(D3DRS_FOGDENSITY, FloatToDWORD(fogDensity)); pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0); pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // Initialise vertex buffer. int vertSize = sizeof(ImposterVertex); int numImposterVerts = m_NumImposters * NUM_IMPOSTER_VERTS; int sizeToLock = numImposterVerts * vertSize; unsigned char* pVertexBufferMem; m_pVertexBuffer->Lock(0, sizeToLock, (void **) &pVertexBufferMem, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD); int imposterVertsSize = vertSize * NUM_IMPOSTER_VERTS; for (int i = 0; i < numActiveImposters; ++i) { Imposter* pImposter = m_pSortBuffer[i]; if (!pImposter->active) { continue; } // Copy verts to vertex buffer. memcpy(pVertexBufferMem, pImposter->verts, imposterVertsSize); pVertexBufferMem += imposterVertsSize; } m_pVertexBuffer->Unlock(); int vertFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1; int numPrimitives = numActiveImposters * 2; pD3DDevice->SetFVF(vertFVF); pD3DDevice->SetStreamSource(0, m_pVertexBuffer, 0, vertSize); pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, numPrimitives); }