OGLES2LightMap.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /******************************************************************************
  2. @File OGLES2LightMap.cpp
  3. @Title LightMap
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independent
  7. @Description Shows how to project a shadow texture on a model which has a base
  8. and reflection texture.
  9. ******************************************************************************/
  10. #include "PVRShell.h"
  11. #include "OGLES2Tools.h"
  12. /******************************************************************************
  13. Constants
  14. ******************************************************************************/
  15. // Camera constants used to generate the projection matrix
  16. const float CAM_NEAR = 75.0f;
  17. const float CAM_FAR = 2000.0f;
  18. /******************************************************************************
  19. shader attributes
  20. ******************************************************************************/
  21. // vertex attributes
  22. enum EVertexAttrib {
  23. VERTEX_ARRAY, NORMAL_ARRAY, TEXCOORD_ARRAY, eNumAttribs };
  24. const char* g_aszAttribNames[] = {
  25. "inVertex", "inNormal", "inTexCoord" };
  26. // shader uniforms
  27. enum EUniform {
  28. eMVPMatrix, eShadowProj, eLightDirModel, eEyePosModel, eModelWorld, eNumUniforms };
  29. const char* g_aszUniformNames[] = {
  30. "MVPMatrix", "ShadowProj", "LightDirModel", "EyePosModel", "ModelWorld" };
  31. /******************************************************************************
  32. Content file names
  33. ******************************************************************************/
  34. // Source and binary shaders
  35. const char c_szFragShaderSrcFile[] = "FragShader.fsh";
  36. const char c_szFragShaderBinFile[] = "FragShader.fsc";
  37. const char c_szVertShaderSrcFile[] = "VertShader.vsh";
  38. const char c_szVertShaderBinFile[] = "VertShader.vsc";
  39. // PVR texture files
  40. const char c_szBaseTexFile[] = "Basetex.pvr";
  41. const char c_szReflectTexFile[] = "Reflection.pvr";
  42. const char c_szShadowTexFile[] = "Shadow.pvr";
  43. // POD scene files
  44. const char c_szMaskFile[] = "Mask.pod";
  45. const char c_szPlaneFile[] = "Plane.pod";
  46. /*!****************************************************************************
  47. Class encapsulating model data and methods
  48. ******************************************************************************/
  49. class CModel
  50. {
  51. protected:
  52. CPVRTModelPOD m_Scene;
  53. GLuint* m_puiVbo;
  54. GLuint* m_puiIndexVbo;
  55. public:
  56. CModel();
  57. ~CModel();
  58. bool ReadFromFile(const char* pszFilename);
  59. void LoadVbos();
  60. void DeleteVbos();
  61. void DrawMesh(int i32NodeIndex);
  62. };
  63. /*!****************************************************************************
  64. Class implementing the PVRShell functions.
  65. ******************************************************************************/
  66. class OGLES2LightMap : public PVRShell
  67. {
  68. // Print3D class used to display text
  69. CPVRTPrint3D m_Print3D;
  70. // 3D Models
  71. enum EModels {
  72. eMask, ePlane, eNumModels
  73. };
  74. CModel m_Models[eNumModels];
  75. // Projection and view matrices
  76. PVRTMat4 m_mProjection, m_mView;
  77. // The shadow projection matrix
  78. PVRTMat4 m_mShadowViewProj;
  79. // OpenGL handles for shaders and textures
  80. GLuint m_uiVertShader;
  81. GLuint m_uiFragShader;
  82. GLuint m_uiBaseTex;
  83. GLuint m_uiReflectTex;
  84. GLuint m_uiShadowTex;
  85. // Group shader programs and their uniform locations together
  86. struct
  87. {
  88. GLuint uiId;
  89. GLuint auiLoc[eNumUniforms];
  90. }
  91. m_ShaderProgram;
  92. // The Rotate parameter of Model
  93. float m_fAngleX;
  94. float m_fAngleY;
  95. public:
  96. virtual bool InitApplication();
  97. virtual bool InitView();
  98. virtual bool ReleaseView();
  99. virtual bool QuitApplication();
  100. virtual bool RenderScene();
  101. bool LoadTextures(CPVRTString* pErrorStr);
  102. bool LoadShaders(CPVRTString* pErrorStr);
  103. };
  104. /*!****************************************************************************
  105. @Function LoadTextures
  106. @Output pErrorStr A string describing the error on failure
  107. @Return bool true if no error occured
  108. @Description Loads the textures required for this training course
  109. ******************************************************************************/
  110. bool OGLES2LightMap::LoadTextures(CPVRTString* const pErrorStr)
  111. {
  112. if(PVRTTextureLoadFromPVR(c_szBaseTexFile, &m_uiBaseTex) != PVR_SUCCESS)
  113. {
  114. *pErrorStr = "ERROR: Failed to load texture.";
  115. return false;
  116. }
  117. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  118. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  119. if(PVRTTextureLoadFromPVR(c_szReflectTexFile, &m_uiReflectTex) != PVR_SUCCESS)
  120. {
  121. *pErrorStr = "ERROR: Failed to load texture.";
  122. return false;
  123. }
  124. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  125. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  126. if(PVRTTextureLoadFromPVR(c_szShadowTexFile, &m_uiShadowTex) != PVR_SUCCESS)
  127. {
  128. *pErrorStr = "ERROR: Failed to load texture.";
  129. return false;
  130. }
  131. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  132. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  133. return true;
  134. }
  135. /*!****************************************************************************
  136. @Function LoadShaders
  137. @Output pErrorStr A string describing the error on failure
  138. @Return bool true if no error occured
  139. @Description Loads and compiles the shaders and links the shader programs
  140. required for this training course
  141. ******************************************************************************/
  142. bool OGLES2LightMap::LoadShaders(CPVRTString* pErrorStr)
  143. {
  144. /*
  145. Load and compile the shaders from files.
  146. Binary shaders are tried first, source shaders
  147. are used as fallback.
  148. */
  149. if (PVRTShaderLoadFromFile(
  150. c_szVertShaderBinFile, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiVertShader, pErrorStr) != PVR_SUCCESS)
  151. {
  152. return false;
  153. }
  154. if (PVRTShaderLoadFromFile(
  155. c_szFragShaderBinFile, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiFragShader, pErrorStr) != PVR_SUCCESS)
  156. {
  157. return false;
  158. }
  159. /*
  160. Set up and link the shader program
  161. */
  162. if (PVRTCreateProgram(&m_ShaderProgram.uiId, m_uiVertShader, m_uiFragShader, g_aszAttribNames, eNumAttribs, pErrorStr))
  163. {
  164. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  165. return false;
  166. }
  167. // Store the location of uniforms for later use
  168. for (int i = 0; i < eNumUniforms; ++i)
  169. {
  170. m_ShaderProgram.auiLoc[i] = glGetUniformLocation(m_ShaderProgram.uiId, g_aszUniformNames[i]);
  171. }
  172. return true;
  173. }
  174. /*!****************************************************************************
  175. @Function InitApplication
  176. @Return bool true if no error occured
  177. @Description Code in InitApplication() will be called by PVRShell once per
  178. run, before the rendering context is created.
  179. Used to initialize variables that are not dependant on it
  180. (e.g. external modules, loading meshes, etc.)
  181. If the rendering context is lost, InitApplication() will
  182. not be called again.
  183. ******************************************************************************/
  184. bool OGLES2LightMap::InitApplication()
  185. {
  186. // Get and set the read path for content files
  187. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  188. // Load the scene files
  189. if(!m_Models[0].ReadFromFile(c_szMaskFile) ||
  190. !m_Models[1].ReadFromFile(c_szPlaneFile))
  191. {
  192. PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
  193. return false;
  194. }
  195. m_fAngleX = 0.0f;
  196. m_fAngleY = 0.0f;
  197. return true;
  198. }
  199. /*!****************************************************************************
  200. @Function QuitApplication
  201. @Return bool true if no error occured
  202. @Description Code in QuitApplication() will be called by PVRShell once per
  203. run, just before exiting the program.
  204. If the rendering context is lost, QuitApplication() will
  205. not be called.x
  206. ******************************************************************************/
  207. bool OGLES2LightMap::QuitApplication()
  208. {
  209. return true;
  210. }
  211. /*!****************************************************************************
  212. @Function InitView
  213. @Return bool true if no error occured
  214. @Description Code in InitView() will be called by PVRShell upon
  215. initialization or after a change in the rendering context.
  216. Used to initialize variables that are dependant on the rendering
  217. context (e.g. textures, vertex buffers, etc.)
  218. ******************************************************************************/
  219. bool OGLES2LightMap::InitView()
  220. {
  221. CPVRTString ErrorStr;
  222. /*
  223. Initialize VBO data
  224. */
  225. m_Models[0].LoadVbos();
  226. m_Models[1].LoadVbos();
  227. /*
  228. Load textures
  229. */
  230. if (!LoadTextures(&ErrorStr))
  231. {
  232. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  233. return false;
  234. }
  235. // Clamp the shadow texture to edge (not repeat).
  236. glBindTexture(GL_TEXTURE_2D, m_uiShadowTex);
  237. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  238. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  239. /*
  240. Load and compile the shaders & link programs
  241. */
  242. if (!LoadShaders(&ErrorStr))
  243. {
  244. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  245. return false;
  246. }
  247. // Set the sampler2D uniforms to corresponding texture units
  248. glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sBasetex"), 0);
  249. glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sReflect"), 1);
  250. glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sShadow"), 2);
  251. // Is the scene rotated?
  252. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  253. /*
  254. Initialize Print3D
  255. */
  256. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
  257. {
  258. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  259. return false;
  260. }
  261. /*
  262. Calculate the projection and view matrices
  263. */
  264. m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI/6, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), CAM_NEAR, CAM_FAR, PVRTMat4::OGL, bRotate);
  265. m_mView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, 150), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0));
  266. // Defines the shadow matrix and stores it, shadow matrix for shadow texture mapping
  267. PVRTVec3 vLightFrom = PVRTVec3( 85, -85, 100);
  268. PVRTVec3 vLightTo = PVRTVec3(0, 0, -25);
  269. PVRTVec3 vLightUp = PVRTVec3(0, 1, 0);
  270. m_mShadowViewProj = PVRTMat4::LookAtRH(vLightFrom, vLightTo, vLightUp);
  271. // Project the shadow from a point (near and far clipping plane are not important here)
  272. PVRTMat4 mShadowProj;
  273. mShadowProj = PVRTMat4::PerspectiveFovRH(PVRT_PI/6, 1, 1, 2, PVRTMat4::OGL);
  274. m_mShadowViewProj = mShadowProj * m_mShadowViewProj;
  275. glUniformMatrix4fv(m_ShaderProgram.auiLoc[eShadowProj], 1, GL_FALSE, m_mShadowViewProj.ptr());
  276. /*
  277. Set OpenGL ES render states needed for this training course
  278. */
  279. // Enable backface culling and depth test
  280. glCullFace(GL_BACK);
  281. glEnable(GL_CULL_FACE);
  282. glEnable(GL_DEPTH_TEST);
  283. glDepthFunc(GL_LEQUAL);
  284. // Use a nice bright blue as clear colour
  285. glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  286. return true;
  287. }
  288. /*!****************************************************************************
  289. @Function ReleaseView
  290. @Return bool true if no error occured
  291. @Description Code in ReleaseView() will be called by PVRShell when the
  292. application quits or before a change in the rendering context.
  293. ******************************************************************************/
  294. bool OGLES2LightMap::ReleaseView()
  295. {
  296. // Delete textures
  297. glDeleteTextures(1, &m_uiBaseTex);
  298. glDeleteTextures(1, &m_uiReflectTex);
  299. glDeleteTextures(1, &m_uiShadowTex);
  300. // Delete program and shader objects
  301. glDeleteProgram(m_ShaderProgram.uiId);
  302. glDeleteShader(m_uiVertShader);
  303. glDeleteShader(m_uiFragShader);
  304. // Delete buffer objects
  305. m_Models[0].DeleteVbos();
  306. m_Models[1].DeleteVbos();
  307. // Release Print3D Textures
  308. m_Print3D.ReleaseTextures();
  309. return true;
  310. }
  311. /*!****************************************************************************
  312. @Function RenderScene
  313. @Return bool true if no error occured
  314. @Description Main rendering loop function of the program. The shell will
  315. call this function every frame.
  316. eglSwapBuffers() will be performed by PVRShell automatically.
  317. PVRShell will also manage important OS events.
  318. Will also manage relevent OS events. The user has access to
  319. these events through an abstraction layer provided by PVRShell.
  320. ******************************************************************************/
  321. bool OGLES2LightMap::RenderScene()
  322. {
  323. // Clear the color and depth buffer
  324. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  325. // Use shader program
  326. glUseProgram(m_ShaderProgram.uiId);
  327. // Bind textures
  328. glActiveTexture(GL_TEXTURE0);
  329. glBindTexture(GL_TEXTURE_2D, m_uiBaseTex);
  330. glActiveTexture(GL_TEXTURE1);
  331. glBindTexture(GL_TEXTURE_2D, m_uiReflectTex);
  332. glActiveTexture(GL_TEXTURE2);
  333. glBindTexture(GL_TEXTURE_2D, m_uiShadowTex);
  334. // draw two models, mask and plane
  335. for (int i = 0; i < eNumModels; ++i)
  336. {
  337. // rotate and translate the model matrix
  338. PVRTMat4 mModel;
  339. if (i == eMask)
  340. {
  341. PVRTMat4 mRotX, mRotY;
  342. mRotX = PVRTMat4::RotationX(m_fAngleX);
  343. m_fAngleX += PVRT_PI / 300;
  344. mRotY = PVRTMat4::RotationY(m_fAngleY);
  345. m_fAngleY += PVRT_PI / 250;
  346. mModel = mRotY * mRotX;
  347. }
  348. else
  349. {
  350. mModel = PVRTMat4::Translation(0.0, 0.0, -25);
  351. }
  352. // Set model view projection matrix
  353. PVRTMat4 mModelView, mMVP;
  354. mModelView = m_mView * mModel;
  355. mMVP = m_mProjection * mModelView;
  356. glUniformMatrix4fv(m_ShaderProgram.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.ptr());
  357. // Set shadow projection matrix
  358. PVRTMat4 mShadowProj;
  359. mShadowProj = m_mShadowViewProj * mModel;
  360. glUniformMatrix4fv(m_ShaderProgram.auiLoc[eShadowProj], 1, GL_FALSE, mShadowProj.ptr());
  361. // Set model world matrix
  362. PVRTMat3 fModelWorld = PVRTMat3(mModel);
  363. glUniformMatrix3fv(m_ShaderProgram.auiLoc[eModelWorld], 1, GL_FALSE, fModelWorld.ptr());
  364. // Set light position in model space
  365. PVRTVec4 vLightDirModel;
  366. vLightDirModel = mModel.inverse() * PVRTVec4( 1, 1, 1, 0 );
  367. glUniform3fv(m_ShaderProgram.auiLoc[eLightDirModel], 1, &vLightDirModel.x);
  368. // Set eye position in model space
  369. PVRTVec4 vEyePosModel;
  370. vEyePosModel = mModelView.inverse() * PVRTVec4(0, 0, 0, 1);
  371. glUniform3fv(m_ShaderProgram.auiLoc[eEyePosModel], 1, &vEyePosModel.x);
  372. m_Models[i].DrawMesh(0);
  373. }
  374. // Displays the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
  375. m_Print3D.DisplayDefaultTitle("LightMap", "", ePVRTPrint3DLogoIMG);
  376. m_Print3D.Flush();
  377. return true;
  378. }
  379. /*!****************************************************************************
  380. @Function CModel
  381. @Description Constructor
  382. ******************************************************************************/
  383. CModel::CModel() : m_puiVbo(0), m_puiIndexVbo(0)
  384. {}
  385. /*!****************************************************************************
  386. @Function ~CModel
  387. @Description Destructor
  388. ******************************************************************************/
  389. CModel::~CModel()
  390. {
  391. m_Scene.Destroy();
  392. }
  393. /*!****************************************************************************
  394. @Function ReadFromFile
  395. @Input pszFilename filename of file to read
  396. @Return bool true if no error occured
  397. @Description Loads POD file
  398. ******************************************************************************/
  399. bool CModel::ReadFromFile(const char* const pszFilename)
  400. {
  401. return m_Scene.ReadFromFile(pszFilename) == PVR_SUCCESS;
  402. }
  403. /*!****************************************************************************
  404. @Function LoadVbos
  405. @Description Loads data from model into vertex buffer objects
  406. ******************************************************************************/
  407. void CModel::LoadVbos()
  408. {
  409. if (!m_puiVbo) m_puiVbo = new GLuint[m_Scene.nNumMesh];
  410. if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];
  411. /*
  412. Load vertex data of all meshes in the scene into VBOs
  413. The meshes have been exported with the "Interleave Vectors" option,
  414. so all data is interleaved in the buffer at pMesh->pInterleaved.
  415. Interleaving data improves the memory access pattern and cache efficiency,
  416. thus it can be read faster by the hardware.
  417. */
  418. glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
  419. for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
  420. {
  421. // Load vertex data into buffer object
  422. SPODMesh& Mesh = m_Scene.pMesh[i];
  423. unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
  424. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
  425. glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
  426. // Load index data into buffer object if available
  427. m_puiIndexVbo[i] = 0;
  428. if (Mesh.sFaces.pData)
  429. {
  430. glGenBuffers(1, &m_puiIndexVbo[i]);
  431. uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
  432. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
  433. glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
  434. }
  435. }
  436. glBindBuffer(GL_ARRAY_BUFFER, 0);
  437. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  438. }
  439. /*!****************************************************************************
  440. @Function DeleteVbos
  441. @Description Deletes vertex buffer objects for model
  442. ******************************************************************************/
  443. void CModel::DeleteVbos()
  444. {
  445. // Delete buffer objects
  446. glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo);
  447. glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo);
  448. delete [] m_puiVbo;
  449. delete [] m_puiIndexVbo;
  450. m_puiVbo = 0;
  451. m_puiIndexVbo = 0;
  452. }
  453. /*!****************************************************************************
  454. @Function DrawMesh
  455. @Input i32NodeIndex Node index of the mesh to draw
  456. @Description Draws a SPODMesh after the model view matrix has been set and
  457. the meterial prepared.
  458. ******************************************************************************/
  459. void CModel::DrawMesh(int i32NodeIndex)
  460. {
  461. int i32MeshIndex = m_Scene.pNode[i32NodeIndex].nIdx;
  462. SPODMesh* pMesh = &m_Scene.pMesh[i32MeshIndex];
  463. // bind the VBO for the mesh
  464. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i32MeshIndex]);
  465. // bind the index buffer, won't hurt if the handle is 0
  466. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i32MeshIndex]);
  467. // Enable the vertex attribute arrays
  468. for (int i = 0; i < eNumAttribs; ++i) glEnableVertexAttribArray(i);
  469. // Set the vertex attribute offsets
  470. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
  471. glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
  472. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
  473. /*
  474. The geometry can be exported in 4 ways:
  475. - Indexed Triangle list
  476. - Non-Indexed Triangle list
  477. - Indexed Triangle strips
  478. - Non-Indexed Triangle strips
  479. */
  480. if(pMesh->nNumStrips == 0)
  481. {
  482. if(m_puiIndexVbo[i32MeshIndex])
  483. {
  484. // Indexed Triangle list
  485. glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
  486. }
  487. else
  488. {
  489. // Non-Indexed Triangle list
  490. glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
  491. }
  492. }
  493. else
  494. {
  495. int offset = 0;
  496. for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
  497. {
  498. if(m_puiIndexVbo[i32MeshIndex])
  499. {
  500. // Indexed Triangle strips
  501. glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, &((GLshort*)0)[offset]);
  502. }
  503. else
  504. {
  505. // Non-Indexed Triangle strips
  506. glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
  507. }
  508. offset += pMesh->pnStripLength[i]+2;
  509. }
  510. }
  511. // Safely disable the vertex attribute arrays
  512. for (int i = 0; i < eNumAttribs; ++i) glDisableVertexAttribArray(i);
  513. glBindBuffer(GL_ARRAY_BUFFER, 0);
  514. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  515. }
  516. /*!****************************************************************************
  517. @Function NewDemo
  518. @Return PVRShell* The demo supplied by the user
  519. @Description This function must be implemented by the user of the shell.
  520. The user should return its PVRShell object defining the
  521. behaviour of the application.
  522. ******************************************************************************/
  523. PVRShell* NewDemo()
  524. {
  525. return new OGLES2LightMap();
  526. }
  527. /******************************************************************************
  528. End of file (OGLES2LightMap.cpp)
  529. ******************************************************************************/