/// Efficiently generate multiple imposters packed into a single render texture. bool GenerateImposters(const D3DXVECTOR3& curCameraPos, const D3DXVECTOR3& curCameraUp, const D3DXMATRIX& viewMatrix, const D3DXMATRIX& projMatrix, RenderTexture* pImposterRenderTexture) { // Note that calling BeginScene (changing render target) is the // expensive part and is only done // once to generate multiple of imposters. if (!pImposterRenderTexture->BeginScene()) { return false; } // Setup render state. LPDIRECT3DDEVICE9 pD3DDevice = DXUTGetD3DDevice(); pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE); pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); pD3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); 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_ADDRESSU, D3DTADDRESS_WRAP pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); // Calculate the uv scale for render texture sub-regions. float imposterDistSq = IMPOSTER_DIST * IMPOSTER_DIST; D3DXVECTOR2 imposterUVScale(1.0f / (float) g_pImposterSystem->GetNumImpostersU(), 1.0f / (float) g_pImposterSystem->GetNumImpostersV()); // Get the bounding box for the mesh that is being impostered. D3DXVECTOR3 boundingBoxVerts[NUM_BOX_VERTS]; g_pMesh->GetBoundingBoxVerts(boundingBoxVerts); int numMeshs = g_RenderLoadsOfMeshes ? NUM_MESHES : 1; for (int i = 0; i < numMeshs; ++i) { Imposter* pImposter = g_pImposterSystem->GetImposter(i); if (!pImposter->requiresRegeneration) { // This imposter does not need to be regenerated at the moment. continue; } // Create the imposter geometry, view and projection matrices. float nearPlane, farPlane; g_pImposterSystem->CreateImposterBillboard(curCameraPos, viewMatrix, projMatrix, g_WorldMatrices[i], boundingBoxVerts, g_pMesh->GetBoundingSphere().radius, pImposter, nearPlane, farPlane); D3DXMATRIX imposterViewMatrix, imposterProjMatrix; g_pImposterSystem->CreateMatrices(curCameraPos, curCameraUp, imposterViewMatrix, imposterProjMatrix, pImposter, nearPlane, farPlane); // Set viewport for rendering to the sub-region of the render texture. g_pImposterSystem->InitImposterViewport( pImposterRenderTexture->GetWidth(), pImposterRenderTexture->GetHeight(), pImposter->uvOffset, imposterUVScale); // Initialise DirectX transforms. pD3DDevice->SetTransform(D3DTS_VIEW, &imposterViewMatrix); pD3DDevice->SetTransform(D3DTS_PROJECTION, &imposterProjMatrix); // Set the world transform for the Mesh. pD3DDevice->SetTransform(D3DTS_WORLD, &g_WorldMatrices[i]); // Clear the texture. D3DCOLOR color = D3DCOLOR_RGBA(0, 0, 0, 0); pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0); // Render the mesh to the imposter. g_pMesh->Render(); pImposter->requiresRegeneration = false; pImposter->lastGeneratedTime = (float) DXUTGetTime(); } pImposterRenderTexture->EndScene(); return true; }