void SharedMeshContainer::ValidateShaderTechniqueTable() { BasicMesh *pMeshObject = m_MeshObjectHandle.GetMesh().get(); if( !pMeshObject ) return; if( m_ShaderTechnique.size_y() == 0 ) { m_ShaderTechnique.resize(1,1); m_ShaderTechnique(0,0).SetTechniqueName( "NoShader" ); } else if( m_ShaderTechnique.size_y() == 1 && 2 <= pMeshObject->GetNumMaterials() ) { // only one technique and 2 or more materials // - assumes the user wants to render all the materials with the same shader technique m_PropertyFlags |= PF_USE_SINGLE_TECHNIQUE_FOR_ALL_MATERIALS; } else if( m_ShaderTechnique.size_y() < pMeshObject->GetNumMaterials() ) { int num_orig_rows = m_ShaderTechnique.size_y(); // (the number of techniques) < (the number of materials) // - copy the last technique and make sure there are as many techniques as materials // increase the columns to cover all the materials m_ShaderTechnique.increase_y( pMeshObject->GetNumMaterials() - m_ShaderTechnique.size_y() ); // overwrite increased rows with the last technique for each LOD int lod, num_lods = m_ShaderTechnique.size_x(); // columns: for LODs int row, num_rows = m_ShaderTechnique.size_y(); // rows: for materials for( lod=0; lod<num_lods; lod++ ) { for( row=num_orig_rows; row<num_rows; row++ ) { m_ShaderTechnique( lod, row ) = m_ShaderTechnique( lod, num_orig_rows - 1 ); } } } }
void CBE_Skybox::Draw(CCopyEntity* pCopyEnt) { BasicMesh* pMeshObject = m_MeshProperty.m_MeshObjectHandle.GetMesh().get(); if( !pMeshObject ) { ONCE( LOG_PRINT_WARNING( " An invlid mesh object: base entity '%s'", m_strName.c_str() ) ); return; } // set the world transform Matrix44 world( Matrix44Scaling( 10.0f, 10.0f, 10.0f ) ); Vector3 vPos; Camera* pCamera = m_pStage->GetCurrentCamera(); if( pCamera ) vPos = pCamera->GetPosition(); else vPos = Vector3(0,0,0); world(0,3) = vPos.x; world(1,3) = vPos.y; world(2,3) = vPos.z; world(3,3) = 1; FixedFunctionPipelineManager().SetWorldTransform( world ); pMeshObject->SetVertexDeclaration(); int num_materials = pMeshObject->GetNumMaterials(); bool shift_camera_height = true; // ShaderParameter<float> cam_height_param( "g_CameraHeight" ); // Disable depth-test and writing to depth buffer. // These 2 settings and restored after rendering skybox because they are changed only when necessary. // This is not required if you are using HLSL effect of Direct3D, and the technique to render // the skybox defines the same render states. // If you are using OpenGL, you have to do this whether you are using GLSL or not? GraphicsDevice().Disable( RenderStateType::DEPTH_TEST ); GraphicsDevice().Disable( RenderStateType::WRITING_INTO_DEPTH_BUFFER ); GraphicsDevice().Disable( RenderStateType::LIGHTING ); // save the original texture and temporarily overwrite it with the sky texture TextureHandle orig_tex; if( 0 < num_materials ) { if( pMeshObject->Material(0).Texture.empty() ) pMeshObject->Material(0).Texture.resize( 1 ); orig_tex = pMeshObject->Material(0).Texture[0]; pMeshObject->Material(0).Texture[0] = m_SkyboxTexture; } ShaderManager *pShaderManager = m_MeshProperty.m_ShaderHandle.GetShaderManager(); if( pShaderManager ) // && pShaderManager->IsValid() ) // check if pEffect is present? { if( shift_camera_height ) { Camera *pCam = m_pStage->GetCurrentCamera(); float fCamHeight; if( pCam ) fCamHeight = pCam->GetPosition().y; else fCamHeight = 5.0f; pShaderManager->GetEffect()->SetFloat( "g_CameraHeight", fCamHeight ); // pShaderManager->SetParam( "g_CameraHeight", fCamHeight ); // pEffect->SetFloat( "g_TexVShiftFactor", 0.000005f ); // pShaderManager->SetParam( "g_TexVShiftFactor", 0.000005f ); // cam_height_param.Parameter() = fCamHeight; // pShaderManager->SetParam( cam_height_param ); } // render the skybox mesh with an HLSL shader pShaderManager->SetWorldTransform( world ); Result::Name res = pShaderManager->SetTechnique( m_MeshProperty.m_ShaderTechnique(0,0) ); // Meshes are divided into subsets by materials. Render each subset in a loop pMeshObject->Render( *pShaderManager ); } else { // RenderAsSkybox( m_MeshProperty.m_MeshObjectHandle, vPos ); pMeshObject->Render(); } if( 0 < num_materials && 0 < pMeshObject->Material(0).Texture.size() ) { // restore the original texture pMeshObject->Material(0).Texture[0] = orig_tex; } GraphicsDevice().Enable( RenderStateType::DEPTH_TEST ); GraphicsDevice().Enable( RenderStateType::WRITING_INTO_DEPTH_BUFFER ); }
// - Set the world transform 'world_transform' to shader // - Update shader params // - Set technique void MeshContainerRenderMethod::RenderMesh( BasicMesh &mesh, const Matrix34& world_transform ) { if( !m_RenderMethodsAndSubsetIndices.empty() ) { if( m_RenderMethodsAndSubsetIndices.size() == 1 && m_RenderMethodsAndSubsetIndices[0].second.empty() ) { // render all the subsets at once RenderMeshOrMeshSubsets( mesh, m_RenderMethodsAndSubsetIndices[0].second, m_RenderMethodsAndSubsetIndices[0].first, world_transform ); } else { for( int i=0; i<(int)m_RenderMethodsAndSubsetIndices.size(); i++ ) { SubsetRenderMethod& render_method = m_RenderMethodsAndSubsetIndices[i].first; const vector<int>& subset_indices = m_RenderMethodsAndSubsetIndices[i].second; for( int j=0; j<(int)subset_indices.size(); j++ ) { RenderMeshOrMeshSubsets( mesh, subset_indices, render_method, world_transform ); } } } } else if( 0 < m_vecSubsetNameToRenderMethod.size() ) { // render subsets one by one // set different shaders / techniques for each subset const int num_subsets = mesh.GetNumMaterials(); std::vector<int> *pvecIndicesOfSubsetsToRender = NULL; if( m_vecIndicesOfSubsetsToRender.size() == 0 ) { // render all the subsets // - create the full indices list // - For the same mesh, this is done only once. for( int j=(int)m_vecFullIndicesOfSubsets.size(); j<num_subsets; j++ ) m_vecFullIndicesOfSubsets.push_back( j ); pvecIndicesOfSubsetsToRender = &m_vecFullIndicesOfSubsets; } else { pvecIndicesOfSubsetsToRender = &m_vecIndicesOfSubsetsToRender; } int lod_index = 0; // for( i=0; i<num_subsets; i++ ) for( size_t i=0; i<pvecIndicesOfSubsetsToRender->size(); i++ ) { int index = (*pvecIndicesOfSubsetsToRender)[i]; map< string, SubsetRenderMethod >::iterator itr = m_vecSubsetNameToRenderMethod[lod_index].find( mesh.GetMaterial(index).Name ); if( itr == m_vecSubsetNameToRenderMethod[lod_index].end() ) continue; SubsetRenderMethod& subset_render_method = (*itr).second; ShaderManager *pShaderMgr = subset_render_method.m_Shader.GetShaderManager(); if( !pShaderMgr ) continue; pShaderMgr->SetWorldTransform( world_transform ); pShaderMgr->SetTechnique( subset_render_method.m_Technique ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->UpdateShaderParams( *pShaderMgr ); } mesh.RenderSubset( *pShaderMgr, index ); for( size_t j=0; j<subset_render_method.m_vecpShaderParamsLoader.size(); j++ ) { subset_render_method.m_vecpShaderParamsLoader[j]->ResetShaderParams( *pShaderMgr ); } } } }