OGLES2Skybox2.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /******************************************************************************
  2. @File OGLES2Skybox2.cpp
  3. @Title Introducing the POD 3d file format
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independant
  7. @Description Shows how to load POD files and play the animation with basic
  8. lighting
  9. ******************************************************************************/
  10. #include <string.h>
  11. #include <math.h>
  12. #include "PVRShell.h"
  13. #include "OGLES2Tools.h"
  14. /******************************************************************************
  15. Defines
  16. ******************************************************************************/
  17. // Camera constants. Used for making the projection matrix
  18. // Shader semantics recognised by this program
  19. enum EUniformSemantic
  20. {
  21. eUsUnknown,
  22. eUsPOSITION,
  23. eUsNORMAL,
  24. eUsUV,
  25. eUsWORLDVIEWPROJECTION,
  26. eUsWORLDVIEW,
  27. eUsWORLDVIEWIT,
  28. eUsVIEWIT,
  29. eUsLIGHTDIRECTION,
  30. eUsTEXTURE
  31. };
  32. /****************************************************************************
  33. ** Constants
  34. ****************************************************************************/
  35. const static SPVRTPFXUniformSemantic c_psUniformSemantics[] =
  36. {
  37. { "POSITION", eUsPOSITION },
  38. { "NORMAL", eUsNORMAL },
  39. { "UV", eUsUV },
  40. { "WORLDVIEWPROJECTION", eUsWORLDVIEWPROJECTION },
  41. { "WORLDVIEW", eUsWORLDVIEW },
  42. { "WORLDVIEWIT", eUsWORLDVIEWIT },
  43. { "VIEWIT", eUsVIEWIT},
  44. { "LIGHTDIRECTION", eUsLIGHTDIRECTION },
  45. { "TEXTURE", eUsTEXTURE }
  46. };
  47. struct SEffect
  48. {
  49. CPVRTPFXEffect *pEffect;
  50. SPVRTPFXUniform *psUniforms;
  51. unsigned int ui32UniformCount;
  52. SEffect()
  53. {
  54. pEffect = 0;
  55. psUniforms = 0;
  56. ui32UniformCount = 0;
  57. }
  58. };
  59. const float g_fFrameRate = 1.0f / 30.0f;
  60. const unsigned int g_ui32NoOfEffects = 8;
  61. const unsigned int g_ui32TexNo = 5;
  62. const bool g_bBlendShader[g_ui32NoOfEffects] = {
  63. false,
  64. false,
  65. false,
  66. false,
  67. true,
  68. false,
  69. false,
  70. true
  71. };
  72. /******************************************************************************
  73. Content file names
  74. ******************************************************************************/
  75. // POD scene files
  76. const char c_szSceneFile[] = "Scene.pod";
  77. // Textures
  78. const char * const g_aszTextureNames[g_ui32TexNo] = {
  79. "Balloon.pvr",
  80. "Balloon_pvr.pvr",
  81. "Noise.pvr",
  82. "Skybox.pvr",
  83. "SkyboxMidnight.pvr"
  84. };
  85. // PFX file
  86. const char * const g_pszEffectFileName = "effects.pfx";
  87. /*!****************************************************************************
  88. Class implementing the PVRShell functions.
  89. ******************************************************************************/
  90. class OGLES2Skybox2 : public PVRShell
  91. {
  92. // Print3D class used to display text
  93. CPVRTPrint3D m_Print3D;
  94. // IDs for the various textures
  95. GLuint m_ui32TextureIDs[g_ui32TexNo];
  96. // 3D Model
  97. CPVRTModelPOD m_Scene;
  98. // Projection and Model View matrices
  99. PVRTMat4 m_mProjection, m_mView;
  100. // Variables to handle the animation in a time-based manner
  101. unsigned long m_iTimePrev;
  102. float m_fFrame;
  103. // The effect currently being displayed
  104. int m_i32Effect;
  105. // The Vertex buffer object handle array.
  106. GLuint *m_aiVboID;
  107. GLuint m_iSkyVboID;
  108. /* View Variables */
  109. VERTTYPE fViewAngle;
  110. VERTTYPE fViewDistance, fViewAmplitude, fViewAmplitudeAngle;
  111. VERTTYPE fViewUpDownAmplitude, fViewUpDownAngle;
  112. /* Vectors for calculating the view matrix and saving the camera position*/
  113. PVRTVec3 vTo, vUp, vCameraPosition;
  114. /* Skybox */
  115. VERTTYPE* g_SkyboxVertices;
  116. VERTTYPE* g_SkyboxUVs;
  117. //animation
  118. float fBurnAnim;
  119. bool bPause;
  120. float fDemoFrame;
  121. // The variables required for the effects
  122. CPVRTPFXParser *m_pEffectParser;
  123. SEffect *m_pEffects;
  124. public:
  125. OGLES2Skybox2()
  126. {
  127. /* Init values to defaults */
  128. fViewAngle = PVRT_PI_OVER_TWO;
  129. fViewDistance = 100.0f;
  130. fViewAmplitude = 60.0f;
  131. fViewAmplitudeAngle = 0.0f;
  132. fViewUpDownAmplitude = 50.0f;
  133. fViewUpDownAngle = 0.0f;
  134. vTo.x = 0;
  135. vTo.y = 0;
  136. vTo.z = 0;
  137. vUp.x = 0;
  138. vUp.y = 1;
  139. vUp.z = 0;
  140. }
  141. virtual bool InitApplication();
  142. virtual bool InitView();
  143. virtual bool ReleaseView();
  144. virtual bool QuitApplication();
  145. virtual bool RenderScene();
  146. void DrawMesh(SPODMesh* mesh);
  147. void ComputeViewMatrix();
  148. void DrawSkybox();
  149. bool LoadEffect(SEffect *pSEffect, const char * pszEffectName, const char *pszFileName);
  150. bool LoadTextures(CPVRTString* const pErrorStr);
  151. bool DestroyEffect(SEffect *pSEffect);
  152. void ChangeSkyboxTo(SEffect *pSEffect, GLuint ui32NewSkybox);
  153. };
  154. /*!****************************************************************************
  155. @Function InitApplication
  156. @Return bool true if no error occured
  157. @Description Code in InitApplication() will be called by PVRShell once per
  158. run, before the rendering context is created.
  159. Used to initialize variables that are not dependant on it
  160. (e.g. external modules, loading meshes, etc.)
  161. If the rendering context is lost, InitApplication() will
  162. not be called again.
  163. ******************************************************************************/
  164. bool OGLES2Skybox2::InitApplication()
  165. {
  166. // Get and set the read path for content files
  167. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  168. // Load the scene
  169. if (m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
  170. {
  171. PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
  172. return false;
  173. }
  174. // Initialise variables used for the animation
  175. m_fFrame = 0;
  176. m_iTimePrev = PVRShellGetTime();
  177. return true;
  178. }
  179. /*!****************************************************************************
  180. @Function QuitApplication
  181. @Return bool true if no error occured
  182. @Description Code in QuitApplication() will be called by PVRShell once per
  183. run, just before exiting the program.
  184. If the rendering context is lost, QuitApplication() will
  185. not be called.
  186. ******************************************************************************/
  187. bool OGLES2Skybox2::QuitApplication()
  188. {
  189. // Frees the memory allocated for the scene
  190. m_Scene.Destroy();
  191. return true;
  192. }
  193. bool OGLES2Skybox2::LoadTextures(CPVRTString* const pErrorStr)
  194. {
  195. for(int i = 0; i < 3; ++i)
  196. {
  197. if(PVRTTextureLoadFromPVR(g_aszTextureNames[i], &m_ui32TextureIDs[i]) != PVR_SUCCESS)
  198. return false;
  199. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  200. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  201. }
  202. // Load cube maps
  203. for(int i = 3; i < 5; ++i)
  204. {
  205. if(PVRTTextureLoadFromPVR(g_aszTextureNames[i], &m_ui32TextureIDs[i]))
  206. {
  207. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + g_aszTextureNames[i];
  208. return false;
  209. }
  210. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  211. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  212. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  213. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  214. }
  215. return true;
  216. }
  217. /*!****************************************************************************
  218. @Function InitView
  219. @Return bool true if no error occured
  220. @Description Code in InitView() will be called by PVRShell upon
  221. initialization or after a change in the rendering context.
  222. Used to initialize variables that are dependant on the rendering
  223. context (e.g. textures, vertex buffers, etc.)
  224. ******************************************************************************/
  225. bool OGLES2Skybox2::InitView()
  226. {
  227. // Sets the clear color
  228. glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  229. // Enables depth test using the z-buffer
  230. glEnable(GL_DEPTH_TEST);
  231. CPVRTString ErrorStr;
  232. /*
  233. Load textures
  234. */
  235. if(!LoadTextures(&ErrorStr))
  236. {
  237. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  238. return false;
  239. }
  240. /*********************/
  241. /* Create the Skybox */
  242. /*********************/
  243. PVRTCreateSkybox( 500.0f, true, 512, &g_SkyboxVertices, &g_SkyboxUVs );
  244. /**********************/
  245. /* Create the Effects */
  246. /**********************/
  247. {
  248. // Parse the file
  249. m_pEffectParser = new CPVRTPFXParser();
  250. if(m_pEffectParser->ParseFromFile(g_pszEffectFileName, &ErrorStr) != PVR_SUCCESS)
  251. {
  252. delete m_pEffectParser;
  253. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  254. return false;
  255. }
  256. m_pEffects = new SEffect[m_pEffectParser->m_nNumEffects];
  257. // Skybox shader
  258. if(!LoadEffect(&m_pEffects[0], "skybox_effect", g_pszEffectFileName))
  259. {
  260. delete m_pEffectParser;
  261. delete[] m_pEffects;
  262. return false;
  263. }
  264. // The Balloon Shaders
  265. if(!LoadEffect(&m_pEffects[1], "balloon_effect1", g_pszEffectFileName) ||
  266. !LoadEffect(&m_pEffects[2], "balloon_effect2", g_pszEffectFileName) ||
  267. !LoadEffect(&m_pEffects[3], "balloon_effect3", g_pszEffectFileName) ||
  268. !LoadEffect(&m_pEffects[4], "balloon_effect4", g_pszEffectFileName) ||
  269. !LoadEffect(&m_pEffects[5], "balloon_effect5", g_pszEffectFileName) ||
  270. !LoadEffect(&m_pEffects[6], "balloon_effect6", g_pszEffectFileName) ||
  271. !LoadEffect(&m_pEffects[7], "balloon_effect7", g_pszEffectFileName))
  272. {
  273. delete m_pEffectParser;
  274. delete[] m_pEffects;
  275. return false;
  276. }
  277. }
  278. // Create Geometry Buffer Objects.
  279. m_aiVboID = new GLuint[m_Scene.nNumMeshNode];
  280. glGenBuffers(m_Scene.nNumMeshNode, m_aiVboID);
  281. for(unsigned int i = 0; i < m_Scene.nNumMeshNode ; ++i)
  282. {
  283. SPODNode* pNode = &m_Scene.pNode[i];
  284. // Gets pMesh referenced by the pNode
  285. SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx];
  286. // Genereta a vertex buffer and set the interleaved vertex datas.
  287. glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]);
  288. glBufferData(GL_ARRAY_BUFFER, pMesh->sVertex.nStride*pMesh->nNumVertex, pMesh->pInterleaved, GL_STATIC_DRAW);
  289. glBindBuffer(GL_ARRAY_BUFFER, 0);
  290. }
  291. glGenBuffers(1, &m_iSkyVboID);
  292. glBindBuffer(GL_ARRAY_BUFFER, m_iSkyVboID);
  293. glBufferData(GL_ARRAY_BUFFER, sizeof(VERTTYPE)*3 * 8, &g_SkyboxVertices, GL_STATIC_DRAW);
  294. glBindBuffer(GL_ARRAY_BUFFER, 0);
  295. /**********************
  296. ** Projection Matrix **
  297. **********************/
  298. /* Projection */
  299. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  300. m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI / 6, (float) PVRShellGet(prefWidth) / (float) PVRShellGet(prefHeight), 4.0f, 1000.0f, PVRTMat4::OGL, bRotate);
  301. // Calculate the model view matrix turning around the balloon
  302. ComputeViewMatrix();
  303. /* Init Values */
  304. bPause = false;
  305. fDemoFrame = 0.0;
  306. fBurnAnim = 0.0f;
  307. m_i32Effect = 1;
  308. /*
  309. Initialise Print3D
  310. */
  311. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
  312. {
  313. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  314. return false;
  315. }
  316. return true;
  317. }
  318. bool OGLES2Skybox2::LoadEffect(SEffect *pSEffect, const char * pszEffectName, const char *pszFileName)
  319. {
  320. if(!pSEffect)
  321. return false;
  322. unsigned int nUnknownUniformCount;
  323. CPVRTString error;
  324. // Load an effect from the file
  325. if(!pSEffect->pEffect)
  326. {
  327. pSEffect->pEffect = new CPVRTPFXEffect();
  328. if(!pSEffect->pEffect)
  329. {
  330. delete m_pEffectParser;
  331. PVRShellSet(prefExitMessage, "Failed to create effect.\n");
  332. return false;
  333. }
  334. }
  335. if(pSEffect->pEffect->Load(*m_pEffectParser, pszEffectName, pszFileName, &error) != PVR_SUCCESS)
  336. {
  337. PVRShellSet(prefExitMessage, error.c_str());
  338. return false;
  339. }
  340. // Generate uniform array
  341. if(pSEffect->pEffect->BuildUniformTable(&pSEffect->psUniforms, &pSEffect->ui32UniformCount, &nUnknownUniformCount,
  342. c_psUniformSemantics, sizeof(c_psUniformSemantics) / sizeof(*c_psUniformSemantics), &error) != PVR_SUCCESS)
  343. {
  344. PVRShellSet(prefExitMessage, error.c_str());
  345. return false;
  346. }
  347. if(nUnknownUniformCount)
  348. {
  349. PVRShellOutputDebug(error.c_str());
  350. PVRShellOutputDebug("Unknown uniform semantic count: %d\n", nUnknownUniformCount);
  351. }
  352. /* Set the textures for each effect */
  353. const SPVRTPFXTexture *psTex;
  354. unsigned int nCnt, i,j ;
  355. psTex = pSEffect->pEffect->GetTextureArray(nCnt);
  356. for(i = 0; i < nCnt; ++i)
  357. {
  358. for(j = 0; j < g_ui32TexNo; ++j)
  359. {
  360. if(strcmp(g_aszTextureNames[j], psTex[i].p) == 0)
  361. {
  362. if(j == 3 || j == 4)
  363. pSEffect->pEffect->SetTexture(i, m_ui32TextureIDs[j], PVRTEX_CUBEMAP);
  364. else
  365. pSEffect->pEffect->SetTexture(i, m_ui32TextureIDs[j]);
  366. break;
  367. }
  368. }
  369. }
  370. return true;
  371. }
  372. bool OGLES2Skybox2::DestroyEffect(SEffect *pSEffect)
  373. {
  374. if(pSEffect)
  375. {
  376. if(pSEffect->pEffect)
  377. {
  378. const SPVRTPFXTexture *psTex;
  379. unsigned int nCnt, i;
  380. psTex = pSEffect->pEffect->GetTextureArray(nCnt);
  381. for(i = 0; i < nCnt; ++i)
  382. {
  383. glDeleteTextures(1, &(psTex[i].ui));
  384. }
  385. delete pSEffect->pEffect;
  386. pSEffect->pEffect = 0;
  387. }
  388. FREE(pSEffect->psUniforms);
  389. }
  390. return true;
  391. }
  392. /*!****************************************************************************
  393. @Function ReleaseView
  394. @Return bool true if no error occured
  395. @Description Code in ReleaseView() will be called by PVRShell when the
  396. application quits or before a change in the rendering context.
  397. ******************************************************************************/
  398. bool OGLES2Skybox2::ReleaseView()
  399. {
  400. // Free the textures
  401. unsigned int i;
  402. for(i = 0; i < g_ui32TexNo; ++i)
  403. {
  404. glDeleteTextures(1, &(m_ui32TextureIDs[i]));
  405. }
  406. // Release Print3D Textures
  407. m_Print3D.ReleaseTextures();
  408. // Release Vertex buffer objects.
  409. glDeleteBuffers(m_Scene.nNumMeshNode, m_aiVboID);
  410. glDeleteBuffers(1, &m_iSkyVboID);
  411. delete[] m_aiVboID;
  412. // Destroy the Skybox
  413. PVRTDestroySkybox( g_SkyboxVertices, g_SkyboxUVs );
  414. for(i = 0; i < m_pEffectParser->m_nNumEffects; ++i)
  415. DestroyEffect(&m_pEffects[i]);
  416. delete[] m_pEffects;
  417. delete m_pEffectParser;
  418. return true;
  419. }
  420. /*!****************************************************************************
  421. @Function RenderScene
  422. @Return bool true if no error occured
  423. @Description Main rendering loop function of the program. The shell will
  424. call this function every frame.
  425. eglSwapBuffers() will be performed by PVRShell automatically.
  426. PVRShell will also manage important OS events.
  427. Will also manage relevent OS events. The user has access to
  428. these events through an abstraction layer provided by PVRShell.
  429. ******************************************************************************/
  430. bool OGLES2Skybox2::RenderScene()
  431. {
  432. unsigned int i, j;
  433. // Clears the colour and depth buffer
  434. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  435. /*
  436. Calculates the frame number to animate in a time-based manner.
  437. Uses the shell function PVRShellGetTime() to get the time in milliseconds.
  438. */
  439. unsigned long iTime = PVRShellGetTime();
  440. if(!bPause)
  441. {
  442. // Calculate the model view matrix turning around the balloon
  443. ComputeViewMatrix();
  444. if(iTime > m_iTimePrev)
  445. {
  446. float fDelta = (float) (iTime - m_iTimePrev) * g_fFrameRate;
  447. m_fFrame += fDelta;
  448. fDemoFrame += fDelta;
  449. fBurnAnim += fDelta * 0.02f;
  450. if(fBurnAnim >= 1.0f)
  451. fBurnAnim = 1.0f;
  452. }
  453. }
  454. m_iTimePrev = iTime;
  455. /* KeyBoard input processing */
  456. if(PVRShellIsKeyPressed(PVRShellKeyNameACTION1))
  457. bPause=!bPause;
  458. if(PVRShellIsKeyPressed(PVRShellKeyNameACTION2))
  459. fBurnAnim = 0.0f;
  460. /* Keyboard Animation and Automatic Shader Change over time */
  461. if(!bPause && (fDemoFrame > 500 || (m_i32Effect == 2 && fDemoFrame > 80)))
  462. {
  463. if(++m_i32Effect >= (int) g_ui32NoOfEffects)
  464. {
  465. m_i32Effect = 1;
  466. m_fFrame = 0.0f;
  467. }
  468. fDemoFrame = 0.0f;
  469. fBurnAnim = 0.0f;
  470. }
  471. /* Change Shader Effect */
  472. if(PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
  473. {
  474. if(++m_i32Effect >= (int) g_ui32NoOfEffects)
  475. m_i32Effect = 1;
  476. fDemoFrame = 0.0f;
  477. fBurnAnim = 0.0f;
  478. m_fFrame = 0.0f;
  479. }
  480. if(PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
  481. {
  482. if(--m_i32Effect < 1)
  483. m_i32Effect = g_ui32NoOfEffects - 1;
  484. fDemoFrame = 0.0f;
  485. fBurnAnim = 0.0f;
  486. m_fFrame = 0.0f;
  487. }
  488. /* Change Skybox Texture */
  489. if(PVRShellIsKeyPressed(PVRShellKeyNameUP))
  490. {
  491. for(i = 0; i < g_ui32NoOfEffects; ++i)
  492. ChangeSkyboxTo(&m_pEffects[i], m_ui32TextureIDs[4]);
  493. fBurnAnim = 0.0f;
  494. }
  495. if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  496. {
  497. for(i = 0; i < g_ui32NoOfEffects; ++i)
  498. ChangeSkyboxTo(&m_pEffects[i], m_ui32TextureIDs[3]);
  499. fBurnAnim = 0.0f;
  500. }
  501. /* Setup Shader and Shader Constants */
  502. int location;
  503. glEnable(GL_CULL_FACE);
  504. glCullFace(GL_BACK);
  505. DrawSkybox();
  506. m_pEffects[m_i32Effect].pEffect->Activate();
  507. for(i = 0; i < m_Scene.nNumMeshNode; i++)
  508. {
  509. SPODNode* pNode = &m_Scene.pNode[i];
  510. // Gets pMesh referenced by the pNode
  511. SPODMesh* pMesh = &m_Scene.pMesh[pNode->nIdx];
  512. // Gets the node model matrix
  513. PVRTMat4 mWorld, mWORLDVIEW;
  514. mWorld = m_Scene.GetWorldMatrix(*pNode);
  515. mWORLDVIEW = m_mView * mWorld;
  516. glBindBuffer(GL_ARRAY_BUFFER, m_aiVboID[i]);
  517. for(j = 0; j < m_pEffects[m_i32Effect].ui32UniformCount; ++j)
  518. {
  519. switch(m_pEffects[m_i32Effect].psUniforms[j].nSemantic)
  520. {
  521. case eUsPOSITION:
  522. {
  523. glVertexAttribPointer(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
  524. glEnableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  525. }
  526. break;
  527. case eUsNORMAL:
  528. {
  529. glVertexAttribPointer(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
  530. glEnableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  531. }
  532. break;
  533. case eUsUV:
  534. {
  535. glVertexAttribPointer(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
  536. glEnableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  537. }
  538. break;
  539. case eUsWORLDVIEWPROJECTION:
  540. {
  541. PVRTMat4 mMVP;
  542. /* Passes the model-view-projection matrix (MVP) to the shader to transform the vertices */
  543. mMVP = m_mProjection * mWORLDVIEW;
  544. glUniformMatrix4fv(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 1, GL_FALSE, mMVP.f);
  545. }
  546. break;
  547. case eUsWORLDVIEW:
  548. {
  549. glUniformMatrix4fv(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 1, GL_FALSE, mWORLDVIEW.f);
  550. }
  551. break;
  552. case eUsWORLDVIEWIT:
  553. {
  554. PVRTMat4 mWORLDVIEWI, mWORLDVIEWIT;
  555. mWORLDVIEWI = mWORLDVIEW.inverse();
  556. mWORLDVIEWIT= mWORLDVIEWI.transpose();
  557. PVRTMat3 WORLDVIEWIT = PVRTMat3(mWORLDVIEWIT);
  558. glUniformMatrix3fv(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 1, GL_FALSE, WORLDVIEWIT.f);
  559. }
  560. break;
  561. case eUsVIEWIT:
  562. {
  563. PVRTMat4 mViewI, mViewIT;
  564. mViewI = m_mView.inverse();
  565. mViewIT = mViewI.transpose();
  566. PVRTMat3 ViewIT = PVRTMat3(mViewIT);
  567. glUniformMatrix3fv(m_pEffects[m_i32Effect].psUniforms[j].nLocation, 1, GL_FALSE, ViewIT.f);
  568. }
  569. break;
  570. case eUsLIGHTDIRECTION:
  571. {
  572. PVRTVec4 vLightDirectionEyeSpace;
  573. // Passes the light direction in eye space to the shader
  574. vLightDirectionEyeSpace = m_mView * PVRTVec4(1.0,1.0,-1.0,0.0);
  575. glUniform3f(m_pEffects[m_i32Effect].psUniforms[j].nLocation, vLightDirectionEyeSpace.x, vLightDirectionEyeSpace.y, vLightDirectionEyeSpace.z);
  576. }
  577. break;
  578. case eUsTEXTURE:
  579. {
  580. // Set the sampler variable to the texture unit
  581. glUniform1i(m_pEffects[m_i32Effect].psUniforms[j].nLocation, m_pEffects[m_i32Effect].psUniforms[j].nIdx);
  582. }
  583. break;
  584. }
  585. }
  586. location = glGetUniformLocation(m_pEffects[m_i32Effect].pEffect->m_uiProgram, "myEyePos");
  587. if(location != -1)
  588. glUniform3f(location, vCameraPosition.x, vCameraPosition.y, vCameraPosition.z);
  589. //set animation
  590. location = glGetUniformLocation(m_pEffects[m_i32Effect].pEffect->m_uiProgram, "fAnim");
  591. if(location != -1)
  592. glUniform1f(location, fBurnAnim);
  593. location = glGetUniformLocation(m_pEffects[m_i32Effect].pEffect->m_uiProgram, "myFrame");
  594. if(location != -1)
  595. glUniform1f(location, m_fFrame);
  596. glEnable(GL_CULL_FACE);
  597. glDisable(GL_BLEND);
  598. if(g_bBlendShader[m_i32Effect])
  599. {
  600. glEnable(GL_BLEND);
  601. // Correct render order for alpha blending through culling
  602. // Draw Back faces
  603. location = glGetUniformLocation(m_pEffects[m_i32Effect].pEffect->m_uiProgram, "bBackFace");
  604. glUniform1i(location, 1);
  605. glCullFace(GL_BACK);
  606. DrawMesh(pMesh);
  607. // Draw Front faces
  608. glUniform1i(location, 0);
  609. }
  610. else
  611. {
  612. location = glGetUniformLocation(m_pEffects[m_i32Effect].pEffect->m_uiProgram, "bBackFace");
  613. if(location != -1)
  614. glUniform1i(location, 0);
  615. glDisable(GL_BLEND);
  616. }
  617. glCullFace(GL_FRONT);
  618. /* Everything should now be setup, therefore draw the mesh*/
  619. DrawMesh(pMesh);
  620. glBindBuffer(GL_ARRAY_BUFFER, 0);
  621. for(j = 0; j < m_pEffects[m_i32Effect].ui32UniformCount; ++j)
  622. {
  623. switch(m_pEffects[m_i32Effect].psUniforms[j].nSemantic)
  624. {
  625. case eUsPOSITION:
  626. {
  627. glDisableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  628. }
  629. break;
  630. case eUsNORMAL:
  631. {
  632. glDisableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  633. }
  634. break;
  635. case eUsUV:
  636. {
  637. glDisableVertexAttribArray(m_pEffects[m_i32Effect].psUniforms[j].nLocation);
  638. }
  639. break;
  640. }
  641. }
  642. }
  643. // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
  644. if(!bPause)
  645. m_Print3D.DisplayDefaultTitle("Skybox2", "", ePVRTPrint3DLogoIMG);
  646. else
  647. m_Print3D.DisplayDefaultTitle("Skybox2", "Paused", ePVRTPrint3DLogoIMG);
  648. m_Print3D.Flush();
  649. return true;
  650. }
  651. /*!****************************************************************************
  652. @Function DrawMesh
  653. @Input mesh The mesh to draw
  654. @Description Draws a SPODMesh after the model view matrix has been set and
  655. the meterial prepared.
  656. ******************************************************************************/
  657. void OGLES2Skybox2::DrawMesh(SPODMesh* pMesh)
  658. {
  659. /*
  660. The geometry can be exported in 4 ways:
  661. - Non-Indexed Triangle list
  662. - Indexed Triangle list
  663. - Non-Indexed Triangle strips
  664. - Indexed Triangle strips
  665. */
  666. if(!pMesh->nNumStrips)
  667. {
  668. if(pMesh->sFaces.pData)
  669. {
  670. // Indexed Triangle list
  671. glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, pMesh->sFaces.pData);
  672. }
  673. else
  674. {
  675. // Non-Indexed Triangle list
  676. glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
  677. }
  678. }
  679. else
  680. {
  681. if(pMesh->sFaces.pData)
  682. {
  683. // Indexed Triangle strips
  684. int offset = 0;
  685. for(int i = 0; i < (int)pMesh->nNumStrips; i++)
  686. {
  687. glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, pMesh->sFaces.pData + offset*2);
  688. offset += pMesh->pnStripLength[i]+2;
  689. }
  690. }
  691. else
  692. {
  693. // Non-Indexed Triangle strips
  694. int offset = 0;
  695. for(int i = 0; i < (int)pMesh->nNumStrips; i++)
  696. {
  697. glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
  698. offset += pMesh->pnStripLength[i]+2;
  699. }
  700. }
  701. }
  702. }
  703. /*******************************************************************************
  704. * Function Name : ComputeViewMatrix
  705. * Description : Calculate the view matrix turning around the balloon
  706. *******************************************************************************/
  707. void OGLES2Skybox2::ComputeViewMatrix()
  708. {
  709. PVRTVec3 vFrom;
  710. /* Calculate the distance to balloon */
  711. float fDistance = fViewDistance + fViewAmplitude * (float) sin(fViewAmplitudeAngle);
  712. fDistance = fDistance / 5.0f;
  713. fViewAmplitudeAngle += 0.004f;
  714. /* Calculate the vertical position of the camera */
  715. float updown = fViewUpDownAmplitude * (float) sin(fViewUpDownAngle);
  716. updown = updown / 5.0f;
  717. fViewUpDownAngle += 0.005f;
  718. /* Calculate the angle of the camera around the balloon */
  719. vFrom.x = fDistance * (float) cos(fViewAngle);
  720. vFrom.y = updown;
  721. vFrom.z = fDistance * (float) sin(fViewAngle);
  722. fViewAngle += 0.003f;
  723. /* Compute and set the matrix */
  724. m_mView = PVRTMat4::LookAtRH(vFrom, vTo, vUp);
  725. /* Remember the camera position to draw the Skybox around it */
  726. vCameraPosition = vFrom;
  727. }
  728. void OGLES2Skybox2::ChangeSkyboxTo(SEffect *pSEffect, GLuint ui32NewSkybox)
  729. {
  730. unsigned int i,i32Cnt;
  731. const SPVRTPFXTexture *psTex;
  732. psTex = pSEffect->pEffect->GetTextureArray(i32Cnt);
  733. for(i = 0; i < i32Cnt; ++i)
  734. {
  735. if(strcmp(g_aszTextureNames[3], psTex[i].p) == 0)
  736. {
  737. pSEffect->pEffect->SetTexture(i, ui32NewSkybox, PVRTEX_CUBEMAP);
  738. return;
  739. }
  740. }
  741. }
  742. /*******************************************************************************
  743. * Function Name : DrawSkybox
  744. * Description : Draws the Skybox
  745. *******************************************************************************/
  746. void OGLES2Skybox2::DrawSkybox()
  747. {
  748. // Use the loaded Skybox shader program
  749. m_pEffects[0].pEffect->Activate();
  750. int iVertexUniform = 0;
  751. for(unsigned int j = 0; j < m_pEffects[0].ui32UniformCount; ++j)
  752. {
  753. switch(m_pEffects[0].psUniforms[j].nSemantic)
  754. {
  755. case eUsPOSITION:
  756. {
  757. iVertexUniform = j;
  758. glEnableVertexAttribArray(m_pEffects[0].psUniforms[j].nLocation);
  759. }
  760. break;
  761. case eUsWORLDVIEWPROJECTION:
  762. {
  763. PVRTMat4 mTrans, mMVP;
  764. mTrans = PVRTMat4::Translation(-vCameraPosition.x, -vCameraPosition.y, -vCameraPosition.z);
  765. mMVP = m_mProjection * mTrans * m_mView;
  766. /* Passes the model-view-projection matrix (MVP) to the shader to transform the vertices */
  767. glUniformMatrix4fv(m_pEffects[0].psUniforms[j].nLocation, 1, GL_FALSE, mMVP.f);
  768. }
  769. break;
  770. case eUsTEXTURE:
  771. {
  772. // Set the sampler variable to the texture unit
  773. glUniform1i(m_pEffects[0].psUniforms[j].nLocation, m_pEffects[0].psUniforms[j].nIdx);
  774. }
  775. break;
  776. }
  777. }
  778. for (int i = 0; i < 6; i++)
  779. {
  780. // Set Data Pointers
  781. glVertexAttribPointer(m_pEffects[0].psUniforms[iVertexUniform].nLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VERTTYPE)*3, &g_SkyboxVertices[i*4*3]);
  782. // Draw
  783. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  784. }
  785. /* Disable States */
  786. glDisableVertexAttribArray(m_pEffects[0].psUniforms[iVertexUniform].nLocation);
  787. }
  788. /*!****************************************************************************
  789. @Function NewDemo
  790. @Return PVRShell* The demo supplied by the user
  791. @Description This function must be implemented by the user of the shell.
  792. The user should return its PVRShell object defining the
  793. behaviour of the application.
  794. ******************************************************************************/
  795. PVRShell* NewDemo()
  796. {
  797. return new OGLES2Skybox2();
  798. }
  799. /******************************************************************************
  800. End of file (OGLES2Skybox2.cpp)
  801. ******************************************************************************/