OGLES2RenderToTexture.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. /******************************************************************************
  2. @File OGLES2RenderToTexture.cpp
  3. @Title RenderToTexture
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independant
  7. @Description Shows how to render to a pBuffer surface or FBO and bind that to a
  8. texture.
  9. ******************************************************************************/
  10. #include "PVRShell.h"
  11. #include "OGLES2Tools.h"
  12. /******************************************************************************
  13. Content file names
  14. ******************************************************************************/
  15. // Source and binary shaders
  16. const char c_szFragShaderSrcFile[] = "FragShader.fsh";
  17. const char c_szFragShaderBinFile[] = "FragShader.fsc";
  18. const char c_szVertShaderSrcFile[] = "VertShader.vsh";
  19. const char c_szVertShaderBinFile[] = "VertShader.vsc";
  20. // Scene
  21. /*
  22. The .pod file was exported from 3DSMax using PVRGeoPOD.
  23. */
  24. const char c_szSceneFile[] = "RenderToTexture.pod";
  25. const char c_szMaskTex[] = "YellowWood.pvr";
  26. /******************************************************************************
  27. Defines
  28. ******************************************************************************/
  29. /******************************************************************************
  30. Consts
  31. ******************************************************************************/
  32. // Camera constants. Used for making the projection matrix
  33. const float g_fCameraNear = 4.0f;
  34. const float g_fCameraFar = 500.0f;
  35. /******************************************************************************
  36. shader attributes
  37. ******************************************************************************/
  38. // vertex attributes
  39. enum EVertexAttrib {
  40. eVERTEX_ARRAY, eNORMAL_ARRAY, eTEXCOORD_ARRAY, eNumAttribs };
  41. const char* g_aszAttribNames[] = {
  42. "inVertex", "inNormal", "inTexCoord" };
  43. // shader uniforms
  44. enum EUniform {
  45. eMVPMatrix, eLightDirection, eNumUniforms };
  46. const char* g_aszUniformNames[] = {
  47. "MVPMatrix", "LightDirection" };
  48. /*****************************************************************************
  49. Class implementing the PVRShell functions.
  50. ******************************************************************************/
  51. class OGLES2RenderToTexture : public PVRShell
  52. {
  53. // Print3D class used to display text
  54. CPVRTPrint3D m_Print3D;
  55. // Vertex Buffer Object (VBO) handles
  56. GLuint* m_puiVbo;
  57. GLuint* m_puiIndexVbo;
  58. // 3D Model
  59. CPVRTModelPOD m_Scene;
  60. // Projection and Model View matrices
  61. PVRTMat4 m_mProjection, m_mView;
  62. PVRTMat4 m_mR2TProjection, m_mR2TView;
  63. // Texture IDs used by the app
  64. GLuint m_uiTextureID;
  65. GLuint m_uiTextureToRenderTo;
  66. // Handles for our shaders
  67. GLuint m_uiVertShader;
  68. GLuint m_uiFragShader;
  69. // Group shader programs and their uniform locations together
  70. struct
  71. {
  72. GLuint uiId;
  73. GLuint auiLoc[eNumUniforms];
  74. }
  75. m_ShaderProgram;
  76. // Variables used for the animation
  77. float m_fAngleY;
  78. // App Variables
  79. int m_i32TexSize;
  80. // Render contexts, etc
  81. GLint m_i32OriginalFbo;
  82. // Handle for our FBO and the depth buffer that it requires
  83. GLuint m_uFBO;
  84. GLuint m_uDepthBuffer;
  85. // Extensions
  86. CPVRTgles2Ext m_Extensions;
  87. // Discard the frame buffer attachments
  88. bool m_bDiscard;
  89. public:
  90. OGLES2RenderToTexture() : m_puiVbo(0),
  91. m_puiIndexVbo(0),
  92. m_uiTextureID(0),
  93. m_uiTextureToRenderTo(0),
  94. m_fAngleY(0),
  95. m_i32OriginalFbo(0)
  96. {
  97. }
  98. // PVRShell functions
  99. virtual bool InitApplication();
  100. virtual bool InitView();
  101. virtual bool ReleaseView();
  102. virtual bool QuitApplication();
  103. virtual bool RenderScene();
  104. bool LoadVbos(CPVRTString* pErrorStr);
  105. void DrawMesh(unsigned int ui32MeshID);
  106. bool LoadTextures(CPVRTString* pErrorStr);
  107. bool LoadShaders(CPVRTString* pErrorStr);
  108. bool CreateFBO();
  109. };
  110. /*!****************************************************************************
  111. @Function InitApplication
  112. @Return bool true if no error occured
  113. @Description Code in InitApplication() will be called by PVRShell once per
  114. run, before the rendering context is created.
  115. Used to initialize variables that are not dependant on it
  116. (e.g. external modules, loading meshes, etc.)
  117. If the rendering context is lost, InitApplication() will
  118. not be called again.
  119. ******************************************************************************/
  120. bool OGLES2RenderToTexture::InitApplication()
  121. {
  122. // Get and set the read path for content files
  123. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  124. /*
  125. Loads the scene from the .pod file into a CPVRTModelPOD object.
  126. We could also export the scene as a header file and
  127. load it with ReadFromMemory().
  128. */
  129. if(m_Scene.ReadFromFile(c_szSceneFile) != PVR_SUCCESS)
  130. {
  131. CPVRTString ErrorStr = "ERROR: Couldn't load '" + CPVRTString(c_szSceneFile) + "'.";
  132. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  133. return false;
  134. }
  135. return true;
  136. }
  137. /*!****************************************************************************
  138. @Function QuitApplication
  139. @Return bool true if no error occured
  140. @Description Code in QuitApplication() will be called by PVRShell once per
  141. run, just before exiting the program.
  142. If the rendering context is lost, QuitApplication() will
  143. not be called.
  144. ******************************************************************************/
  145. bool OGLES2RenderToTexture::QuitApplication()
  146. {
  147. // Frees the memory allocated for the scene
  148. m_Scene.Destroy();
  149. delete[] m_puiVbo;
  150. delete[] m_puiIndexVbo;
  151. return true;
  152. }
  153. /*!****************************************************************************
  154. @Function InitView
  155. @Return bool true if no error occured
  156. @Description Code in InitView() will be called by PVRShell upon
  157. initialization or after a change in the rendering context.
  158. Used to initialize variables that are dependant on the rendering
  159. context (e.g. textures, vertex buffers, etc.)
  160. ******************************************************************************/
  161. bool OGLES2RenderToTexture::InitView()
  162. {
  163. CPVRTString ErrorStr;
  164. /*
  165. Initialise Print3D
  166. */
  167. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  168. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
  169. {
  170. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  171. return false;
  172. }
  173. // Initialize VBO data
  174. if(!LoadVbos(&ErrorStr))
  175. {
  176. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  177. return false;
  178. }
  179. /*
  180. Load textures
  181. */
  182. if(!LoadTextures(&ErrorStr))
  183. {
  184. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  185. return false;
  186. }
  187. /*
  188. Load and compile the shaders & link programs
  189. */
  190. if (!LoadShaders(&ErrorStr))
  191. {
  192. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  193. return false;
  194. }
  195. // Create FBO
  196. if(!CreateFBO())
  197. return false;
  198. // Check to see if the GL_EXT_discard_framebuffer extension is supported
  199. m_bDiscard=CPVRTgles2Ext::IsGLExtensionSupported("GL_EXT_discard_framebuffer");
  200. if(m_bDiscard)
  201. {
  202. m_Extensions.LoadExtensions();
  203. m_bDiscard = m_Extensions.glDiscardFramebufferEXT != 0;
  204. }
  205. // Setup some render states
  206. // Enable the depth test
  207. glEnable(GL_DEPTH_TEST);
  208. // Enable culling
  209. glEnable(GL_CULL_FACE);
  210. // Setup view and projection matrices used for when rendering to the texture
  211. // Calculate the view matrix
  212. m_mR2TView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, 60), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0));
  213. // Calculate the projection matrix
  214. // Note: As we'll be rendering to a texture we don't need to take the screen rotation into account
  215. m_mR2TProjection = PVRTMat4::PerspectiveFovRH(1, 1, g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, false);
  216. // Setup view and projection matrices used for when rendering the main scene
  217. // Caculate the view matrix
  218. m_mView = PVRTMat4::LookAtRH(PVRTVec3(0, 0, 125), PVRTVec3(0, 0, 0), PVRTVec3(0, 1, 0));
  219. // Calculate the projection matrix
  220. m_mProjection = PVRTMat4::PerspectiveFovRH(PVRT_PI/6, (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight), g_fCameraNear, g_fCameraFar, PVRTMat4::OGL, bRotate);
  221. return true;
  222. }
  223. /*!****************************************************************************
  224. @Function LoadTextures
  225. @Return bool true if no error occured
  226. @Description Loads the textures required for this training course
  227. ******************************************************************************/
  228. bool OGLES2RenderToTexture::LoadTextures(CPVRTString* pErrorStr)
  229. {
  230. // Load the texture that our mask will have
  231. if(PVRTTextureLoadFromPVR(c_szMaskTex, &m_uiTextureID) != PVR_SUCCESS)
  232. {
  233. *pErrorStr += "Failed to open ";
  234. *pErrorStr += c_szMaskTex;
  235. return false;
  236. }
  237. return true;
  238. }
  239. /*!****************************************************************************
  240. @Function LoadShaders
  241. @Output pErrorStr A string describing the error on failure
  242. @Return bool true if no error occured
  243. @Description Loads and compiles the shaders and links the shader programs
  244. required for this training course
  245. ******************************************************************************/
  246. bool OGLES2RenderToTexture::LoadShaders(CPVRTString* pErrorStr)
  247. {
  248. /*
  249. Load and compile the shaders from files.
  250. Binary shaders are tried first, source shaders
  251. are used as fallback.
  252. */
  253. if (PVRTShaderLoadFromFile(
  254. c_szVertShaderBinFile, c_szVertShaderSrcFile, GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_uiVertShader, pErrorStr) != PVR_SUCCESS)
  255. {
  256. return false;
  257. }
  258. if (PVRTShaderLoadFromFile(
  259. c_szFragShaderBinFile, c_szFragShaderSrcFile, GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_uiFragShader, pErrorStr) != PVR_SUCCESS)
  260. {
  261. return false;
  262. }
  263. /*
  264. Set up and link the shader program
  265. */
  266. if (PVRTCreateProgram(&m_ShaderProgram.uiId, m_uiVertShader, m_uiFragShader, g_aszAttribNames, eNumAttribs, pErrorStr) != PVR_SUCCESS)
  267. {
  268. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  269. return false;
  270. }
  271. // Store the location of uniforms for later use
  272. for (int i = 0; i < eNumUniforms; ++i)
  273. {
  274. m_ShaderProgram.auiLoc[i] = glGetUniformLocation(m_ShaderProgram.uiId, g_aszUniformNames[i]);
  275. }
  276. // Set the sampler2D variable to the first texture unit
  277. glUniform1i(glGetUniformLocation(m_ShaderProgram.uiId, "sTexture"), 0);
  278. return true;
  279. }
  280. /*!****************************************************************************
  281. @Function LoadVbos
  282. @Description Loads the mesh data required for this training course into
  283. vertex buffer objects
  284. ******************************************************************************/
  285. bool OGLES2RenderToTexture::LoadVbos(CPVRTString* pErrorStr)
  286. {
  287. if(m_Scene.nNumMesh == 0) // If there are no VBO to create return
  288. return true;
  289. if(!m_Scene.pMesh[0].pInterleaved)
  290. {
  291. *pErrorStr = "ERROR: RenderToTexture requires the pod data to be interleaved. Please re-export with the interleaved option enabled.";
  292. return false;
  293. }
  294. if(!m_puiVbo)
  295. m_puiVbo = new GLuint[m_Scene.nNumMesh];
  296. if(!m_puiIndexVbo)
  297. m_puiIndexVbo = new GLuint[m_Scene.nNumMesh];
  298. /*
  299. Load vertex data of all meshes in the scene into VBOs
  300. The meshes have been exported with the "Interleave Vectors" option,
  301. so all data is interleaved in the buffer at pMesh->pInterleaved.
  302. Interleaving data improves the memory access pattern and cache efficiency,
  303. thus it can be read faster by the hardware.
  304. */
  305. glGenBuffers(m_Scene.nNumMesh, m_puiVbo);
  306. for(unsigned int i = 0; i < m_Scene.nNumMesh; ++i)
  307. {
  308. // Load vertex data into buffer object
  309. SPODMesh& Mesh = m_Scene.pMesh[i];
  310. unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
  311. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[i]);
  312. glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
  313. // Load index data into buffer object if available
  314. m_puiIndexVbo[i] = 0;
  315. if(Mesh.sFaces.pData)
  316. {
  317. glGenBuffers(1, &m_puiIndexVbo[i]);
  318. uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
  319. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[i]);
  320. glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
  321. }
  322. }
  323. glBindBuffer(GL_ARRAY_BUFFER, 0);
  324. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  325. return true;
  326. }
  327. /*!****************************************************************************
  328. @Function ReleaseView
  329. @Return bool true if no error occured
  330. @Description Code in ReleaseView() will be called by PVRShell when the
  331. application quits or before a change in the rendering context.
  332. ******************************************************************************/
  333. bool OGLES2RenderToTexture::ReleaseView()
  334. {
  335. // Delete the texture
  336. glDeleteTextures(1, &m_uiTextureID);
  337. glDeleteTextures(1, &m_uiTextureToRenderTo);
  338. // Release Print3D Textures
  339. m_Print3D.ReleaseTextures();
  340. // Tidy up the FBO
  341. // Delete frame buffer objects
  342. glDeleteFramebuffers(1, &m_uFBO);
  343. // Delete our depth buffer
  344. glDeleteRenderbuffers(1, &m_uDepthBuffer);
  345. return true;
  346. }
  347. /*!****************************************************************************
  348. @Function CreateFBO
  349. @Return bool true if no error occured
  350. @Description Attempts to create our FBO.
  351. ******************************************************************************/
  352. bool OGLES2RenderToTexture::CreateFBO()
  353. {
  354. // Find the largest square power of two texture that fits into the viewport
  355. m_i32TexSize = 1;
  356. int iSize = PVRT_MIN(PVRShellGet(prefWidth), PVRShellGet(prefHeight));
  357. while (m_i32TexSize * 2 < iSize) m_i32TexSize *= 2;
  358. // Get the currently bound frame buffer object. On most platforms this just gives 0.
  359. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo);
  360. // Generate and bind a render buffer which will become a depth buffer shared between our two FBOs
  361. glGenRenderbuffers(1, &m_uDepthBuffer);
  362. glBindRenderbuffer(GL_RENDERBUFFER, m_uDepthBuffer);
  363. /*
  364. Currently it is unknown to GL that we want our new render buffer to be a depth buffer.
  365. glRenderbufferStorage will fix this and in this case will allocate a depth buffer
  366. m_i32TexSize by m_i32TexSize.
  367. */
  368. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_i32TexSize, m_i32TexSize);
  369. // Create a texture for rendering to
  370. glGenTextures(1, &m_uiTextureToRenderTo);
  371. glBindTexture(GL_TEXTURE_2D, m_uiTextureToRenderTo);
  372. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_i32TexSize, m_i32TexSize, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
  373. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  374. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  375. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  376. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  377. // Create the object that will allow us to render to the aforementioned texture
  378. glGenFramebuffers(1, &m_uFBO);
  379. glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO);
  380. // Attach the texture to the FBO
  381. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_uiTextureToRenderTo, 0);
  382. // Attach the depth buffer we created earlier to our FBO.
  383. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uDepthBuffer);
  384. // Check that our FBO creation was successful
  385. GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  386. if(uStatus != GL_FRAMEBUFFER_COMPLETE)
  387. {
  388. PVRShellSet(prefExitMessage, "ERROR: Failed to initialise FBO");
  389. return false;
  390. }
  391. // Clear the colour and depth buffers for the FBO / PBuffer surface
  392. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  393. // Unbind the frame buffer object so rendering returns back to the backbuffer
  394. glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);
  395. return true;
  396. }
  397. /*!****************************************************************************
  398. @Function RenderScene
  399. @Return bool true if no error occured
  400. @Description Main rendering loop function of the program. The shell will
  401. call this function every frame.
  402. eglSwapBuffers() will be performed by PVRShell automatically.
  403. PVRShell will also manage important OS events.
  404. Will also manage relevent OS events. The user has access to
  405. these events through an abstraction layer provided by PVRShell.
  406. ******************************************************************************/
  407. bool OGLES2RenderToTexture::RenderScene()
  408. {
  409. // Enable the vertex attribute arrays
  410. glEnableVertexAttribArray(eVERTEX_ARRAY);
  411. glEnableVertexAttribArray(eNORMAL_ARRAY);
  412. glEnableVertexAttribArray(eTEXCOORD_ARRAY);
  413. // Use shader program
  414. glUseProgram(m_ShaderProgram.uiId);
  415. // Setup the lighting direction
  416. // Reads the light direction from the scene.
  417. PVRTVec4 vLightDirection;
  418. PVRTVec3 vPos;
  419. vLightDirection = m_Scene.GetLightDirection(0);
  420. // Update out angle used for rotating the mask
  421. PVRTMat4 mWorld, mMVP;
  422. PVRTVec4 vLightDir;
  423. PVRTVec3 vLightDirModel;
  424. m_fAngleY += (2*PVRT_PI/60)/7;
  425. // Render to our texture
  426. {
  427. // Bind our FBO
  428. glBindFramebuffer(GL_FRAMEBUFFER, m_uFBO);
  429. // Setup the Viewport to the dimensions of the texture
  430. glViewport(0, 0, m_i32TexSize, m_i32TexSize);
  431. // Set the colour to clear our texture to
  432. glClearColor(0.8f, 1.0f, 0.6f, 1.0f);
  433. // Clear the colour and depth buffer of our FBO / PBuffer surface
  434. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  435. // Render our objects as we usually would
  436. mWorld = PVRTMat4::RotationY(m_fAngleY);
  437. // Pass the light direction in model space to the shader
  438. vLightDir = mWorld.inverse() * vLightDirection;
  439. vLightDirModel = *(PVRTVec3*)&vLightDir;
  440. vLightDirModel.normalize();
  441. glUniform3fv(m_ShaderProgram.auiLoc[eLightDirection], 1, &vLightDirModel.x);
  442. // Set the model-view-projection matrix
  443. mMVP = m_mR2TProjection * m_mR2TView * mWorld;
  444. glUniformMatrix4fv(m_ShaderProgram.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.f);
  445. // Bind the mask's texture
  446. glBindTexture(GL_TEXTURE_2D, m_uiTextureID);
  447. // Draw our mask
  448. DrawMesh(m_Scene.pNode[0].nIdx);
  449. if(m_bDiscard) // Was GL_EXT_discard_framebuffer supported?
  450. {
  451. /*
  452. Give the drivers a hint that we don't want the depth and stencil information stored for future use.
  453. Note: This training course doesn't have any stencil information so the STENCIL_ATTACHMENT enum
  454. is used for demonstrations purposes only and will be ignored by the driver.
  455. */
  456. const GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
  457. m_Extensions.glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
  458. }
  459. // We are done with rendering to our FBO so switch back to the back buffer.
  460. glBindFramebuffer(GL_FRAMEBUFFER, m_i32OriginalFbo);
  461. }
  462. // Set the clear colour
  463. glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  464. // Clear the colour and depth buffer
  465. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  466. // Setup the Viewport to the dimensions of the screen
  467. glViewport(0, 0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
  468. // Get the node model matrix
  469. mWorld = m_Scene.GetWorldMatrix(m_Scene.pNode[1]);
  470. // Pass the light direction in model space to the shader
  471. vLightDir = mWorld.inverse() * vLightDirection;
  472. vLightDirModel = *(PVRTVec3*)&vLightDir;
  473. vLightDirModel.normalize();
  474. glUniform3fv(m_ShaderProgram.auiLoc[eLightDirection], 1, &vLightDirModel.x);
  475. // Set the model-view-projection matrix
  476. mMVP = m_mProjection * m_mView * mWorld ;
  477. glUniformMatrix4fv(m_ShaderProgram.auiLoc[eMVPMatrix], 1, GL_FALSE, mMVP.f);
  478. // Bind our texture that we have rendered to
  479. glBindTexture(GL_TEXTURE_2D, m_uiTextureToRenderTo);
  480. // Draw our textured cube
  481. DrawMesh(m_Scene.pNode[1].nIdx);
  482. // Safely disable the vertex attribute arrays
  483. glDisableVertexAttribArray(eVERTEX_ARRAY);
  484. glDisableVertexAttribArray(eNORMAL_ARRAY);
  485. glDisableVertexAttribArray(eTEXCOORD_ARRAY);
  486. // Unbind our VBOs
  487. glBindBuffer(GL_ARRAY_BUFFER, 0);
  488. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  489. // Display the demo name using the tools. For a detailed explanation, see the training course IntroducingPVRTools
  490. m_Print3D.DisplayDefaultTitle("RenderToTexture", "Using FBOs", ePVRTPrint3DSDKLogo);
  491. m_Print3D.Flush();
  492. return true;
  493. }
  494. /*!****************************************************************************
  495. @Function DrawMesh
  496. @Input mesh The mesh to draw
  497. @Description Draws a SPODMesh after the model view matrix has been set and
  498. the meterial prepared.
  499. ******************************************************************************/
  500. void OGLES2RenderToTexture::DrawMesh(unsigned int ui32MeshID)
  501. {
  502. SPODMesh& Mesh = m_Scene.pMesh[ui32MeshID];
  503. // bind the VBO for the mesh
  504. glBindBuffer(GL_ARRAY_BUFFER, m_puiVbo[ui32MeshID]);
  505. // bind the index buffer, won't hurt if the handle is 0
  506. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_puiIndexVbo[ui32MeshID]);
  507. // Set the vertex attribute offsets
  508. glVertexAttribPointer(eVERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData);
  509. glVertexAttribPointer(eNORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sNormals.nStride, Mesh.sNormals.pData);
  510. glVertexAttribPointer(eTEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData);
  511. // Indexed Triangle list
  512. glDrawElements(GL_TRIANGLES, Mesh.nNumFaces*3, GL_UNSIGNED_SHORT, 0);
  513. }
  514. /*!****************************************************************************
  515. @Function NewDemo
  516. @Return PVRShell* The demo supplied by the user
  517. @Description This function must be implemented by the user of the shell.
  518. The user should return its PVRShell object defining the
  519. behaviour of the application.
  520. ******************************************************************************/
  521. PVRShell* NewDemo()
  522. {
  523. return new OGLES2RenderToTexture();
  524. }
  525. /******************************************************************************
  526. End of file (OGLES2RenderToTexture.cpp)
  527. ******************************************************************************/