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 );
			}
		}
	}
}
Beispiel #2
0
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 );
			}
		}
	}
}