/*!*************************************************************************** @Function LoadEffect @Output ppEffect @Input pszEffectName @Input pszFileName @Return bool @Description Loads a PFX Effect. *****************************************************************************/ bool OGLES3Skybox2::LoadEffect( CPVRTPFXEffect **ppEffect, const char * pszEffectName, const char *pszFileName ) { if(!ppEffect) return false; unsigned int nUnknownUniformCount; CPVRTString error; CPVRTPFXEffect* pEffect = *ppEffect; // Load an effect from the file if(!pEffect) { *ppEffect = new CPVRTPFXEffect(); pEffect = *ppEffect; if(!pEffect) { delete m_pEffectParser; PVRShellSet(prefExitMessage, "Failed to create effect.\n"); return false; } } if(pEffect->Load(*m_pEffectParser, pszEffectName, pszFileName, NULL, nUnknownUniformCount, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } if(nUnknownUniformCount) { PVRShellOutputDebug(error.c_str()); PVRShellOutputDebug("Unknown uniform semantic count: %d\n", nUnknownUniformCount); } /* Set the textures for each effect */ unsigned int i,j ; const CPVRTArray<SPVRTPFXTexture>& sTex = pEffect->GetTextureArray(); for(i = 0; i < sTex.GetSize(); ++i) { for(j = 0; j < g_ui32TexNo; ++j) { int iTexIdx = m_pEffectParser->FindTextureByName(sTex[i].Name); const CPVRTStringHash& FileName = m_pEffectParser->GetTexture(iTexIdx)->FileName; if(FileName == g_aszTextureNames[j]) { if(j == 3 || j == 4) pEffect->SetTexture(i, m_ui32TextureIDs[j], PVRTEX_CUBEMAP); else pEffect->SetTexture(i, m_ui32TextureIDs[j]); break; } } } return true; }
/*!*************************************************************************** @Function ChangeSkyboxTo @Output pEffect @Input ui32NewSkybox @Description Changes the skybox to use the selected effect. *****************************************************************************/ void OGLES3Skybox2::ChangeSkyboxTo(CPVRTPFXEffect *pEffect, GLuint ui32NewSkybox) { const CPVRTArray<SPVRTPFXTexture>& sTex = pEffect->GetTextureArray(); for(unsigned int i = 0; i < sTex.GetSize(); ++i) { int iTexIdx = m_pEffectParser->FindTextureByName(sTex[i].Name); const CPVRTStringHash& FileName = m_pEffectParser->GetTexture(iTexIdx)->FileName; if(FileName == g_aszTextureNames[3]) { pEffect->SetTexture(i, ui32NewSkybox, PVRTEX_CUBEMAP); return; } } }
/*!**************************************************************************** @Function ReleaseView @Return bool true if no error occurred @Description Code in ReleaseView() will be called by PVRShell when the application quits or before a change in the rendering context. ******************************************************************************/ bool OGLES3MagicLantern::ReleaseView() { // Delete all effects. for (unsigned int i=0; i<m_ppEffectParser->GetNumberEffects(); i++) { delete m_pFX[i]; } // Delete the PFX container. delete m_ppEffectParser; // Delete buffer objects. glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo); glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo); // Release loaded textures for(unsigned int uiIndex = 0; uiIndex < m_TextureCache.GetSize(); ++uiIndex) { GLuint uiHandle = m_TextureCache.GetDataAtIndex(uiIndex)->uiHandle; glDeleteTextures(1, &uiHandle); } m_TextureCache.Clear(); // Release Print3D Textures m_Print3D.ReleaseTextures(); return true; }
/*!**************************************************************************** @Function ReleaseView @Return bool true if no error occured @Description Code in ReleaseView() will be called by PVRShell when the application quits or before a change in the rendering context. ******************************************************************************/ bool OGLES3ShadowMapping::ReleaseView() { // Release textures { const CPVRTArray<SPVRTPFXTexture>& sTex = m_ppPFXEffects[0]->GetTextureArray(); for(unsigned int i = 0; i < sTex.GetSize(); ++i) glDeleteTextures(1, &sTex[i].ui); } // Release Print3D Textures m_Print3D.ReleaseTextures(); glDeleteBuffers(m_Scene.nNumMeshNode, m_puiVbo); glDeleteBuffers(m_Scene.nNumMeshNode, m_puiIndexVbo); // Release the effect[s] then the parser if (m_pPFXEffectParser) for (unsigned int i=0; i < m_pPFXEffectParser->GetNumberEffects(); i++) if (m_ppPFXEffects[i]) delete m_ppPFXEffects[i]; delete [] m_ppPFXEffects; delete m_pPFXEffectParser; return true; }
/*!**************************************************************************** @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; }
/*!**************************************************************************** @Function InitView @Return bool true if no error occurred @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 dependent on the rendering context (e.g. textures, vertex buffers, etc.) ******************************************************************************/ bool OGLES3Skybox2::InitView() { // Sets the clear colour glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // Enables depth test using the z-buffer glEnable(GL_DEPTH_TEST); CPVRTString ErrorStr; /* Load textures */ if(!LoadTextures(&ErrorStr)) { PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } /*********************/ /* Create the Skybox */ /*********************/ float* skyboxVertices; float* skyboxUVs; PVRTCreateSkybox( 500.0f, true, 512, &skyboxVertices, &skyboxUVs ); glGenBuffers(1, &m_iSkyVboID); glBindBuffer(GL_ARRAY_BUFFER, m_iSkyVboID); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 24, &skyboxVertices[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); PVRTDestroySkybox(skyboxVertices, skyboxUVs); /**********************/ /* Create the Effects */ /**********************/ { // Parse the file m_pEffectParser = new CPVRTPFXParser(); if(m_pEffectParser->ParseFromFile(g_pszEffectFileName, &ErrorStr) != PVR_SUCCESS) { delete m_pEffectParser; PVRShellSet(prefExitMessage, ErrorStr.c_str()); return false; } m_ppEffects = new CPVRTPFXEffect*[g_ui32NoOfEffects]; memset(m_ppEffects, 0, sizeof(CPVRTPFXEffect*) * g_ui32NoOfEffects); // Skybox shader if(!LoadEffect(&m_ppEffects[0], "skybox_effect", g_pszEffectFileName)) { delete m_pEffectParser; delete[] m_ppEffects; return false; } // The Balloon Shaders if(!LoadEffect(&m_ppEffects[1], "balloon_effect1", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[2], "balloon_effect2", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[3], "balloon_effect3", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[4], "balloon_effect4", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[5], "balloon_effect5", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[6], "balloon_effect6", g_pszEffectFileName) || !LoadEffect(&m_ppEffects[7], "balloon_effect7", g_pszEffectFileName)) { delete m_pEffectParser; delete[] m_ppEffects; return false; } } // Create Geometry Buffer Objects. m_aiVboID = new GLuint[m_Scene.nNumMeshNode]; glGenBuffers(m_Scene.nNumMeshNode, m_aiVboID); for(unsigned int i = 0; i < m_Scene.nNumMeshNode ; ++i) { SPODNode* pNode = &m_Scene.pNode[i]; // Gets pMesh referenced by the pNode SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx]; // Genereta a vertex buffer and set the interleaved vertex datas. glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]); glBufferData(GL_ARRAY_BUFFER, pMesh->sVertex.nStride*pMesh->nNumVertex, pMesh->pInterleaved, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } /********************** ** Projection Matrix ** **********************/ /* Projection */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI / 6, (float) PVRShellGet(prefWidth) / (float) PVRShellGet(prefHeight), 4.0f, 1000.0f, PVRTMat4::OGL, bRotate); // Calculate the model view matrix turning around the balloon ComputeViewMatrix(); /* Init Values */ bPause = false; fDemoFrame = 0.0; fBurnAnim = 0.0f; m_i32Effect = 1; // Initialise Print3D if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Initialise variables used for the animation m_iTimePrev = PVRShellGetTime(); return true; }
/*!**************************************************************************** @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 OGLESIntroducingPFX::InitView() { /* Initialize Print3D */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Sets the clear color glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // Enables depth test using the z-buffer glEnable(GL_DEPTH_TEST); /* Loads the light direction from the scene. */ // We check the scene contains at least one if (m_Scene.nNumLight == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light\n"); return false; } /* Load the effect file */ { unsigned int nUnknownUniformCount; CPVRTString error; // Parse the file m_pEffectParser = new CPVRTPFXParser; if(m_pEffectParser->ParseFromFile(c_szPfxFile, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } // Load an effect from the file m_pEffect = new CPVRTPFXEffect(); if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } // Generate uniform array if(m_pEffect->BuildUniformTable( &m_psUniforms, &m_nUniformCnt, &nUnknownUniformCount, c_psUniformSemantics, sizeof(c_psUniformSemantics) / sizeof(*c_psUniformSemantics), &error) != PVR_SUCCESS) { PVRShellOutputDebug(error.c_str()); return false; } if(nUnknownUniformCount) { PVRShellOutputDebug(error.c_str()); PVRShellOutputDebug("Unknown uniform semantic count: %d\n", nUnknownUniformCount); } } /* Loads the textures. For a more detailed explanation, see Texturing and IntroducingPVRTools */ { const SPVRTPFXTexture *psTex; unsigned int nCnt, i; GLuint ui; psTex = m_pEffect->GetTextureArray(nCnt); for(i = 0; i < nCnt; ++i) { if(strcmp(psTex[i].p, "Reflection.pvr") == 0) { if(PVRTTextureLoadFromPVR(c_szReflectTexFile, &ui) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot load the texture\n"); return false; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); m_pEffect->SetTexture(i, ui); } else if (strcmp(psTex[i].p, "Basetex.pvr") == 0) { if(PVRTTextureLoadFromPVR(c_szBaseTexFile, &ui) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot load the texture\n"); return false; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); m_pEffect->SetTexture(i, ui); } else { PVRShellOutputDebug("Warning: effect file requested unrecognised texture: \"%s\"\n", psTex[i].p); m_pEffect->SetTexture(i, 0); } } } // Create buffer objects. m_aiVboID = new GLuint[m_Scene.nNumMeshNode]; glGenBuffers(m_Scene.nNumMeshNode, m_aiVboID); for(int i = 0; i < (int)m_Scene.nNumMeshNode ; i++) { SPODNode* pNode = &m_Scene.pNode[i]; // Gets pMesh referenced by the pNode SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx]; // Generate a vertex buffer and set the interleaved vertex data. glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]); glBufferData(GL_ARRAY_BUFFER, pMesh->sVertex.nStride*pMesh->nNumVertex, pMesh->pInterleaved, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } return true; }
/*!**************************************************************************** @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 OGLES3IntroducingPFX::InitView() { /* Initialize Print3D */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Sets the clear color glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // Enables depth test using the z-buffer glEnable(GL_DEPTH_TEST); /* Loads the light direction from the scene. */ // We check the scene contains at least one if (m_Scene.nNumLight == 0) { PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light\n"); return false; } // Load the VBOs LoadVBOs(); /* Load the effect file */ CPVRTString error; unsigned int uiUnknownUniforms; // Parse the file m_pEffectParser = new CPVRTPFXParser; if(m_pEffectParser->ParseFromFile(c_szPfxFile, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } // --- Load an effect from the file m_pEffect = new CPVRTPFXEffect(); // Register a custom uniform if(m_pEffect->RegisterUniformSemantic(c_sCustomSemantics, sizeof(c_sCustomSemantics) / sizeof(c_sCustomSemantics[0]), &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } /* Load the effect. We pass 'this' as an argument as we wish to receive callbacks as the PFX is loaded. This is optional and supplying NULL implies that the developer will take care of all texture loading and binding to to the Effect instead. */ if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, this, uiUnknownUniforms, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } /* 'Unknown uniforms' are uniform semantics that have been detected in the PFX file but are unknown to PVRTools. If you wish to utilise this semantic, register the semantic by calling RegisterUniformSemantic(). This is performed above. */ if(uiUnknownUniforms) { PVRShellOutputDebug(error.c_str()); PVRShellOutputDebug("Unknown uniform semantic count: %u\n", uiUnknownUniforms); } // Enable culling glEnable(GL_CULL_FACE); return true; }
/*!**************************************************************************** @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; }
/*!**************************************************************************** @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 OGLES2MaximumIntensityBlend::InitView() { /* Check that EXT_blend_minmax is supported */ if(!CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_blend_minmax")) { PVRShellSet(prefExitMessage, "ERROR: GL_EXT_blend_minmax extension is required to run this example."); return false; } /* Initialize Print3D */ bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen); if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n"); return false; } // Sets the clear color glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glEnable(GL_CULL_FACE); glFrontFace(GL_CW); // Load the VBOs LoadVBOs(); /* Load the effect file */ CPVRTString error; unsigned int uiUnknownUniforms; // Parse the file m_pEffectParser = new CPVRTPFXParser; if(m_pEffectParser->ParseFromFile(c_szPfxFile, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } // --- Load an effect from the file m_pEffect = new CPVRTPFXEffect(); m_pEffect->RegisterUniformSemantic(c_sCustomSemantics, sizeof(c_sCustomSemantics) / sizeof(c_sCustomSemantics[0]), &error); /* Load the effect. */ if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, NULL, uiUnknownUniforms, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } // --- Load the textured effect m_pEffectTextured = new CPVRTPFXEffect(); m_pEffectTextured->RegisterUniformSemantic(c_sCustomSemantics, sizeof(c_sCustomSemantics) / sizeof(c_sCustomSemantics[0]), &error); /* Load the effect. */ if(m_pEffectTextured->Load(*m_pEffectParser, "TexturedEffect", c_szPfxFile, this, uiUnknownUniforms, &error) != PVR_SUCCESS) { PVRShellSet(prefExitMessage, error.c_str()); return false; } return true; }
/*!**************************************************************************** @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; }
/*!**************************************************************************** @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; }