Esempio n. 1
0
/*!****************************************************************************
 @Function		LoadPFX
 @Return		bool			true if no error occurred
 @Description	Loads and compiles the shaders and links the shader programs
				required for this training course
******************************************************************************/
bool OGLES3ShadowMapping::LoadPFX(CPVRTString* pErrorStr)
{
	// Parse the whole PFX and store all data.
	m_pPFXEffectParser = new CPVRTPFXParser();
	if(m_pPFXEffectParser->ParseFromFile(c_szPFXFile, pErrorStr) != PVR_SUCCESS)
	{
		*pErrorStr = "Parse failed:\n" + *pErrorStr;
		return false;
	}

	// Setup all effects in the PFX file so we initialize the shaders and
	// store uniforms and attributes locations.
	unsigned int uiNumEffects = m_pPFXEffectParser->GetNumberEffects();
	m_ppPFXEffects = new CPVRTPFXEffect*[uiNumEffects];
	for (unsigned int i=0; i < uiNumEffects; i++)
		m_ppPFXEffects[i] = 0;

	// Load one by one the effects. This will also compile the shaders.
	for (unsigned int i=0; i < uiNumEffects; i++)
	{
		m_ppPFXEffects[i] = new CPVRTPFXEffect(m_sContext);
				
		if(m_ppPFXEffects[i]->RegisterUniformSemantic(c_CustomSemantics, c_uiNumCustomSemantics, pErrorStr))
		{
			*pErrorStr = "Failed to set custom semantics:\n" + *pErrorStr;
			return false;
		}

		unsigned int nUnknownUniformCount = 0;
		if(m_ppPFXEffects[i]->Load(*m_pPFXEffectParser, m_pPFXEffectParser->GetEffect(i).Name.c_str(), NULL, NULL, nUnknownUniformCount, pErrorStr)  != PVR_SUCCESS)
		{
			*pErrorStr = "Failed to load effect " + m_pPFXEffectParser->GetEffect(i).Name.String() + CPVRTString(":\n") + *pErrorStr;
			return false;
		}

		// .. upps, some uniforms are not in our table. Better to quit because something is not quite right.
		if(nUnknownUniformCount)
		{
			*pErrorStr = "Unknown uniform semantic.\n";
			return false;
		}		
	}
	
	return true;
}
Esempio n. 2
0
/*!****************************************************************************
 @Function		InitView
 @Return		bool		true if no error occured
 @Description	Code in InitView() will be called by PVRShell upon
				initialization or after a change in the rendering context.
				Used to initialize variables that are dependant on the rendering
				context (e.g. textures, vertex buffers, etc.)
******************************************************************************/
bool OGLES3ShadowMapping::InitView()
{
	CPVRTString ErrorStr;	    
    
	m_bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);

	// Initialize VBO data
	if(!LoadVbos(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Load textures
	if (!LoadTextures(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Load and compile the shaders & link programs
	if (!LoadPFX(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	// Map the individual effects to make it easier to address them
	for (unsigned int i=0; i < m_pPFXEffectParser->GetNumberEffects(); i++)
	{
		// Store the indices for the individual effects
		if (m_pPFXEffectParser->GetEffect(i).Name == c_RenderShadowMapEffectName)
			m_iEffectIndex[INDEX_RENDERSHADOW] = i;
		else if (m_pPFXEffectParser->GetEffect(i).Name == c_RenderSceneEffectName)
			m_iEffectIndex[INDEX_RENDERSCENE] = i;		
	}	

	if (!CreateFBO(&ErrorStr))
	{
		PVRShellSet(prefExitMessage, ErrorStr.c_str());
		return false;
	}

	//	Initialize Print3D
	if (m_Print3D.SetTextures(0, PVRShellGet(prefWidth), PVRShellGet(prefHeight),m_bRotate) != PVR_SUCCESS)
	{
		PVRShellSet(prefExitMessage, "ERROR: Cannot initialize Print3D\n");
		return false;
	}

	// Use a nice bright blue as clear colour
	glClearColor(0.6f, 0.8f, 1.0f, 1.0f);

	// Enable culling
	glEnable(GL_CULL_FACE);	

	// and depth testing
	glEnable(GL_DEPTH_TEST);

	return true;
}
Esempio n. 3
0
/*!****************************************************************************
 @Function		LoadPFX
 @Output		pErrorStr		A string describing the error on failure
 @Return		bool			true if no error occurred
 @Description	Loads and compiles the shaders and links the shader programs
				required for this training course
******************************************************************************/
bool OGLES3MagicLantern::LoadPFX(void)
{
	CPVRTString error = "";
	
	// Parse the whole PFX and store all data.
	m_ppEffectParser = new CPVRTPFXParser();
	if(m_ppEffectParser->ParseFromFile(c_szPFXSrcFile, &error) != PVR_SUCCESS)
	{
		error = "Parse failed:\n\n" + error;
		PVRShellSet(prefExitMessage, error.c_str());
		return false;
	}

	// Setup all effects in the PFX file so we initialise the shaders and
	// store uniforms and attributes locations.
	unsigned int uNumEffects = m_ppEffectParser->GetNumberEffects();
	for (unsigned int i=0; i<uNumEffects; i++)
	{
		// Load one by one the effects. This will also compile the shaders.
		m_pFX[i] = new CPVRTPFXEffect();
		unsigned int nUnknownUniformCount = 0;
		if(m_pFX[i]->Load(*m_ppEffectParser, m_ppEffectParser->GetEffect(i).Name.c_str(), NULL, this, nUnknownUniformCount, &error)  != PVR_SUCCESS)
		{
			error = "Effect load failed:\n\n" + error;
			PVRShellSet(prefExitMessage, error.c_str());
			return false;
		}

		// .. upps, some uniforms are not in our table. Better to quit because something is not quite right.
		if(nUnknownUniformCount)
		{
			PVRShellOutputDebug(error.c_str());
			PVRShellOutputDebug("Unknown uniform semantic count: %d\n", nUnknownUniformCount);
			return false;
		}
	}

	// Allocate an array of integers to hold an effect ID per material.
	m_puiMaterialEffectID = new GLuint[m_Scene.nNumMaterial];
	
	// Assign an effect to each material based on its name.
	// If there is a material with an effect name which is not in the PFX 
	// file, the application will quit and report an error.
	for(int i = 0; i < (int) m_Scene.nNumMaterial; ++i)
	{
		SPODMaterial* pMaterial = &m_Scene.pMaterial[i];

		m_puiMaterialEffectID[i] = 0xbad;

		for (unsigned int j=0; j<uNumEffects; j++)
		{
			// Compare the effect string in the material to each effect in our file so we can
			// match effects to meshes.
			// All effects are contained in the same PFX file so we do not have to worry about
			// effects spread across several files.
			// Note: Each material can only contain a single effect but the same effect
			// might be applied to several materials.
			if (m_ppEffectParser->GetEffect(j).Name == pMaterial->pszEffectName)
			{
				m_puiMaterialEffectID[i] = j;
			}
		}

		if(m_puiMaterialEffectID[i] == 0xbad)
		{
			PVRShellOutputDebug("ERROR: %s effect not found in PFX\n", pMaterial->pszEffectName);
			return false;
		}
	}

	return true;
}
Esempio n. 4
0
/*!****************************************************************************
 @Function		RenderScene
 @Return		bool		true if no error occurred
 @Description	Main rendering loop function of the program. The shell will
				call this function every frame.
				eglSwapBuffers() will be performed by PVRShell automatically.
				PVRShell will also manage important OS events.
				Will also manage relevant OS events. The user has access to
				these events through an abstraction layer provided by PVRShell.
******************************************************************************/
bool OGLES3MagicLantern::RenderScene()
{
	PVRTMat4 mLightWorld;

	// Clear the color and depth buffer.
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Time based animation and locks the app to 60 FPS.
	// Uses the shell function PVRShellGetTime() to get the time in milliseconds.
	unsigned long ulTime = PVRShellGetTime();
	unsigned long ulDeltaTime = ulTime - m_ulTimePrev;
	m_ulTimePrev = ulTime;
	m_fFrame += (float)ulDeltaTime * (60.0f/1000.0f);

	// Create an animation for the the position and rotation of the light-ball.
	m_LightPosition.x = cos(m_fFrame/140.0f)*60.0f;
	m_LightPosition.z = sin(m_fFrame/70.0f)*60.0f - 40.0f;
	m_LightPosition.y = sin(m_fFrame/100.0f)*20.0f;

	mLightWorld  = PVRTMat4::Translation(m_LightPosition.x, m_LightPosition.y-10, m_LightPosition.z);
	mLightWorld *= PVRTMat4::RotationX(m_fFrame/540.0f);
	mLightWorld *= PVRTMat4::RotationZ(m_fFrame/370.0f);
	
	// To draw a scene, you must go through all the MeshNodes and draw the referenced meshes.
	for (unsigned int i = 0; i < m_Scene.nNumMeshNode; ++i)
	{
		SPODNode& Node = m_Scene.pNode[i]; 

		// Get the current effect from the material ID. The list of IDs was built in LoadPFX()
		GLuint uiFXID = m_puiMaterialEffectID[Node.nIdxMaterial];

		// Use the loaded effect (Vertex and Fragment shader)
		// And also bind all textures in the effect.
		m_pFX[uiFXID]->Activate();
		
		// Set the blend mode
		// Based in the info stored in the material by PVRShaman.
		// We check whether the blend mode is 'opaque' (ONE,ZERO).
		// Otherwise we enable blending and set the corresponding operations.
		if (m_Scene.pMaterial[Node.nIdxMaterial].eBlendSrcRGB == ePODBlendFunc_ONE && m_Scene.pMaterial[Node.nIdxMaterial].eBlendDstRGB == ePODBlendFunc_ZERO)
		{
			glDisable(GL_BLEND);
		}
		else
		{
			glEnable(GL_BLEND);
			glBlendFunc(m_Scene.pMaterial[Node.nIdxMaterial].eBlendSrcRGB, m_Scene.pMaterial[Node.nIdxMaterial].eBlendDstRGB);
		}

		// Now process PVRShaman semantics and set-up the associated uniforms.
		const CPVRTArray<SPVRTPFXUniform>& Uniforms = m_pFX[uiFXID]->GetUniformArray();
		for(unsigned int j = 0; j < Uniforms.GetSize() ; ++j)
		{
			switch(Uniforms[j].nSemantic)
			{
			case ePVRTPFX_UsWORLDVIEWPROJECTION:
				{
					PVRTMat4 mWVP;

					// The whole scene (except the ball) is static.
					// The POD file was saved with 'word space' coordinates so there is no need to apply the
					// transformation matrices for the meshes, just the identity.
					// If you are exporting animation you will need to set the corresponding mesh
					// transformation matrix here (see IntroducingPOD training course).
					PVRTMat4 mWorld = PVRTMat4::Identity();

					// Check whether the current effect is the sphere and set up the word matrix with the sphere animation.
					if (m_ppEffectParser->GetEffect(uiFXID).Name == c_SphereEffectName)
					{
						mWorld = mLightWorld;
					}

					// Pass the model-view-projection matrix (MVP) to the shader to transform the vertices.
					PVRTMat4 mModelView;
					mModelView = m_mView * mWorld;
					mWVP = m_mProjection * mModelView;

					glUniformMatrix4fv(Uniforms[j].nLocation, 1, GL_FALSE, mWVP.f);
				} 
				break;
			case ePVRTPFX_UsWORLDIT:
				{
					// Passes the inverse transpose of the light rotation matrix.
					// This is needed to transform the light direction (from the light to each vertex) 
					// and it will give us a three component texture vector to map the cubemap texture.
					PVRTMat3 mLightModelIT = PVRTMat3(mLightWorld).inverse().transpose();
					glUniformMatrix3fv(Uniforms[j].nLocation, 1, GL_FALSE, mLightModelIT.f);
				}
				break;
			case ePVRTPFX_UsLIGHTPOSWORLD:
				{
					glUniform3f(Uniforms[j].nLocation, m_LightPosition.x, m_LightPosition.y, m_LightPosition.z);
				}
				break;
			case ePVRTPFX_UsLIGHTCOLOR:
				{
					// Some color variation here to make it more interesting.
					float afLightColor[] = { 1.0f, sin(m_fFrame/300.0f)*0.3f+0.7f, cos(m_fFrame/400.0f)*0.3f+0.7f};
					glUniform3fv(Uniforms[j].nLocation, 1, afLightColor ); 
				}
				break;
			}
		}

		// Now that all transformation matrices and the materials are ready,
		// call a function to actually draw the mesh.
		// We need to pass the current effect to process 'attributes' properly.
		DrawMesh(i, m_pFX[uiFXID]);
	}

	// Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools.
	m_Print3D.DisplayDefaultTitle("Magic Lantern", "", ePVRTPrint3DSDKLogo);
	m_Print3D.Flush();

	return true;
}