1 /******************************************************************************
2
3 @File OGLES2DisplacementMap.cpp
4
5 @Title Displacement Map
6
7 @Version
8
9 @Copyright Copyright (c) Imagination Technologies Limited.
10
11 @Platform Independent
12
13 @Description Shows how to displace geometry in the vertex shader using a
14 texture.
15
16 ******************************************************************************/
17 #include <string.h>
18
19 #include "PVRShell.h"
20 #include "OGLES2Tools.h"
21
22 /******************************************************************************
23 Defines
24 ******************************************************************************/
25 // Index to bind the attributes to vertex shaders
26 #define VERTEX_ARRAY 0
27 #define NORMAL_ARRAY 1
28 #define TEXCOORD_ARRAY 2
29
30 /******************************************************************************
31 Consts
32 ******************************************************************************/
33 // Camera constants. Used for making the projection matrix
34 const float g_fCameraNear = 4.0f;
35 const float g_fCameraFar = 2000.0f;
36
37 const float g_fDemoFrameRate = 1.0f / 90.0f;
38
39 // The camera to use from the pod file
40 const int g_ui32Camera = 0;
41
42 /******************************************************************************
43 Content file names
44 ******************************************************************************/
45
46 // Source and binary shaders
47 const char c_szFragShaderSrcFile[] = "FragShader.fsh";
48 const char c_szFragShaderBinFile[] = "FragShader.fsc";
49 const char c_szVertShaderSrcFile[] = "VertShader.vsh";
50 const char c_szVertShaderBinFile[] = "VertShader.vsc";
51
52 // POD scene files
53 const char c_szSceneFile[] = "DisMapScene.pod";
54 const char c_szDisMapFile[] = "DisMap.pvr";
55
56 /*!****************************************************************************
57 Class implementing the PVRShell functions.
58 ******************************************************************************/
59 class OGLES2DisplacementMap : public PVRShell
60 {
61 // Print3D class used to display text
62 CPVRTPrint3D m_Print3D;
63
64 // 3D Model
65 CPVRTModelPOD m_Scene;
66
67 // OpenGL handles for shaders, textures and VBOs
68 GLuint m_uiVertShader;
69 GLuint m_uiFragShader;
70 GLuint* m_puiVbo;
71 GLuint* m_puiIndexVbo;
72 GLuint* m_puiTextureIDs;
73 GLuint m_uiDisMapID;
74
75 // Group shader programs and their uniform locations together
76 struct
77 {
78 GLuint uiId;
79 GLuint uiMVPMatrixLoc;
80 GLuint uiLightDirLoc;
81 GLuint uiTexture;
82 GLuint uiDisMap;
83 GLuint uiDisplacementFactor;
84 }
85 m_ShaderProgram;
86
87 // Variables to handle the animation in a time-based manner
88 unsigned long m_ulTimePrev;
89
90 // App variables
91 PVRTVec4 m_LightDir;
92 PVRTMat4 m_View, m_Projection;
93 float m_DisplacementFactor;
94 bool m_bGrow;
95
96 public:
97 virtual bool InitApplication();
98 virtual bool InitView();
99 virtual bool ReleaseView();
100 virtual bool QuitApplication();
101 virtual bool RenderScene();
102
103 OGLES2DisplacementMap();
104 bool LoadTextures(CPVRTString* pErrorStr);
105 bool LoadShaders(CPVRTString* pErrorStr);
106 bool LoadVbos(CPVRTString* pErrorStr);
107
108 void DrawMesh(int i32NodeIndex);
109 };
110
111 /*!****************************************************************************
112 @Function OGLES2DisplacementMap
113 @Description Constructor
114 ******************************************************************************/
OGLES2DisplacementMap()115 OGLES2DisplacementMap::OGLES2DisplacementMap() : m_puiVbo(0),
116 m_puiIndexVbo(0),
117 m_puiTextureIDs(0),
118 m_ulTimePrev(0),
119 m_DisplacementFactor(0),
120 m_bGrow(false)
121 {
122 }
123
124 /*!****************************************************************************
125 @Function LoadTextures
126 @Return bool true if no error occurred
127 @Description Loads the textures required for this training course
128 ******************************************************************************/
LoadTextures(CPVRTString * pErrorStr)129 bool OGLES2DisplacementMap::LoadTextures(CPVRTString* pErrorStr)
130 {
131 /*
132 Load the textures.
133 For a more detailed explanation, see Texturing and IntroducingPVRTools
134 */
135
136 /*
137 Initialises an array to lookup the textures
138 for each material in the scene.
139 */
140 m_puiTextureIDs = new GLuint[m_Scene.nNumMaterial];
141
142 if(!m_puiTextureIDs)
143 {
144 *pErrorStr = "ERROR: Insufficient memory.";
145 return false;
146 }
147
148 for(int i = 0; i < (int) m_Scene.nNumMaterial; ++i)
149 {
150 m_puiTextureIDs[i] = 0;
151 SPODMaterial* pMaterial = &m_Scene.pMaterial[i];
152
153 if(pMaterial->nIdxTexDiffuse != -1)
154 {
155 /*
156 Using the tools function PVRTTextureLoadFromPVR load the textures required by the pod file.
157
158 Note: This function only loads .pvr files. You can set the textures in 3D Studio Max to .pvr
159 files using the PVRTexTool plug-in for max. Alternatively, the pod material properties can be
160 modified in PVRShaman.
161 */
162
163 CPVRTString sTextureName = m_Scene.pTexture[pMaterial->nIdxTexDiffuse].pszName;
164
165 if(PVRTTextureLoadFromPVR(sTextureName.c_str(), &m_puiTextureIDs[i]) != PVR_SUCCESS)
166 {
167 *pErrorStr = "ERROR: Failed to load " + sTextureName + ".";
168
169 // Check to see if we're trying to load .pvr or not
170 CPVRTString sFileExtension = PVRTStringGetFileExtension(sTextureName);
171
172 if(sFileExtension.toLower() == "pvr")
173 *pErrorStr += "Note: Can only load pvr files.";
174
175 return false;
176 }
177 }
178 }
179
180 // Load the texture used for the displacement map
181 if(PVRTTextureLoadFromPVR(c_szDisMapFile, &m_uiDisMapID) != PVR_SUCCESS)
182 {
183 *pErrorStr = "ERROR: Failed to load " + CPVRTString(c_szDisMapFile) + ".";
184 return false;
185 }
186
187 // Define the wrapping to use for the displacement map
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
190
191 return true;
192 }
193
194 /*!****************************************************************************
195 @Function LoadShaders
196 @Output pErrorStr A string describing the error on failure
197 @Return bool true if no error occurred
198 @Description Loads and compiles the shaders and links the shader programs
199 required for this training course
200 ******************************************************************************/
LoadShaders(CPVRTString * pErrorStr)201 bool OGLES2DisplacementMap::LoadShaders(CPVRTString* pErrorStr)
202 {
203 /*
204 Load and compile the shaders from files.
205 Binary shaders are tried first, source shaders
206 are used as fallback.
207 */
208 if(PVRTShaderLoadFromFile(
209 c_szVertShaderBinFile, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiVertShader, pErrorStr) != PVR_SUCCESS)
210 {
211 return false;
212 }
213
214 if (PVRTShaderLoadFromFile(
215 c_szFragShaderBinFile, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiFragShader, pErrorStr) != PVR_SUCCESS)
216 {
217 return false;
218 }
219
220 /*
221 Set up and link the shader program
222 */
223 const char* aszAttribs[] = { "inVertex", "inNormal", "inTexCoord" };
224
225 if(PVRTCreateProgram(
226 &m_ShaderProgram.uiId, m_uiVertShader, m_uiFragShader, aszAttribs, 3, pErrorStr) != PVR_SUCCESS)
227 {
228 PVRShellSet(prefExitMessage, pErrorStr->c_str());
229 return false;
230 }
231
232 // Store the location of uniforms for later use
233 m_ShaderProgram.uiMVPMatrixLoc = glGetUniformLocation(m_ShaderProgram.uiId, "MVPMatrix");
234 m_ShaderProgram.uiLightDirLoc = glGetUniformLocation(m_ShaderProgram.uiId, "LightDirection");
235 m_ShaderProgram.uiDisplacementFactor = glGetUniformLocation(m_ShaderProgram.uiId, "DisplacementFactor");
236
237 m_ShaderProgram.uiTexture = glGetUniformLocation(m_ShaderProgram.uiId, "sTexture");
238 m_ShaderProgram.uiDisMap = glGetUniformLocation(m_ShaderProgram.uiId, "sDisMap");
239
240 return true;
241 }
242
243 /*!****************************************************************************
244 @Function LoadVbos
245 @Description Loads the mesh data required for this training course into
246 vertex buffer objects
247 ******************************************************************************/
LoadVbos(CPVRTString * pErrorStr)248 bool OGLES2DisplacementMap::LoadVbos(CPVRTString* pErrorStr)
249 {
250 if(!m_Scene.pMesh[0].pInterleaved)
251 {
252 *pErrorStr = "ERROR: IntroducingPOD requires the pod data to be interleaved. Please re-export with the interleaved option enabled.";
253 return false;
254 }
255
256 if (!m_puiVbo) m_puiVbo = new GLuint[m_Scene.nNumMesh];
257 if (!m_puiIndexVbo) m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];
258
259 /*
260 Load vertex data of all meshes in the scene into VBOs
261
262 The meshes have been exported with the "Interleave Vectors" option,
263 so all data is interleaved in the buffer at pMesh->pInterleaved.
264 Interleaving data improves the memory access pattern and cache efficiency,
265 thus it can be read faster by the hardware.
266 */
267 glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
268 for (unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
269 {
270 // Load vertex data into buffer object
271 SPODMesh& Mesh = m_Scene.pMesh[i];
272 unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
273 glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
274 glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
275
276 // Load index data into buffer object if available
277 m_puiIndexVbo[i] = 0;
278 if (Mesh.sFaces.pData)
279 {
280 glGenBuffers(1, &m_puiIndexVbo[i]);
281 uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
282 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
283 glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
284 }
285 }
286 glBindBuffer(GL_ARRAY_BUFFER, 0);
287 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
288
289 return true;
290 }
291
292 /*!****************************************************************************
293 @Function InitApplication
294 @Return bool true if no error occurred
295 @Description Code in InitApplication() will be called by PVRShell once per
296 run, before the rendering context is created.
297 Used to initialize variables that are not dependent on it
298 (e.g. external modules, loading meshes, etc.)
299 If the rendering context is lost, InitApplication() will
300 not be called again.
301 ******************************************************************************/
InitApplication()302 bool OGLES2DisplacementMap::InitApplication()
303 {
304 // Get and set the read path for content files
305 CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
306
307 // Get and set the load/release functions for loading external files.
308 // In the majority of cases the PVRShell will return NULL function pointers implying that
309 // nothing special is required to load external files.
310 CPVRTResourceFile::SetLoadReleaseFunctions(PVRShellGet(prefLoadFileFunc), PVRShellGet(prefReleaseFileFunc));
311
312 // Load the scene
313 if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
314 {
315 PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
316 return false;
317 }
318
319 // The cameras are stored in the file. We check it contains at least one.
320 if(m_Scene.nNumCamera == 0)
321 {
322 PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a camera. Please add one and re-export.\n");
323 return false;
324 }
325
326 // We also check that the scene contains at least one light
327 if(m_Scene.nNumLight == 0)
328 {
329 PVRShellSet(prefExitMessage, "ERROR: The scene does not contain a light. Please add one and re-export.\n");
330 return false;
331 }
332
333 return true;
334 }
335
336 /*!****************************************************************************
337 @Function QuitApplication
338 @Return bool true if no error occurred
339 @Description Code in QuitApplication() will be called by PVRShell once per
340 run, just before exiting the program.
341 If the rendering context is lost, QuitApplication() will
342 not be called.
343 ******************************************************************************/
QuitApplication()344 bool OGLES2DisplacementMap::QuitApplication()
345 {
346 // Free the memory allocated for the scene
347 m_Scene.Destroy();
348
349 delete[] m_puiVbo;
350 delete[] m_puiIndexVbo;
351
352 return true;
353 }
354
355 /*!****************************************************************************
356 @Function InitView
357 @Return bool true if no error occurred
358 @Description Code in InitView() will be called by PVRShell upon
359 initialization or after a change in the rendering context.
360 Used to initialize variables that are dependent on the rendering
361 context (e.g. textures, vertex buffers, etc.)
362 ******************************************************************************/
InitView()363 bool OGLES2DisplacementMap::InitView()
364 {
365 CPVRTString ErrorStr;
366
367 /*
368 Initialize VBO data
369 */
370 if(!LoadVbos(&ErrorStr))
371 {
372 PVRShellSet(prefExitMessage, ErrorStr.c_str());
373 return false;
374 }
375
376 /*
377 Load textures
378 */
379 if(!LoadTextures(&ErrorStr))
380 {
381 PVRShellSet(prefExitMessage, ErrorStr.c_str());
382 return false;
383 }
384
385 /*
386 Load and compile the shaders & link programs
387 */
388 if(!LoadShaders(&ErrorStr))
389 {
390 PVRShellSet(prefExitMessage, ErrorStr.c_str());
391 return false;
392 }
393
394 /*
395 Initialize Print3D
396 */
397 bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
398
399 if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
400 {
401 PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
402 return false;
403 }
404
405 /*
406 Set OpenGL ES render states needed for this training course
407 */
408 // Enable backface culling and depth test
409 glCullFace(GL_BACK);
410 glEnable(GL_CULL_FACE);
411
412 glEnable(GL_DEPTH_TEST);
413
414 // Use a nice bright blue as clear colour
415 glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
416
417 //Get the direction of the first light from the scene.
418 m_LightDir = m_Scene.GetLightDirection(0);
419
420 // For direction vectors, w should be 0
421 m_LightDir.w = 0.0f;
422
423
424 // Set up the view and projection matrices from the camera
425 PVRTVec3 vFrom, vTo(0.0f), vUp(0.0f, 1.0f, 0.0f);
426 float fFOV;
427
428 // Setup the camera
429
430 // Camera nodes are after the mesh and light nodes in the array
431 int i32CamID = m_Scene.pNode[m_Scene.nNumMeshNode + m_Scene.nNumLight + g_ui32Camera].nIdx;
432
433 // Get the camera position, target and field of view (fov)
434 if(m_Scene.pCamera[i32CamID].nIdxTarget != -1) // Does the camera have a target?
435 fFOV = m_Scene.GetCameraPos( vFrom, vTo, g_ui32Camera); // vTo is taken from the target node
436 else
437 fFOV = m_Scene.GetCamera( vFrom, vTo, vUp, g_ui32Camera); // vTo is calculated from the rotation
438
439 // We can build the model view matrix from the camera position, target and an up vector.
440 // For this we usePVRTMat4LookAtRH()
441 m_View = PVRTMat4::LookAtRH(vFrom, vTo, vUp);
442
443 // Calculate the projection matrix
444 m_Projection = PVRTMat4::PerspectiveFovRH(fFOV, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate);
445
446 // Initialize variables used for the animation
447 m_ulTimePrev = PVRShellGetTime();
448
449 return true;
450 }
451
452 /*!****************************************************************************
453 @Function ReleaseView
454 @Return bool true if no error occurred
455 @Description Code in ReleaseView() will be called by PVRShell when the
456 application quits or before a change in the rendering context.
457 ******************************************************************************/
ReleaseView()458 bool OGLES2DisplacementMap::ReleaseView()
459 {
460 // Deletes the textures
461 glDeleteTextures(m_Scene.nNumMaterial, &m_puiTextureIDs[0]);
462 glDeleteTextures(1, &m_uiDisMapID);
463
464 // Frees the texture lookup array
465 delete[] m_puiTextureIDs;
466 m_puiTextureIDs = 0;
467
468 // Delete program and shader objects
469 glDeleteProgram(m_ShaderProgram.uiId);
470
471 glDeleteShader(m_uiVertShader);
472 glDeleteShader(m_uiFragShader);
473
474 // Delete buffer objects
475 glDeleteBuffers(m_Scene.nNumMesh, m_puiVbo);
476 glDeleteBuffers(m_Scene.nNumMesh, m_puiIndexVbo);
477
478 // Release Print3D Textures
479 m_Print3D.ReleaseTextures();
480
481 return true;
482 }
483
484 /*!****************************************************************************
485 @Function RenderScene
486 @Return bool true if no error occurred
487 @Description Main rendering loop function of the program. The shell will
488 call this function every frame.
489 eglSwapBuffers() will be performed by PVRShell automatically.
490 PVRShell will also manage important OS events.
491 Will also manage relevant OS events. The user has access to
492 these events through an abstraction layer provided by PVRShell.
493 ******************************************************************************/
RenderScene()494 bool OGLES2DisplacementMap::RenderScene()
495 {
496 // Clear the color and depth buffer
497 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
498
499
500 // Calculates the the time since the last frame
501 unsigned long ulTime = PVRShellGetTime();
502 unsigned long ulDeltaTime = ulTime - m_ulTimePrev;
503 m_ulTimePrev = ulTime;
504
505 // Use shader program
506 glUseProgram(m_ShaderProgram.uiId);
507
508 // Enable 2D texturing for the first texture.
509 glActiveTexture(GL_TEXTURE0);
510
511 // Set the sampler2D variable to the first texture unit
512 glUniform1i(m_ShaderProgram.uiTexture, 0);
513
514 // Enable 2D texturing for the second texture.
515 glActiveTexture(GL_TEXTURE1);
516
517 // Set the displacement map variable to the second texture unit
518 glUniform1i(m_ShaderProgram.uiDisMap, 1);
519
520 // Calculate and set the displacement factor
521 if(m_bGrow)
522 {
523 m_DisplacementFactor += (float)ulDeltaTime * g_fDemoFrameRate;
524
525 if(m_DisplacementFactor > 25.0f)
526 {
527 m_bGrow = false;
528 m_DisplacementFactor = 25.0f;
529 }
530 }
531 else
532 {
533 m_DisplacementFactor -= (float)ulDeltaTime * g_fDemoFrameRate;
534
535 if(m_DisplacementFactor < 0.0f)
536 {
537 m_bGrow = true;
538 m_DisplacementFactor = 0.0f;
539 }
540 }
541
542 glUniform1f(m_ShaderProgram.uiDisplacementFactor, m_DisplacementFactor);
543
544 // Bind the displacement map texture
545 glBindTexture(GL_TEXTURE_2D, m_uiDisMapID);
546
547 // Now the displacement map texture is bound set the active texture to texture 0
548 glActiveTexture(GL_TEXTURE0);
549
550 // Draw the scene
551
552 // Enable the vertex attribute arrays
553 glEnableVertexAttribArray(VERTEX_ARRAY);
554 glEnableVertexAttribArray(NORMAL_ARRAY);
555 glEnableVertexAttribArray(TEXCOORD_ARRAY);
556
557 for(unsigned int i = 0; i < m_Scene.nNumMeshNode; ++i)
558 {
559 SPODNode& Node = m_Scene.pNode[i];
560
561 // Get the node model matrix
562 PVRTMat4 mWorld;
563 mWorld = m_Scene.GetWorldMatrix(Node);
564
565 // Pass the model-view-projection matrix (MVP) to the shader to transform the vertices
566 PVRTMat4 mModelView, mMVP;
567 mModelView = m_View * mWorld;
568 mMVP = m_Projection * mModelView;
569 glUniformMatrix4fv(m_ShaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.f);
570
571 // Pass the light direction in model space to the shader
572 PVRTVec4 vLightDir;
573 vLightDir = mWorld.inverse() * m_LightDir;
574
575 PVRTVec3 vLightDirModel = *(PVRTVec3*) vLightDir.ptr();
576 vLightDirModel.normalize();
577
578 glUniform3fv(m_ShaderProgram.uiLightDirLoc, 1, &vLightDirModel.x);
579
580 // Load the correct texture for the mesh using our texture lookup table
581 GLuint uiTex = 0;
582
583 if(Node.nIdxMaterial != -1)
584 uiTex = m_puiTextureIDs[Node.nIdxMaterial];
585
586 glBindTexture(GL_TEXTURE_2D, uiTex);
587
588 /*
589 Now that the model-view matrix is set and the materials ready,
590 call another function to actually draw the mesh.
591 */
592 DrawMesh(i);
593 }
594
595 // Safely disable the vertex attribute arrays
596 glDisableVertexAttribArray(VERTEX_ARRAY);
597 glDisableVertexAttribArray(NORMAL_ARRAY);
598 glDisableVertexAttribArray(TEXCOORD_ARRAY);
599
600 glBindBuffer(GL_ARRAY_BUFFER, 0);
601 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
602
603 // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
604 m_Print3D.DisplayDefaultTitle("DisplacementMapping", "", ePVRTPrint3DSDKLogo);
605 m_Print3D.Flush();
606
607 return true;
608 }
609
610 /*!****************************************************************************
611 @Function DrawMesh
612 @Input i32NodeIndex Node index of the mesh to draw
613 @Description Draws a SPODMesh after the model view matrix has been set and
614 the material prepared.
615 ******************************************************************************/
DrawMesh(int i32NodeIndex)616 void OGLES2DisplacementMap::DrawMesh(int i32NodeIndex)
617 {
618 int i32MeshIndex = m_Scene.pNode[i32NodeIndex].nIdx;
619 SPODMesh* pMesh = &m_Scene.pMesh[i32MeshIndex];
620
621 // bind the VBO for the mesh
622 glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i32MeshIndex]);
623 // bind the index buffer, won't hurt if the handle is 0
624 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i32MeshIndex]);
625
626 // Set the vertex attribute offsets
627 glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
628 glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
629 glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
630
631 /*
632 The geometry can be exported in 4 ways:
633 - Indexed Triangle list
634 - Non-Indexed Triangle list
635 - Indexed Triangle strips
636 - Non-Indexed Triangle strips
637 */
638 if(pMesh->nNumStrips == 0)
639 {
640 if(m_puiIndexVbo[i32MeshIndex])
641 {
642 // Indexed Triangle list
643 glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
644 }
645 else
646 {
647 // Non-Indexed Triangle list
648 glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
649 }
650 }
651 else
652 {
653 int offset = 0;
654
655 for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
656 {
657 if(m_puiIndexVbo[i32MeshIndex])
658 {
659 // Indexed Triangle strips
660 glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, &((GLshort*)0)[offset]);
661 }
662 else
663 {
664 // Non-Indexed Triangle strips
665 glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
666 }
667 offset += pMesh->pnStripLength[i]+2;
668 }
669 }
670 }
671
672 /*!****************************************************************************
673 @Function NewDemo
674 @Return PVRShell* The demo supplied by the user
675 @Description This function must be implemented by the user of the shell.
676 The user should return its PVRShell object defining the
677 behaviour of the application.
678 ******************************************************************************/
NewDemo()679 PVRShell* NewDemo()
680 {
681 return new OGLES2DisplacementMap();
682 }
683
684 /******************************************************************************
685 End of file (OGLES2DisplacementMap.cpp)
686 ******************************************************************************/
687
688