OGLES2Water.cpp 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233
  1. /******************************************************************************
  2. @File OGLES2Water.cpp
  3. @Title Water
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independent
  7. @Description Demonstrates a method of rendering a water effect efficiently
  8. using OpenGL ES 2.0
  9. ******************************************************************************/
  10. #include "PVRShell.h"
  11. #include "OGLES2Tools.h"
  12. /******************************************************************************
  13. Defines
  14. ******************************************************************************/
  15. // Camera constants. Used for making the projection matrix
  16. #define CAM_NEAR (12.0f)
  17. #define CAM_FAR (4000.0f)
  18. // Index the attributes that are bound to vertex shaders
  19. #define VERTEX_ARRAY 0
  20. #define NORMAL_ARRAY 1
  21. #define TEXCOORD_ARRAY 2
  22. #define ENABLE_UI // Remove when user input is not required
  23. //#define DEBUG_MODE // Only use for debugging
  24. //#define FREE_CAMERA_MODE // Only use for debugging
  25. /****************************************************************************
  26. ** Enums
  27. ****************************************************************************/
  28. enum ETextureNames
  29. {
  30. eSKYBOX_TEX,
  31. eWATER_NORMAL_TEX,
  32. eTEX_NAME_SIZE
  33. };
  34. enum EShaderNames
  35. {
  36. eREFLECTION_ONLY_SHADER,
  37. eSKYBOX_SHADER,
  38. eMODEL_SHADER,
  39. eTEX2D_SHADER,
  40. ePLANE_TEX_SHADER,
  41. eSHADER_SIZE
  42. };
  43. enum EDefineShaderNames
  44. {
  45. eFULL_WATER_SHADER,
  46. eNO_FRESNEL_SHADER,
  47. eFOG_MODEL_SHADER,
  48. eLIGHT_MODEL_SHADER,
  49. eBUMP_REFLECT_WATER_SHADER,
  50. eDEFINE_SHADER_SIZE
  51. };
  52. enum EVertexBufferObjects
  53. {
  54. eSKYBOX_VBO,
  55. eVBO_SIZE
  56. };
  57. enum EFrameBufferObjects
  58. {
  59. eREFLECTION_FBO,
  60. eREFRACTION_FBO,
  61. eWATER_FBO,
  62. eFBO_SIZE
  63. };
  64. enum EUserInterface
  65. {
  66. eUI_NULL,
  67. eTOGGLE_REFRACTION,
  68. eTOGGLE_FRESNEL,
  69. eTOGGLE_FOG,
  70. eFOG_DEPTH,
  71. eWAVE_DISTORTION,
  72. eARTEFACT_FIX,
  73. #ifdef DEBUG_MODE
  74. #ifdef FREE_CAMERA_MODE
  75. eMOVE_X,
  76. eMOVE_Y,
  77. eMOVE_Z,
  78. eCAMERA_X,
  79. eCAMERA_Y,
  80. eCAMERA_Z,
  81. eLOOK_AT_X,
  82. eLOOK_AT_Y,
  83. eLOOK_AT_Z,
  84. #endif
  85. eWATER_HEIGHT,
  86. eWATER_COLOUR_R,
  87. eWATER_COLOUR_G,
  88. eWATER_COLOUR_B,
  89. eTOGGLE_DEBUG_WINDOWS,
  90. #endif
  91. eUI_SIZE
  92. };
  93. /****************************************************************************
  94. ** Structures
  95. ****************************************************************************/
  96. // Group shader programs and their uniform locations together
  97. struct WaterShader
  98. {
  99. GLuint uiId;
  100. GLuint uiMVMatrixLoc;
  101. GLuint uiMVPMatrixLoc;
  102. GLuint uiEyePosLoc;
  103. GLuint uiWaterColourLoc;
  104. GLuint uiBumpTranslation0Loc;
  105. GLuint uiBumpScale0Loc;
  106. GLuint uiBumpTranslation1Loc;
  107. GLuint uiBumpScale1Loc;
  108. GLuint uiWaveDistortionLoc;
  109. GLuint uiRcpWindowSizeLoc;
  110. };
  111. struct SkyboxShader
  112. {
  113. GLuint uiId;
  114. GLuint uiMVPMatrixLoc;
  115. GLuint uiModelMatrixLoc;
  116. GLuint uiLightDirLoc;
  117. GLuint uiEyePosLoc;
  118. GLuint uiWaterHeightLoc;
  119. GLuint uiFogColourLoc;
  120. GLuint uiMaxFogDepthLoc;
  121. };
  122. struct ModelShader
  123. {
  124. GLuint uiId;
  125. GLuint uiMVPMatrixLoc;
  126. GLuint uiModelMatrixLoc;
  127. GLuint uiLightDirectionLoc;
  128. GLuint uiWaterHeightLoc;
  129. GLuint uiFogColourLoc;
  130. GLuint uiMaxFogDepthLoc;
  131. };
  132. struct Tex2DShader
  133. {
  134. GLuint uiId;
  135. GLuint uiMVPMatrixLoc;
  136. }
  137. m_Tex2DShader;
  138. struct PlaneTexShader
  139. {
  140. GLuint uiId;
  141. GLuint uiMVPMatrixLoc;
  142. GLuint uiRcpWindowSizeLoc;
  143. }
  144. m_PlaneTexShader;
  145. /****************************************************************************
  146. ** Consts
  147. ****************************************************************************/
  148. // Water plane equations
  149. static const GLuint c_uiTexSize = 256; // 256x256 for reflection and refraction mapping
  150. static const GLuint c_uiWaterTexSize = 256; // 256x256 for water mapping
  151. static const GLuint c_uiNumberOfSkyboxTextures = 1;
  152. static const GLuint c_uiNoOfDefines[eDEFINE_SHADER_SIZE] = {3,2,2,1,1};
  153. static const GLuint c_uiNoOfModels = 1;
  154. static const float c_fDemoFrameRate = 1.0f / 30.0f; // Used during animation
  155. static const GLuint c_uiCamera = 0; // The camera to use from the .pod file
  156. /******************************************************************************
  157. Content file names
  158. ******************************************************************************/
  159. // Source and binary shaders
  160. const char * const c_aszFragShaderSrcFile[eSHADER_SIZE] =
  161. {
  162. "FragShader.fsh",
  163. "SkyboxFShader.fsh",
  164. "ModelFShader.fsh",
  165. "Tex2DFShader.fsh",
  166. "PlaneTexFShader.fsh"
  167. };
  168. const char * const c_aszFragShaderBinFile[eSHADER_SIZE] =
  169. {
  170. "FragShader.fsc",
  171. "SkyboxFShader.fsc",
  172. "ModelFShader.fsc",
  173. "Tex2DFShader.fsc",
  174. "PlaneTexFShader.fsc"
  175. };
  176. const char * const c_aszVertShaderSrcFile[eSHADER_SIZE] =
  177. {
  178. "VertShader.vsh",
  179. "SkyboxVShader.vsh",
  180. "ModelVShader.vsh",
  181. "Tex2DVShader.vsh",
  182. "PlaneTexVShader.vsh"
  183. };
  184. const char * const c_aszVertShaderBinFile[eSHADER_SIZE] =
  185. {
  186. "VertShader.vsc",
  187. "SkyboxVShader.vsc",
  188. "ModelVShader.vsc",
  189. "Tex2DVShader.vsc",
  190. "PlaneTexVShader.vsc"
  191. };
  192. // PVR texture files
  193. const char * const c_aszTextureNames[eTEX_NAME_SIZE] =
  194. {
  195. "Mountain.pvr",
  196. "NewNormalMap.pvr"
  197. };
  198. // Shader defines are used to control which code path is taken in each shader
  199. static const char* c_aszFullWaterShaderDefines[] =
  200. {
  201. "ENABLE_REFRACTION",
  202. "ENABLE_FRESNEL",
  203. "ENABLE_DISTORTION"
  204. };
  205. static const char* c_aszFogShaderDefines[] =
  206. {
  207. "ENABLE_FOG_DEPTH",
  208. "ENABLE_LIGHTING"
  209. };
  210. static const char* c_aszNoFresnelShaderDefines[] =
  211. {
  212. "ENABLE_REFRACTION",
  213. "ENABLE_DISTORTION"
  214. };
  215. const char* c_aszModelLightingDefines[1] =
  216. {
  217. "ENABLE_LIGHTING"
  218. };
  219. const char* c_aszBumpedReflectionShaderDefines[] =
  220. {
  221. "ENABLE_DISTORTION"
  222. };
  223. // Array of pointers to the defines for shaders
  224. const char** c_aszAllDefines[eDEFINE_SHADER_SIZE] =
  225. {
  226. c_aszFullWaterShaderDefines,
  227. c_aszNoFresnelShaderDefines,
  228. c_aszFogShaderDefines,
  229. c_aszModelLightingDefines,
  230. c_aszBumpedReflectionShaderDefines
  231. };
  232. // POD scene files
  233. static const char* c_aszModelFiles[c_uiNoOfModels] =
  234. {
  235. "Scene.pod"
  236. };
  237. /*!****************************************************************************
  238. Class declaration
  239. ******************************************************************************/
  240. class OGLES2Water : public PVRShell
  241. {
  242. // Print3D class used to display text
  243. CPVRTPrint3D m_Print3D;
  244. // 3D Model
  245. CPVRTModelPOD m_Mesh[c_uiNoOfModels];
  246. // Projection, view and other matrices
  247. PVRTMat4 m_mProjection, m_mView;
  248. // Camera settings
  249. PVRTVec3 m_vEyePos, m_vLookAt, m_vCamUp;
  250. GLfloat m_fFOV;
  251. // Shared variables
  252. PVRTVec4 m_vLightDirection;
  253. // UI variables
  254. int m_iCurrentUIOption;
  255. // OpenGL handles for shaders, textures and VBOs
  256. GLuint* m_apuiModelVbo[c_uiNoOfModels];
  257. GLuint* m_apuiModelIndexVbo[c_uiNoOfModels];
  258. GLuint* m_apuiModelTextureIds[c_uiNoOfModels];
  259. GLuint m_auiTextureIds[eTEX_NAME_SIZE];
  260. GLuint m_uiNormalisationCubeMap;
  261. GLuint m_auiVertShaderIds[eSHADER_SIZE + eDEFINE_SHADER_SIZE];
  262. GLuint m_auiFragShaderIds[eSHADER_SIZE + eDEFINE_SHADER_SIZE];
  263. GLuint m_auiVBOIds[eVBO_SIZE]; // Vertex buffer objects
  264. GLint m_iOriginalFBO; // Original frame buffer object
  265. GLuint m_auiFBOIds[eFBO_SIZE]; // Frame buffer objects
  266. // Render to texture variables
  267. GLuint m_auiRendToTexture[eFBO_SIZE];
  268. GLuint m_auiDepthBuffer[eFBO_SIZE]; // Used for reflection render
  269. // Shader programs
  270. ModelShader m_ModelShader, m_FogModelShader, m_LightModelShader;
  271. WaterShader m_ReflectionOnlyShader, m_FullWaterShader, m_NoFresnelWaterShader, m_BumpReflectionWaterShader;
  272. SkyboxShader m_SkyboxShader;
  273. // Water
  274. PVRTVec4 m_vPlaneWater; // [A,B,C,D] plane definition
  275. PVRTVec3 m_pvPlaneWater[5]; // Procedurally generated water plane
  276. int m_i32WaterPlaneNo;
  277. // Skybox
  278. GLfloat* m_SkyboxVertices;
  279. GLfloat* m_SkyboxTexCoords;
  280. // Time variables
  281. unsigned long m_ulPreviousTime, m_ulCurrentTime;
  282. float m_fElapsedTimeInSecs, m_fDeltaTime, m_fFrame, m_fCount;
  283. unsigned int m_uiFPS, m_uiFrameCount;
  284. bool m_bPause;
  285. // Water variables
  286. PVRTVec4 m_vWaterColour;
  287. GLfloat m_fWaterHeight;
  288. GLfloat m_fMaxFogDepth;
  289. bool m_bFogDepth;
  290. GLfloat m_fWaterArtefactFix;
  291. GLfloat m_fBoatSpeed;
  292. PVRTVec2 m_vBumpTranslation0;
  293. PVRTVec2 m_vBumpVelocity0;
  294. PVRTVec2 m_vBumpScale0;
  295. PVRTVec2 m_vBumpTranslation1;
  296. PVRTVec2 m_vBumpVelocity1;
  297. PVRTVec2 m_vBumpScale1;
  298. GLfloat m_fWaveDistortion;
  299. PVRTVec2 m_vRcpWindowSize;
  300. GLuint m_uiTerrainNodeIndex;
  301. bool m_bShaderRefraction;
  302. bool m_bShaderFogging;
  303. bool m_bShaderFresnel;
  304. bool m_bDisplayDebugWindows;
  305. PVRTVec4 m_vClipPlane;
  306. bool m_bClipPlane;
  307. public:
  308. virtual bool InitApplication();
  309. virtual bool InitView();
  310. virtual bool ReleaseView();
  311. virtual bool QuitApplication();
  312. virtual bool RenderScene();
  313. bool LoadTextures(CPVRTString* pErrorStr);
  314. bool LoadWaterShader(WaterShader& shaderProgram, GLuint uiShaderId, CPVRTString* pErrorStr);
  315. bool LoadModelShader(ModelShader& shaderProgram,GLuint uiShaderId, CPVRTString* pErrorStr);
  316. bool LoadShaders(CPVRTString* pErrorStr);
  317. bool LoadVbos(CPVRTString* pErrorStr);
  318. void SetProjection(const float fFOV = 60.0f * (PVRT_PI/180.0f), const float fFarClip = CAM_FAR);
  319. void SetView();
  320. void ResetVariables();
  321. void RenderReflectionTexture();
  322. void RenderRefractionTexture();
  323. void RenderWaterTexture(const WaterShader& shaderProgram);
  324. void DrawMesh( GLuint uiModelNo, int i32NodeIndex, const ModelShader& shaderProgram);
  325. void DrawMeshScene(const ModelShader& shaderProgram);
  326. void DrawInfinitePlane(const PVRTVec4& vPlane, float fFarDistance = CAM_FAR);
  327. void DrawWater(const WaterShader& shaderProgram, GLuint uiViewPortWidth, GLuint uiViewPortHeight, const PVRTVec4& vPlane, float fFarDistance = CAM_FAR);
  328. void DrawWaterFromTexture(float farDistance = CAM_FAR);
  329. void DrawSkybox(GLuint uiCubeMapHandle, const SkyboxShader& shaderProgram, GLuint uiVboId,
  330. const PVRTVec3& vTranslation = PVRTVec3(0.0f,0.0f,0.0f));
  331. void DrawScene(const ModelShader& shaderProgram);
  332. void DrawRefractionScene(const ModelShader& shaderProgram);
  333. void DrawTestQuad(GLuint uiTextureHandle, const PVRTVec2 &vBottomLeftPosition = PVRTVec2(-1,-1));
  334. void ModifyProjectionForClipping(const PVRTVec4 &vClipPlane);
  335. bool GenerateNormalisationCubeMap(int uiTextureSize = 32);
  336. void UpdateTimer();
  337. inline GLfloat sgn(GLfloat a);
  338. };
  339. /*!****************************************************************************
  340. @Function sgn
  341. @Return a Returns the result of the signum function.
  342. @Description Takes a float input and determines if it's value is greater than,
  343. equal to or less than zero. It returns a value within normal
  344. space to reflect this outcome
  345. ******************************************************************************/
  346. GLfloat OGLES2Water::sgn(GLfloat a)
  347. {
  348. if(a > 0.0f) return(1.0f);
  349. if(a < 0.0f) return(-1.0f);
  350. return 0.0f;
  351. }
  352. /*!****************************************************************************
  353. @Function LoadTextures
  354. @Output pErrorStr A string describing the error on failure
  355. @Return bool true if no error occured
  356. @Description Loads the textures required for this training course
  357. ******************************************************************************/
  358. bool OGLES2Water::LoadTextures(CPVRTString* const pErrorStr)
  359. {
  360. // Load textures to array
  361. GLuint i = 0;
  362. // Load cubemaps first
  363. for(; i < c_uiNumberOfSkyboxTextures; ++i)
  364. {
  365. if(PVRTTextureLoadFromPVR(c_aszTextureNames[i], &m_auiTextureIds[i]) != PVR_SUCCESS)
  366. {
  367. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_aszTextureNames[i];
  368. return false;
  369. }
  370. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  371. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  372. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  373. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  374. }
  375. // Load remaining textures
  376. for(; i < eTEX_NAME_SIZE; ++i)
  377. {
  378. if(PVRTTextureLoadFromPVR(c_aszTextureNames[i],&m_auiTextureIds[i]) != PVR_SUCCESS)
  379. {
  380. *pErrorStr = CPVRTString("ERROR: Could not open texture file ") + c_aszTextureNames[i];
  381. return false;
  382. }
  383. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  384. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  385. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  386. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  387. }
  388. //Create normalisation cube map
  389. glGenTextures(1, &m_uiNormalisationCubeMap);
  390. glBindTexture(GL_TEXTURE_CUBE_MAP, m_uiNormalisationCubeMap);
  391. GenerateNormalisationCubeMap(8);
  392. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  393. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  394. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  395. glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  396. glGenTextures(eFBO_SIZE, m_auiRendToTexture);
  397. // Allocate textures for reflection and refraction FBOs
  398. for(i = 0; i < eFBO_SIZE - 1; ++i)
  399. {
  400. glBindTexture(GL_TEXTURE_2D, m_auiRendToTexture[i]);
  401. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB/*A*/, c_uiTexSize, c_uiTexSize, 0, GL_RGB/*A*/, GL_UNSIGNED_BYTE, 0);
  402. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  403. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  404. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  405. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  406. }
  407. // Allocate texture for water FBO
  408. glBindTexture(GL_TEXTURE_2D, m_auiRendToTexture[eWATER_FBO]);
  409. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, c_uiWaterTexSize, c_uiWaterTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
  410. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  411. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  412. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  413. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  414. // Load all textures for each model
  415. for(GLuint j = 0 ; j < c_uiNoOfModels ; ++j)
  416. {
  417. m_apuiModelTextureIds[j] = new GLuint[m_Mesh[j].nNumMaterial];
  418. if(!m_apuiModelTextureIds[j])
  419. {
  420. *pErrorStr = "ERROR: Insufficient memory.";
  421. return false;
  422. }
  423. for(int i = 0; i < (int) m_Mesh[j].nNumMaterial; ++i)
  424. {
  425. m_apuiModelTextureIds[j][i] = 0;
  426. SPODMaterial* pMaterial = &m_Mesh[j].pMaterial[i];
  427. if(pMaterial->nIdxTexDiffuse != -1)
  428. {
  429. /*
  430. Using the tools function PVRTTextureLoadFromPVR load the textures required by the pod file.
  431. Note: This function only loads .pvr files. You can set the textures in 3D Studio Max to .pvr
  432. files using the PVRTexTool plug-in for max. Alternatively, the pod material properties can be
  433. modified in PVRShaman.
  434. */
  435. CPVRTString sTextureName = m_Mesh[j].pTexture[pMaterial->nIdxTexDiffuse].pszName;
  436. if(PVRTTextureLoadFromPVR(sTextureName.c_str(), &m_apuiModelTextureIds[j][i]) != PVR_SUCCESS)
  437. {
  438. *pErrorStr = "ERROR: Failed to load " + sTextureName + ".";
  439. // Check to see if we're trying to load .pvr or not
  440. CPVRTString sFileExtension = PVRTStringGetFileExtension(sTextureName);
  441. if(sFileExtension.toLower() != "pvr")
  442. {
  443. *pErrorStr += "Note: Demo can only load pvr files.";
  444. }
  445. return false;
  446. }
  447. }
  448. }
  449. }
  450. return true;
  451. }
  452. /*!****************************************************************************
  453. @Function LoadWaterShader
  454. @Input/output shaderProgram The water shader to load
  455. @Input uiShaderId The shader's ID
  456. @Output pErrorStr A string describing the error on failure
  457. @Return bool true if no error occured
  458. @Description Loads and compiles a water shader and links it to a shader program
  459. ******************************************************************************/
  460. bool OGLES2Water::LoadWaterShader(WaterShader& shaderProgram, GLuint uiShaderId, CPVRTString* pErrorStr)
  461. {
  462. const char* aszWaterAttribs[] = { "inVertex"};
  463. if (PVRTCreateProgram(&shaderProgram.uiId, m_auiVertShaderIds[uiShaderId], m_auiFragShaderIds[uiShaderId], aszWaterAttribs, 1, pErrorStr))
  464. {
  465. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  466. return false;
  467. }
  468. // Set the sampler2D variables
  469. glUniform1i(glGetUniformLocation(shaderProgram.uiId, "NormalTex"), 0);
  470. glUniform1i(glGetUniformLocation(shaderProgram.uiId, "ReflectionTex"),1);
  471. glUniform1i(glGetUniformLocation(shaderProgram.uiId, "RefractionTex"),2);
  472. glUniform1i(glGetUniformLocation(shaderProgram.uiId, "NormalisationCubeMap"),3);
  473. // Store the location of uniforms for later use
  474. shaderProgram.uiMVMatrixLoc = glGetUniformLocation(shaderProgram.uiId, "ModelViewMatrix");
  475. shaderProgram.uiMVPMatrixLoc = glGetUniformLocation(shaderProgram.uiId, "MVPMatrix");
  476. shaderProgram.uiEyePosLoc = glGetUniformLocation(shaderProgram.uiId, "EyePosition");
  477. shaderProgram.uiWaterColourLoc = glGetUniformLocation(shaderProgram.uiId, "WaterColour");
  478. shaderProgram.uiBumpTranslation0Loc = glGetUniformLocation(shaderProgram.uiId, "BumpTranslation0");
  479. shaderProgram.uiBumpScale0Loc = glGetUniformLocation(shaderProgram.uiId, "BumpScale0");
  480. shaderProgram.uiBumpTranslation1Loc = glGetUniformLocation(shaderProgram.uiId, "BumpTranslation1");
  481. shaderProgram.uiBumpScale1Loc = glGetUniformLocation(shaderProgram.uiId, "BumpScale1");
  482. shaderProgram.uiWaveDistortionLoc = glGetUniformLocation(shaderProgram.uiId, "WaveDistortion");
  483. shaderProgram.uiRcpWindowSizeLoc = glGetUniformLocation(shaderProgram.uiId, "RcpWindowSize");
  484. return true;
  485. }
  486. /*!****************************************************************************
  487. @Function LoadModelShader
  488. @Input/output shaderProgram The model shader to load
  489. @Input uiShaderId The shader's ID
  490. @Output pErrorStr A string describing the error on failure
  491. @Return bool true if no error occured
  492. @Description Loads and compiles a model shader and links it to a shader program
  493. ******************************************************************************/
  494. bool OGLES2Water::LoadModelShader(ModelShader &shaderProgram, GLuint uiShaderId, CPVRTString *pErrorStr)
  495. {
  496. const char* aszModelAttribs[] = { "inVertex", "inNormal", "inTexCoord"};
  497. if (PVRTCreateProgram(&shaderProgram.uiId, m_auiVertShaderIds[uiShaderId], m_auiFragShaderIds[uiShaderId], aszModelAttribs, 3, pErrorStr))
  498. {
  499. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  500. return false;
  501. }
  502. glUniform1i(glGetUniformLocation(shaderProgram.uiId, "ModelTexture"),0);
  503. shaderProgram.uiMVPMatrixLoc = glGetUniformLocation(shaderProgram.uiId, "MVPMatrix");
  504. shaderProgram.uiModelMatrixLoc = glGetUniformLocation(shaderProgram.uiId, "ModelMatrix");
  505. shaderProgram.uiLightDirectionLoc = glGetUniformLocation(shaderProgram.uiId, "LightDirection");
  506. shaderProgram.uiWaterHeightLoc = glGetUniformLocation(shaderProgram.uiId, "WaterHeight");
  507. shaderProgram.uiFogColourLoc = glGetUniformLocation(shaderProgram.uiId, "FogColour");
  508. shaderProgram.uiMaxFogDepthLoc = glGetUniformLocation(shaderProgram.uiId, "RcpMaxFogDepth");
  509. return true;
  510. }
  511. /*!****************************************************************************
  512. @Function LoadShaders
  513. @Output pErrorStr A string describing the error on failure
  514. @Return bool true if no error occured
  515. @Description Loads and compiles shaders and links them to shader programs
  516. ******************************************************************************/
  517. bool OGLES2Water::LoadShaders(CPVRTString* pErrorStr)
  518. {
  519. /*
  520. Load and compile the shaders from files.
  521. Binary shaders are tried first, source shaders
  522. are used as fallback.
  523. */
  524. for(GLuint i = 0; i < eSHADER_SIZE; ++i)
  525. {
  526. if(PVRTShaderLoadFromFile(
  527. c_aszVertShaderBinFile[i],c_aszVertShaderSrcFile[i],GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &m_auiVertShaderIds[i], pErrorStr) != PVR_SUCCESS)
  528. {
  529. return false;
  530. }
  531. if(PVRTShaderLoadFromFile(
  532. c_aszFragShaderBinFile[i],c_aszFragShaderSrcFile[i],GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &m_auiFragShaderIds[i], pErrorStr) != PVR_SUCCESS)
  533. {
  534. return false;
  535. }
  536. }
  537. // Assign pointers to the original source files the defines need to be prepended to
  538. const char* pDefVertShaderSrcFile[eDEFINE_SHADER_SIZE] = { c_aszVertShaderSrcFile[eREFLECTION_ONLY_SHADER],
  539. c_aszVertShaderSrcFile[eREFLECTION_ONLY_SHADER],
  540. c_aszVertShaderSrcFile[eMODEL_SHADER],
  541. c_aszVertShaderSrcFile[eMODEL_SHADER],
  542. c_aszVertShaderSrcFile[eREFLECTION_ONLY_SHADER]};
  543. const char* pDefFragShaderSrcFile[eDEFINE_SHADER_SIZE] = { c_aszFragShaderSrcFile[eREFLECTION_ONLY_SHADER],
  544. c_aszFragShaderSrcFile[eREFLECTION_ONLY_SHADER],
  545. c_aszFragShaderSrcFile[eMODEL_SHADER],
  546. c_aszFragShaderSrcFile[eMODEL_SHADER],
  547. c_aszFragShaderSrcFile[eREFLECTION_ONLY_SHADER]};
  548. // Load shaders using defines
  549. for(GLuint i = 0; i < eDEFINE_SHADER_SIZE; ++i)
  550. {
  551. if(PVRTShaderLoadFromFile(0,pDefVertShaderSrcFile[i],GL_VERTEX_SHADER, 0, &m_auiVertShaderIds[eSHADER_SIZE + i], pErrorStr, 0, c_aszAllDefines[i], c_uiNoOfDefines[i]) != PVR_SUCCESS)
  552. {
  553. return false;
  554. }
  555. if(PVRTShaderLoadFromFile(0, pDefFragShaderSrcFile[i],GL_FRAGMENT_SHADER, 0, &m_auiFragShaderIds[eSHADER_SIZE + i], pErrorStr, 0, c_aszAllDefines[i], c_uiNoOfDefines[i]) != PVR_SUCCESS)
  556. {
  557. return false;
  558. }
  559. }
  560. /*
  561. Set up and link to water shader programs
  562. */
  563. if(!LoadWaterShader(m_ReflectionOnlyShader, eREFLECTION_ONLY_SHADER, pErrorStr))
  564. {
  565. return false;
  566. }
  567. if(!LoadWaterShader(m_FullWaterShader, eSHADER_SIZE + eFULL_WATER_SHADER, pErrorStr))
  568. {
  569. return false;
  570. }
  571. if(!LoadWaterShader(m_NoFresnelWaterShader, eSHADER_SIZE + eNO_FRESNEL_SHADER, pErrorStr))
  572. {
  573. return false;
  574. }
  575. if(!LoadWaterShader(m_BumpReflectionWaterShader, eSHADER_SIZE + eBUMP_REFLECT_WATER_SHADER, pErrorStr))
  576. {
  577. return false;
  578. }
  579. /*
  580. Set up and link the sky box shader program
  581. */
  582. const char* aszSkyboxAttribs[] = { "inVertex"};
  583. if (PVRTCreateProgram(&m_SkyboxShader.uiId, m_auiVertShaderIds[eSKYBOX_SHADER], m_auiFragShaderIds[eSKYBOX_SHADER], aszSkyboxAttribs, 1, pErrorStr))
  584. {
  585. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  586. return false;
  587. }
  588. glUniform1i(glGetUniformLocation(m_SkyboxShader.uiId, "CubeMap"),0);
  589. m_SkyboxShader.uiMVPMatrixLoc = glGetUniformLocation(m_SkyboxShader.uiId, "MVPMatrix");
  590. m_SkyboxShader.uiModelMatrixLoc = glGetUniformLocation(m_SkyboxShader.uiId, "ModelMatrix");
  591. m_SkyboxShader.uiEyePosLoc = glGetUniformLocation(m_SkyboxShader.uiId, "EyePosition");
  592. m_SkyboxShader.uiWaterHeightLoc = glGetUniformLocation(m_SkyboxShader.uiId, "WaterHeight");
  593. m_SkyboxShader.uiFogColourLoc = glGetUniformLocation(m_SkyboxShader.uiId, "FogColour");
  594. m_SkyboxShader.uiMaxFogDepthLoc = glGetUniformLocation(m_SkyboxShader.uiId, "RcpMaxFogDepth");
  595. /*
  596. Set up and link to the model shader programs
  597. */
  598. if(!LoadModelShader(m_ModelShader, eMODEL_SHADER, pErrorStr))
  599. {
  600. return false;
  601. }
  602. if(!LoadModelShader(m_FogModelShader, eSHADER_SIZE + eFOG_MODEL_SHADER, pErrorStr))
  603. {
  604. return false;
  605. }
  606. if(!LoadModelShader(m_LightModelShader, eSHADER_SIZE + eLIGHT_MODEL_SHADER, pErrorStr))
  607. {
  608. return false;
  609. }
  610. /*
  611. Set up and link to the Tex2D shader program
  612. */
  613. const char* aszTex2DAttribs[] = { "inVertex", "inNormal", "inTexCoord"};
  614. if (PVRTCreateProgram(&m_Tex2DShader.uiId, m_auiVertShaderIds[eTEX2D_SHADER], m_auiFragShaderIds[eTEX2D_SHADER], aszTex2DAttribs, 3, pErrorStr))
  615. {
  616. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  617. return false;
  618. }
  619. glUniform1i(glGetUniformLocation(m_Tex2DShader.uiId, "Texture"),0);
  620. m_Tex2DShader.uiMVPMatrixLoc = glGetUniformLocation(m_Tex2DShader.uiId, "MVPMatrix");
  621. /*
  622. Set up and link to plane texturing shader program
  623. */
  624. const char* aszPlaneTexAttribs[] = { "inVertex"};
  625. if (PVRTCreateProgram(&m_PlaneTexShader.uiId, m_auiVertShaderIds[ePLANE_TEX_SHADER], m_auiFragShaderIds[ePLANE_TEX_SHADER], aszPlaneTexAttribs, 1, pErrorStr))
  626. {
  627. PVRShellSet(prefExitMessage, pErrorStr->c_str());
  628. return false;
  629. }
  630. glUniform1i(glGetUniformLocation(m_PlaneTexShader.uiId, "Texture"),0);
  631. m_PlaneTexShader.uiMVPMatrixLoc = glGetUniformLocation(m_PlaneTexShader.uiId, "MVPMatrix");
  632. m_PlaneTexShader.uiRcpWindowSizeLoc = glGetUniformLocation(m_PlaneTexShader.uiId, "RcpWindowSize");
  633. return true;
  634. }
  635. /*!****************************************************************************
  636. @Function LoadVbos
  637. @Output pErrorStr A string describing the error on failure
  638. @Description Loads data into vertex buffer objects
  639. ******************************************************************************/
  640. bool OGLES2Water::LoadVbos(CPVRTString* pErrorStr)
  641. {
  642. // Load models into VBOs
  643. for(GLuint j = 0 ; j < c_uiNoOfModels; ++j)
  644. {
  645. if(!m_Mesh[j].pMesh[0].pInterleaved)
  646. {
  647. *pErrorStr = "ERROR: The demo requires the pod data to be interleaved. Please re-export with the interleaved option enabled.";
  648. return false;
  649. }
  650. if(!m_apuiModelVbo[j]) m_apuiModelVbo[j] = new GLuint[m_Mesh[j].nNumMesh];
  651. if(!m_apuiModelIndexVbo[j]) m_apuiModelIndexVbo[j] = new GLuint[m_Mesh[j].nNumMesh];
  652. /*
  653. Load vertex data of all meshes in the scene into VBOs
  654. The meshes have been exported with the "Interleave Vectors" option,
  655. so all data is interleaved in the buffer at pMesh->pInterleaved.
  656. Interleaving data improves the memory access pattern and cache efficiency,
  657. thus it can be read faster by the hardware.
  658. */
  659. glGenBuffers(m_Mesh[j].nNumMesh, m_apuiModelVbo[j]);
  660. for (unsigned int i = 0; i < m_Mesh[j].nNumMesh; ++i)
  661. {
  662. // Load vertex data into buffer object
  663. SPODMesh& Mesh = m_Mesh[j].pMesh[i];
  664. unsigned int uiSize = Mesh.nNumVertex * Mesh.sVertex.nStride;
  665. glBindBuffer(GL_ARRAY_BUFFER, m_apuiModelVbo[j][i]);
  666. glBufferData(GL_ARRAY_BUFFER, uiSize, Mesh.pInterleaved, GL_STATIC_DRAW);
  667. // Load index data into buffer object if available
  668. m_apuiModelIndexVbo[j][i] = 0;
  669. if (Mesh.sFaces.pData)
  670. {
  671. glGenBuffers(1, &m_apuiModelIndexVbo[j][i]);
  672. uiSize = PVRTModelPODCountIndices(Mesh) * sizeof(GLshort);
  673. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_apuiModelIndexVbo[j][i]);
  674. glBufferData(GL_ELEMENT_ARRAY_BUFFER, uiSize, Mesh.sFaces.pData, GL_STATIC_DRAW);
  675. }
  676. }
  677. glBindBuffer(GL_ARRAY_BUFFER, 0);
  678. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  679. }
  680. // Skybox
  681. glGenBuffers(1,&m_auiVBOIds[eSKYBOX_VBO]);
  682. glBindBuffer(GL_ARRAY_BUFFER,m_auiVBOIds[eSKYBOX_VBO]);
  683. glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*24, m_SkyboxVertices, GL_STATIC_DRAW);
  684. glBindBuffer(GL_ARRAY_BUFFER,0);
  685. return true;
  686. }
  687. /*!****************************************************************************
  688. @Function InitApplication
  689. @Return bool true if no error occured
  690. @Description Code in InitApplication() will be called by PVRShell once per
  691. run, before the rendering context is created.
  692. Used to initialize variables that are not dependant on it
  693. (e.g. external modules, loading meshes, etc.)
  694. If the rendering context is lost, InitApplication() will
  695. not be called again.
  696. ******************************************************************************/
  697. bool OGLES2Water::InitApplication()
  698. {
  699. #ifdef DEBUG_MODE
  700. PVRShellSet(prefSwapInterval,0); // Disable v-sync for testing
  701. m_bPause = true; // Pause initially as a benchmark reference point
  702. #else
  703. m_bPause = false; // NOTE: Should be set to false!
  704. #endif
  705. // Set null pointers for all models
  706. for(GLuint i = 0 ; i < c_uiNoOfModels; ++i)
  707. {
  708. m_apuiModelVbo[i] = 0;
  709. m_apuiModelIndexVbo[i] = 0;
  710. m_apuiModelTextureIds[i] = 0;
  711. }
  712. // Get and set the read path for content files
  713. CPVRTResourceFile::SetReadPath((char*)PVRShellGet(prefReadPath));
  714. // Set timer variables
  715. m_ulCurrentTime = PVRShellGetTime();
  716. m_ulPreviousTime = m_ulCurrentTime;
  717. m_fCount = 0;
  718. m_uiFrameCount = 0;
  719. m_uiFPS = 0;
  720. // Load meshes
  721. for(GLuint i = 0 ; i < c_uiNoOfModels; ++i)
  722. {
  723. if( m_Mesh[i].ReadFromFile(c_aszModelFiles[i]) != PVR_SUCCESS)
  724. {
  725. PVRShellSet(prefExitMessage, "ERROR: Couldn't load the .pod file\n");
  726. return false;
  727. }
  728. }
  729. // Set UI variables
  730. m_iCurrentUIOption = 0;
  731. ResetVariables();
  732. // Set animation variables
  733. m_fFOV = 60.0f * (PVRT_PI/180.0f);
  734. m_fFrame = 0;
  735. return true;
  736. }
  737. /*!****************************************************************************
  738. @Function ResetVariables
  739. @Description Resets all variables to their original value. This allows
  740. the user to reset the scene during run-time
  741. ******************************************************************************/
  742. void OGLES2Water::ResetVariables()
  743. {
  744. #ifdef FREE_CAMERA_MODE
  745. // Set camera variables
  746. m_vEyePos = PVRTVec3(0.0001f, 100.0001f, 400.0001f); // Slight offset is used to prevent divide by
  747. m_vLookAt = PVRTVec3(0.0001f, 10.0001f, 0.0001f); // zero when altering the camera position and orientation
  748. #endif
  749. m_vCamUp = PVRTVec3(0.00f, 1.0001f, 0.00f);
  750. // Set light direction
  751. m_vLightDirection = PVRTVec4(1.0f,-0.5f,-1.0f,0.0f);
  752. // Set variables
  753. m_vPlaneWater = PVRTVec4(0.0f, 1.0f, 0.0f, 0.0f);
  754. m_vWaterColour = PVRTVec4(0.3f,0.35f,0.35f,1.0f);
  755. m_fWaterHeight = 0.0f;
  756. m_fMaxFogDepth = 100.0f;
  757. m_fWaveDistortion = 50.0f;
  758. m_bFogDepth = false;
  759. m_fWaterArtefactFix = 2.5f;
  760. m_fBoatSpeed = 0.05f;
  761. m_uiTerrainNodeIndex = 10;
  762. // Normal map values
  763. m_vBumpVelocity0 = PVRTVec2(0.016f,-0.014f);
  764. m_vBumpTranslation0 = PVRTVec3(0.0f,0.0f,0.0f); // No translation should be applied
  765. m_vBumpScale0 = PVRTVec2(0.0012f,0.0012f);
  766. m_vBumpVelocity1 = PVRTVec2(0.025f,-0.03f);
  767. m_vBumpTranslation1 = PVRTVec3(0.0f,0.0f,0.0f); // No translation should be applied
  768. m_vBumpScale1 = PVRTVec2(0.0005f,0.0005f);
  769. m_bShaderRefraction = true;
  770. m_bShaderFogging = true;
  771. m_bShaderFresnel = true;
  772. m_bDisplayDebugWindows = false;
  773. m_bClipPlane = false;
  774. }
  775. /*!****************************************************************************
  776. @Function QuitApplication
  777. @Return bool true if no error occured
  778. @Description Code in QuitApplication() will be called by PVRShell once per
  779. run, just before exiting the program.
  780. If the rendering context is lost, QuitApplication() will
  781. not be called.
  782. ******************************************************************************/
  783. bool OGLES2Water::QuitApplication()
  784. {
  785. // Free the memory allocated for the scene
  786. for(GLuint i = 0 ; i < c_uiNoOfModels ; ++i)
  787. {
  788. delete[] m_apuiModelVbo[i];
  789. delete[] m_apuiModelIndexVbo[i];
  790. }
  791. return true;
  792. }
  793. /*!****************************************************************************
  794. @Function InitView
  795. @Return bool true if no error occured
  796. @Description Code in InitView() will be called by PVRShell upon
  797. initialization or after a change in the rendering context.
  798. Used to initialize variables that are dependant on the rendering
  799. context (e.g. textures, vertex buffers, etc.)
  800. ******************************************************************************/
  801. bool OGLES2Water::InitView()
  802. {
  803. CPVRTString ErrorStr;
  804. // Create the skybox
  805. PVRTCreateSkybox( 1500.0f, true, 512, &m_SkyboxVertices, &m_SkyboxTexCoords);
  806. /*
  807. Load textures
  808. */
  809. if (!LoadTextures(&ErrorStr))
  810. {
  811. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  812. return false;
  813. }
  814. /*
  815. Load in the vertex buffered objects
  816. */
  817. if(!LoadVbos(&ErrorStr))
  818. {
  819. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  820. return false;
  821. }
  822. /*
  823. Load and compile the shaders & link programs
  824. */
  825. if (!LoadShaders(&ErrorStr))
  826. {
  827. PVRShellSet(prefExitMessage, ErrorStr.c_str());
  828. return false;
  829. }
  830. // Is the screen rotated?
  831. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  832. /*
  833. Initialize Print3D
  834. */
  835. if(m_Print3D.SetTextures(0,PVRShellGet(prefWidth),PVRShellGet(prefHeight), bRotate) != PVR_SUCCESS)
  836. {
  837. PVRShellSet(prefExitMessage, "ERROR: Cannot initialise Print3D\n");
  838. return false;
  839. }
  840. /*
  841. Calculate the projection and view matrices
  842. */
  843. SetProjection();
  844. SetView();
  845. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iOriginalFBO);
  846. // Enable culling and depth test
  847. glCullFace(GL_BACK);
  848. glEnable(GL_CULL_FACE);
  849. glEnable(GL_DEPTH_TEST);
  850. // Use the water colour for clearing
  851. glClearColor(m_vWaterColour.x, m_vWaterColour.y, m_vWaterColour.z, 1.0f);
  852. glGenFramebuffers(eFBO_SIZE, m_auiFBOIds);
  853. glGenRenderbuffers(eFBO_SIZE, m_auiDepthBuffer);
  854. // Reflection and refraction FBO
  855. for(GLuint i = 0; i < eFBO_SIZE - 1; ++i)
  856. {
  857. glBindFramebuffer(GL_FRAMEBUFFER, m_auiFBOIds[i]);
  858. glCullFace(GL_BACK);
  859. glEnable(GL_CULL_FACE);
  860. glEnable(GL_DEPTH_TEST);
  861. // Attach the texture that the frame buffer will render to
  862. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiRendToTexture[i],0);
  863. glClear(GL_COLOR_BUFFER_BIT);
  864. // Create anda attach a depth buffer
  865. glBindRenderbuffer(GL_RENDERBUFFER, m_auiDepthBuffer[i]);
  866. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, c_uiTexSize, c_uiTexSize);
  867. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer[i]);
  868. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  869. {
  870. PVRShellSet(prefExitMessage,"ERROR: Frame buffer did not set up correctly\n");
  871. return false;
  872. }
  873. }
  874. // The water texture size may be different from the reflection & refraction textures, so it is set up seperately
  875. glBindFramebuffer(GL_FRAMEBUFFER, m_auiFBOIds[eWATER_FBO]);
  876. glCullFace(GL_BACK);
  877. glEnable(GL_CULL_FACE);
  878. glEnable(GL_DEPTH_TEST);
  879. // Attach the texture that the frame buffer will render to
  880. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_auiRendToTexture[eWATER_FBO],0);
  881. glClear(GL_COLOR_BUFFER_BIT);
  882. // Create anda attach a depth buffer
  883. glBindRenderbuffer(GL_RENDERBUFFER, m_auiDepthBuffer[eWATER_FBO]);
  884. glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, c_uiWaterTexSize, c_uiWaterTexSize);
  885. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_auiDepthBuffer[eWATER_FBO]);
  886. if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  887. {
  888. PVRShellSet(prefExitMessage,"ERROR: Frame buffer did not set up correctly\n");
  889. return false;
  890. }
  891. // Bind the original frame buffer
  892. glBindFramebuffer(GL_FRAMEBUFFER, m_iOriginalFBO);
  893. return true;
  894. }
  895. /*!****************************************************************************
  896. @Function ReleaseView
  897. @Return bool true if no error occured
  898. @Description Code in ReleaseView() will be called by PVRShell when the
  899. application quits or before a change in the rendering context.
  900. ******************************************************************************/
  901. bool OGLES2Water::ReleaseView()
  902. {
  903. // Delete textures
  904. glDeleteTextures(eTEX_NAME_SIZE,m_auiTextureIds);
  905. glDeleteTextures(eFBO_SIZE, m_auiRendToTexture);
  906. for(GLuint i = 0 ; i < c_uiNoOfModels ; ++i)
  907. {
  908. glDeleteTextures(m_Mesh[i].nNumMaterial, &m_apuiModelTextureIds[i][0]);
  909. delete[] m_apuiModelTextureIds[i];
  910. m_apuiModelTextureIds[i] = 0;
  911. }
  912. // Delete program and shader objects
  913. glDeleteProgram(m_ReflectionOnlyShader.uiId);
  914. glDeleteProgram(m_SkyboxShader.uiId);
  915. glDeleteProgram(m_Tex2DShader.uiId);
  916. glDeleteProgram(m_FullWaterShader.uiId);
  917. glDeleteProgram(m_BumpReflectionWaterShader.uiId);
  918. glDeleteProgram(m_NoFresnelWaterShader.uiId);
  919. glDeleteProgram(m_ModelShader.uiId);
  920. glDeleteProgram(m_FogModelShader.uiId);
  921. glDeleteProgram(m_PlaneTexShader.uiId);
  922. glDeleteProgram(m_LightModelShader.uiId);
  923. for(GLuint i = 0 ; i < eSHADER_SIZE; ++i)
  924. {
  925. glDeleteShader(m_auiVertShaderIds[i]);
  926. glDeleteShader(m_auiFragShaderIds[i]);
  927. }
  928. // Delete buffer objects
  929. glDeleteBuffers(eVBO_SIZE, m_auiVBOIds);
  930. glDeleteFramebuffers(eFBO_SIZE, m_auiFBOIds);
  931. for(GLuint i = 0; i < c_uiNoOfModels; ++i)
  932. {
  933. glDeleteBuffers(m_Mesh[i].nNumMesh, m_apuiModelVbo[i]);
  934. glDeleteBuffers(m_Mesh[i].nNumMesh, m_apuiModelIndexVbo[i]);
  935. }
  936. // Release Print3D Textures
  937. m_Print3D.ReleaseTextures();
  938. // Destroy the Skybox
  939. PVRTDestroySkybox( m_SkyboxVertices, m_SkyboxTexCoords);
  940. return true;
  941. }
  942. /*!****************************************************************************
  943. @Function RenderScene
  944. @Return bool true if no error occured
  945. @Description Main rendering loop function of the program. The shell will
  946. call this function every frame.
  947. eglSwapBuffers() will be performed by PVRShell automatically.
  948. PVRShell will also manage important OS events.
  949. The user has access to these events through an abstraction
  950. layer provided by PVRShell.
  951. ******************************************************************************/
  952. bool OGLES2Water::RenderScene()
  953. {
  954. UpdateTimer(); // Update timer variables
  955. // Set the scene animation
  956. if(!m_bPause)
  957. {
  958. m_fFrame += ((GLfloat)((m_ulCurrentTime - m_ulPreviousTime) * c_fDemoFrameRate)) * m_fBoatSpeed; // value is scaled by animation speed
  959. if(m_fFrame > m_Mesh[0].nNumFrame - 1)
  960. {
  961. m_fFrame = 0;
  962. }
  963. }
  964. m_Mesh[0].SetFrame(m_fFrame);
  965. // Perform reflection render pass
  966. RenderReflectionTexture();
  967. if(m_bShaderRefraction)
  968. {
  969. RenderRefractionTexture(); // Only perform the refraction render pass if it is needed
  970. }
  971. // Render water texture
  972. if(m_bShaderRefraction && m_bShaderFresnel)
  973. {
  974. RenderWaterTexture(m_FullWaterShader);
  975. }
  976. else if(m_bShaderRefraction)
  977. {
  978. RenderWaterTexture(m_NoFresnelWaterShader);
  979. }
  980. else
  981. {
  982. RenderWaterTexture(m_BumpReflectionWaterShader);
  983. }
  984. // Bind the main frame bufffer
  985. glBindFramebuffer(GL_FRAMEBUFFER, m_iOriginalFBO);
  986. glViewport(0,0, PVRShellGet(prefWidth), PVRShellGet(prefHeight));
  987. // Clear the color and depth buffer
  988. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  989. SetView();
  990. SetProjection(m_fFOV);
  991. /*
  992. Draw the scene
  993. */
  994. DrawScene(m_LightModelShader);
  995. DrawWaterFromTexture();
  996. #ifdef DEBUG_MODE
  997. if(m_bDisplayDebugWindows)
  998. {
  999. // Display reflection, refraction and water textures to debug windows
  1000. DrawTestQuad(m_auiRendToTexture[eREFLECTION_FBO],PVRTVec2(-1.0f,-0.8f));
  1001. DrawTestQuad(m_auiRendToTexture[eREFRACTION_FBO],PVRTVec2(-1.0f,-0.25f));
  1002. DrawTestQuad(m_auiRendToTexture[eWATER_FBO], PVRTVec2(-1.0f, 0.325f));
  1003. }
  1004. #endif
  1005. #ifdef ENABLE_UI
  1006. // UI keyboard input
  1007. if(PVRShellIsKeyPressed(PVRShellKeyNameRIGHT))
  1008. {
  1009. if(++m_iCurrentUIOption >= (int)eUI_SIZE)
  1010. {
  1011. m_iCurrentUIOption = 0;
  1012. }
  1013. }
  1014. if(PVRShellIsKeyPressed(PVRShellKeyNameLEFT))
  1015. {
  1016. if(--m_iCurrentUIOption < 0)
  1017. {
  1018. m_iCurrentUIOption = eUI_SIZE - 1;
  1019. }
  1020. }
  1021. if(PVRShellIsKeyPressed(PVRShellKeyNameSELECT) || PVRShellIsKeyPressed(PVRShellKeyNameACTION1))
  1022. {
  1023. m_bPause = !m_bPause;
  1024. }
  1025. // UI options
  1026. switch(m_iCurrentUIOption)
  1027. {
  1028. case eUI_NULL: break;
  1029. case eTOGGLE_REFRACTION:
  1030. {
  1031. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) || PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1032. {
  1033. m_bShaderRefraction = !m_bShaderRefraction;
  1034. }
  1035. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Toggle refraction : %1i", m_bShaderRefraction);
  1036. break;
  1037. }
  1038. case eTOGGLE_FRESNEL:
  1039. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) || PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1040. {
  1041. m_bShaderFresnel = !m_bShaderFresnel;
  1042. }
  1043. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Toggle Fresnel : %1i", m_bShaderFresnel);
  1044. break;
  1045. case eTOGGLE_FOG:
  1046. {
  1047. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) || PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1048. {
  1049. m_bShaderFogging = !m_bShaderFogging;
  1050. }
  1051. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Toggle depth fogging : %1i", m_bShaderFogging);
  1052. break;
  1053. }
  1054. case eFOG_DEPTH:
  1055. {
  1056. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1057. {
  1058. m_fMaxFogDepth += 1.0f;
  1059. }
  1060. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN) && (m_fMaxFogDepth > 0))
  1061. {
  1062. m_fMaxFogDepth -= 1.0f;
  1063. }
  1064. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Fog depth : %4.2f", m_fMaxFogDepth);
  1065. break;
  1066. }
  1067. case eWAVE_DISTORTION:
  1068. {
  1069. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1070. {
  1071. m_fWaveDistortion += 1.0f;
  1072. }
  1073. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)&& (m_fWaveDistortion - 0.01f >= 0.0f))
  1074. {
  1075. m_fWaveDistortion -= 1.0f;
  1076. }
  1077. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Wave distortion : %4.2f", m_fWaveDistortion);
  1078. break;
  1079. }
  1080. case eARTEFACT_FIX:
  1081. {
  1082. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1083. {
  1084. m_fWaterArtefactFix += 0.1f;
  1085. }
  1086. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)&& (m_fWaterArtefactFix - 0.1f >= 0.0f))
  1087. {
  1088. m_fWaterArtefactFix -= 0.1f;
  1089. }
  1090. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Water's edge artifact fix : %4.2f", m_fWaterArtefactFix);
  1091. break;
  1092. }
  1093. #ifdef DEBUG_MODE
  1094. #ifdef FREE_CAMERA_MODE
  1095. case eMOVE_X:
  1096. {
  1097. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1098. {
  1099. m_vEyePos.x += 1.0f;
  1100. m_vLookAt.x += 1.0f;
  1101. }
  1102. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1103. {
  1104. m_vEyePos.x -= 1.0f;
  1105. m_vLookAt.x -= 1.0f;
  1106. }
  1107. m_Print3D.Print3D(2.0f, 90.0f, 0.75f, 0xffffffff, "MOVE: Camera x-axis : %4.2f \nLook at x-axis : %4.2f", m_vEyePos.x, m_vLookAt.x);
  1108. break;
  1109. }
  1110. case eMOVE_Y:
  1111. {
  1112. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1113. {
  1114. m_vEyePos.y += 1.0f;
  1115. m_vLookAt.y += 1.0f;
  1116. }
  1117. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1118. {
  1119. m_vEyePos.y -= 1.0f;
  1120. m_vLookAt.y -= 1.0f;
  1121. }
  1122. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "MOVE: Camera y-axis : %4.2f \nLook at y-axis : %4.2f", m_vEyePos.y, m_vLookAt.y);
  1123. break;
  1124. }
  1125. case eMOVE_Z:
  1126. {
  1127. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1128. {
  1129. m_vEyePos.z += 1.0f;
  1130. m_vLookAt.z += 1.0f;
  1131. }
  1132. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1133. {
  1134. m_vEyePos.z -= 1.0f;
  1135. m_vLookAt.z -= 1.0f;
  1136. }
  1137. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "MOVE: Camera z-axis : %4.2f \nLook at z-axis : %4.2f", m_vEyePos.z, m_vLookAt.z);
  1138. break;
  1139. }
  1140. case eCAMERA_X:
  1141. {
  1142. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1143. {
  1144. m_vEyePos.x += 1.0f;
  1145. }
  1146. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1147. {
  1148. m_vEyePos.x -= 1.0f;
  1149. }
  1150. m_Print3D.Print3D(2.0f, 90.0f, 0.75f, 0xffffffff, "Camera x-axis : %4.2f", m_vEyePos.x);
  1151. break;
  1152. }
  1153. case eCAMERA_Y:
  1154. {
  1155. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1156. {
  1157. m_vEyePos.y += 1.0f;
  1158. }
  1159. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1160. {
  1161. m_vEyePos.y -= 1.0f;
  1162. }
  1163. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Camera y-axis : %4.2f", m_vEyePos.y);
  1164. break;
  1165. }
  1166. case eCAMERA_Z:
  1167. {
  1168. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1169. {
  1170. m_vEyePos.z += 1.0f;
  1171. }
  1172. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1173. {
  1174. m_vEyePos.z -= 1.0f;
  1175. }
  1176. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Camera z-axis : %4.2f", m_vEyePos.z);
  1177. break;
  1178. }
  1179. case eLOOK_AT_X:
  1180. {
  1181. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1182. {
  1183. m_vLookAt.x += 1.0f;
  1184. }
  1185. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1186. {
  1187. m_vLookAt.x -= 1.0f;
  1188. }
  1189. m_Print3D.Print3D(2.0f, 90.0f, 0.75f, 0xffffffff, "Look at x-axis : %4.2f", m_vLookAt.x);
  1190. break;
  1191. }
  1192. case eLOOK_AT_Y:
  1193. {
  1194. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1195. {
  1196. m_vLookAt.y += 1.0f;
  1197. }
  1198. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1199. {
  1200. m_vLookAt.y -= 1.0f;
  1201. }
  1202. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Look at y-axis : %4.2f", m_vLookAt.y);
  1203. break;
  1204. }
  1205. case eLOOK_AT_Z:
  1206. {
  1207. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1208. {
  1209. m_vLookAt.z += 1.0f;
  1210. }
  1211. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1212. {
  1213. m_vLookAt.z -= 1.0f;
  1214. }
  1215. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Look at z-axis : %4.2f", m_vLookAt.z);
  1216. break;
  1217. }
  1218. #endif
  1219. case eWATER_HEIGHT:
  1220. {
  1221. if (PVRShellIsKeyPressed(PVRShellKeyNameUP))
  1222. {
  1223. m_vPlaneWater.w -= 0.2f;
  1224. }
  1225. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1226. {
  1227. m_vPlaneWater.w += 0.2f;
  1228. }
  1229. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Water height : %4.2f", -m_vPlaneWater.w); // Negate to represent in world space
  1230. break;
  1231. }
  1232. case eWATER_COLOUR_R:
  1233. {
  1234. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) && (m_vWaterColour.x + 0.05f <= 1.0f))
  1235. {
  1236. m_vWaterColour.x += 0.05f;
  1237. }
  1238. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)&& (m_vWaterColour.x - 0.05f > 0.0f))
  1239. {
  1240. m_vWaterColour.x -= 0.05f;
  1241. }
  1242. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Water colour red : %4.2f", m_vWaterColour.x);
  1243. break;
  1244. }
  1245. case eWATER_COLOUR_G:
  1246. {
  1247. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) && (m_vWaterColour.x + 0.05f <= 1.0f))
  1248. {
  1249. m_vWaterColour.y += 0.05f;
  1250. }
  1251. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)&& (m_vWaterColour.x - 0.05f > 0.0f))
  1252. {
  1253. m_vWaterColour.y -= 0.05f;
  1254. }
  1255. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Water colour green : %4.2f", m_vWaterColour.y);
  1256. break;
  1257. }
  1258. case eWATER_COLOUR_B:
  1259. {
  1260. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) && (m_vWaterColour.x + 0.05f <= 1.0f))
  1261. {
  1262. m_vWaterColour.z += 0.05f;
  1263. }
  1264. else if(PVRShellIsKeyPressed(PVRShellKeyNameDOWN)&& (m_vWaterColour.x - 0.05f > 0.0f))
  1265. {
  1266. m_vWaterColour.z -= 0.05f;
  1267. }
  1268. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Water colour blue : %4.2f", m_vWaterColour.z);
  1269. break;
  1270. }
  1271. case eTOGGLE_DEBUG_WINDOWS:
  1272. {
  1273. if (PVRShellIsKeyPressed(PVRShellKeyNameUP) || PVRShellIsKeyPressed(PVRShellKeyNameDOWN))
  1274. {
  1275. m_bDisplayDebugWindows = !m_bDisplayDebugWindows;
  1276. }
  1277. m_Print3D.Print3D(2.0f,90.0f,0.75f, 0xffffffff, "Toggle debug windows : %1i", m_bDisplayDebugWindows);
  1278. break;
  1279. }
  1280. #endif
  1281. }
  1282. #endif
  1283. #ifdef DEBUG_MODE
  1284. // Display debugging data
  1285. m_Print3D.Print3D(2.0f, 10.0f, 0.75f, 0xffffff00, "%4i fps", m_uiFPS);
  1286. #endif
  1287. // Displays the demo name using the Print3D tool. For a detailed explanation, see the training course IntroducingPVRTools
  1288. m_Print3D.DisplayDefaultTitle("Water", "", ePVRTPrint3DLogoIMG);
  1289. m_Print3D.Flush();
  1290. return true;
  1291. }
  1292. /*!****************************************************************************
  1293. @Function RenderReflectionTexture
  1294. @Description Renders the scence (excluding the water) so a reflection
  1295. texture for the frame can be calculated. The water plane is used
  1296. during clipping so that only objects above the water are rendered.
  1297. See section 2.3 of the corresponding white paper for more information
  1298. ******************************************************************************/
  1299. void OGLES2Water::RenderReflectionTexture()
  1300. {
  1301. glBindFramebuffer(GL_FRAMEBUFFER, m_auiFBOIds[eREFLECTION_FBO]); // Bind a frame buffer that has a texture attached (stores the render in a texture)
  1302. glViewport(0,0, c_uiTexSize, c_uiTexSize); // Set the viewport to the texture size
  1303. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  1304. SetView();
  1305. SetProjection(m_fFOV);
  1306. glCullFace(GL_BACK);
  1307. // Mirror the view matrix about the plane.
  1308. PVRTMat4 mMirrorCam(PVRTMat4::Identity());
  1309. mMirrorCam.ptr()[1] = -m_vPlaneWater.x;
  1310. mMirrorCam.ptr()[5] = -m_vPlaneWater.y;
  1311. mMirrorCam.ptr()[9] = -m_vPlaneWater.z;
  1312. mMirrorCam.ptr()[13] = -(2.0f * m_vPlaneWater.w);
  1313. m_mView = m_mView * mMirrorCam;
  1314. ModifyProjectionForClipping(m_vPlaneWater + PVRTVec4(0.0f,0.0f,0.0f,m_fWaterArtefactFix));
  1315. DrawScene(m_LightModelShader);
  1316. glCullFace(GL_FRONT);
  1317. }
  1318. /*!****************************************************************************
  1319. @Function RenderRefractionTexture
  1320. @Description Renders the scence (excluding the water) so that refraction
  1321. (including depth, when enabled) for the frame can be calculated.
  1322. When depth shading is enabled, the skybox is ommited from the render.
  1323. See section 2.4 of the corresponding white paper for more information
  1324. ******************************************************************************/
  1325. void OGLES2Water::RenderRefractionTexture()
  1326. {
  1327. glBindFramebuffer(GL_FRAMEBUFFER, m_auiFBOIds[eREFRACTION_FBO]); // Bind a frame buffer that has a texture and depth texture attached (stores the render in a texture)
  1328. glViewport(0,0, c_uiTexSize, c_uiTexSize);
  1329. // Use the water colour for clearing
  1330. glClearColor(m_vWaterColour.x, m_vWaterColour.y, m_vWaterColour.z, 1.0f);
  1331. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  1332. SetView();
  1333. SetProjection(m_fFOV);
  1334. PVRTVec4 vPlaneView = PVRTVec4( -m_vPlaneWater.x, -m_vPlaneWater.y, -m_vPlaneWater.z, -m_vPlaneWater.w + m_fWaterArtefactFix);
  1335. ModifyProjectionForClipping(vPlaneView);
  1336. // Allow fogging to be toggled by the user
  1337. if(m_bShaderFogging)
  1338. {
  1339. DrawRefractionScene(m_FogModelShader);
  1340. }
  1341. else
  1342. {
  1343. DrawScene(m_LightModelShader);
  1344. }
  1345. }
  1346. /*!****************************************************************************
  1347. @Function RenderWaterTexture
  1348. @Input shaderProgram The water shader program to be applied during the render
  1349. @Description Render the water effect to a lower resolution texture
  1350. that can then be applied to the plane's surface.
  1351. See section 3.3.3 of the corresponding white paper for more information
  1352. ******************************************************************************/
  1353. void OGLES2Water::RenderWaterTexture(const WaterShader& shaderProgram)
  1354. {
  1355. glBindFramebuffer(GL_FRAMEBUFFER, m_auiFBOIds[eWATER_FBO]);
  1356. glViewport(0,0, c_uiWaterTexSize, c_uiWaterTexSize);
  1357. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  1358. SetView();
  1359. SetProjection(m_fFOV);
  1360. DrawMesh(0, m_uiTerrainNodeIndex, m_LightModelShader); // Only draw the terrain
  1361. DrawWater(shaderProgram, c_uiWaterTexSize, c_uiWaterTexSize, m_vPlaneWater);
  1362. }
  1363. /*!****************************************************************************
  1364. @Function DrawScene
  1365. @Input shaderProgram The water shader program to be applied during the render
  1366. @Description Draw all elements of the scene, excluding the water
  1367. ******************************************************************************/
  1368. void OGLES2Water::DrawScene(const ModelShader& shaderProgram)
  1369. {
  1370. // Draw meshes
  1371. DrawMeshScene(shaderProgram);
  1372. // Reset the projection before the skyox so that the sky box wont be clipped, as it should appear infinite.
  1373. SetProjection(m_fFOV);
  1374. DrawSkybox(m_auiTextureIds[eSKYBOX_TEX],m_SkyboxShader, eSKYBOX_VBO, PVRTVec3(0.0, 499.0, 0.0));
  1375. }
  1376. /*!****************************************************************************
  1377. @Function DrawRefractionScene
  1378. @Input shaderProgram The water shader program to be applied during the render
  1379. @Description Draw
  1380. all elements of the scene, excluding the water and the sky box.
  1381. ******************************************************************************/
  1382. void OGLES2Water::DrawRefractionScene(const ModelShader& shaderProgram)
  1383. {
  1384. // Draw meshes
  1385. DrawMeshScene(shaderProgram);
  1386. }
  1387. /*!****************************************************************************
  1388. @Function DrawMesh
  1389. @Input uiModelNumber The element to draw from the POD array
  1390. @Input i32NodeIndex Node index of the mesh to draw
  1391. @Input shaderProgram The water shader program to be applied during the render
  1392. @Description Draws a SPODMesh after the model view matrix has been set and
  1393. the material has been prepared.
  1394. ******************************************************************************/
  1395. void OGLES2Water::DrawMesh(GLuint uiModelNo, int i32NodeIndex, const ModelShader& shaderProgram)
  1396. {
  1397. SPODNode& node = m_Mesh[uiModelNo].pNode[i32NodeIndex];
  1398. int i32MeshIndex = m_Mesh[uiModelNo].pNode[i32NodeIndex].nIdx;
  1399. SPODMesh* pMesh = &m_Mesh[uiModelNo].pMesh[i32MeshIndex];
  1400. // Load the correct texture using the texture lookup table
  1401. GLuint uiTex = 0;
  1402. if(node.nIdxMaterial != -1)
  1403. {
  1404. uiTex = m_apuiModelTextureIds[uiModelNo][node.nIdxMaterial];
  1405. }
  1406. glActiveTexture(GL_TEXTURE0);
  1407. glBindTexture(GL_TEXTURE_2D, uiTex);
  1408. // Use shader program
  1409. glUseProgram(shaderProgram.uiId);
  1410. /*
  1411. Set the shading parameters
  1412. */
  1413. // Extract the world matrix for the model from the POD file
  1414. PVRTMat4 mModel(m_Mesh[uiModelNo].GetWorldMatrix(node));
  1415. PVRTMat4 mModelView(m_mView * mModel);
  1416. glUniformMatrix4fv(shaderProgram.uiModelMatrixLoc,1, GL_FALSE, mModel.ptr());
  1417. PVRTMat4 mMVP(m_mProjection * mModelView);
  1418. glUniformMatrix4fv(shaderProgram.uiMVPMatrixLoc,1, GL_FALSE, mMVP.ptr());
  1419. PVRTVec4 vLightDir(mModel.inverseEx() * m_vLightDirection);
  1420. PVRTVec3 vLightDirModel(vLightDir.x,vLightDir.y,vLightDir.z);
  1421. vLightDirModel.normalize();
  1422. glUniform3fv(shaderProgram.uiLightDirectionLoc, 1, &vLightDirModel.x);
  1423. glUniform1f(shaderProgram.uiWaterHeightLoc, -m_vPlaneWater.w); // Negate the scale to represent the water's distance along the y-axis in world coordinates
  1424. glUniform3fv(shaderProgram.uiFogColourLoc,1, &m_vWaterColour.x); // Only requires the rgb values of colour
  1425. glUniform1f(shaderProgram.uiMaxFogDepthLoc, 1.0f/m_fMaxFogDepth); // Invert fog depth to avoid division in fragment shader
  1426. // bind the VBO for the mesh
  1427. glBindBuffer(GL_ARRAY_BUFFER, m_apuiModelVbo[uiModelNo][i32MeshIndex]);
  1428. // bind the index buffer, won't hurt if the handle is 0
  1429. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_apuiModelIndexVbo[uiModelNo][i32MeshIndex]);
  1430. // Enable the vertex attribute arrays
  1431. glEnableVertexAttribArray(VERTEX_ARRAY);
  1432. glEnableVertexAttribArray(NORMAL_ARRAY);
  1433. glEnableVertexAttribArray(TEXCOORD_ARRAY);
  1434. // Set the vertex attribute offsets
  1435. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sVertex.nStride, pMesh->sVertex.pData);
  1436. glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, pMesh->sNormals.nStride, pMesh->sNormals.pData);
  1437. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, pMesh->psUVW[0].nStride, pMesh->psUVW[0].pData);
  1438. /*
  1439. The geometry can be exported in 4 ways:
  1440. - Indexed Triangle list
  1441. - Non-Indexed Triangle list
  1442. - Indexed Triangle strips
  1443. - Non-Indexed Triangle strips
  1444. */
  1445. if(pMesh->nNumStrips == 0)
  1446. {
  1447. if(m_apuiModelIndexVbo[uiModelNo][i32MeshIndex])
  1448. {
  1449. // Indexed Triangle list
  1450. glDrawElements(GL_TRIANGLES, pMesh->nNumFaces*3, GL_UNSIGNED_SHORT, 0);
  1451. }
  1452. else
  1453. {
  1454. // Non-Indexed Triangle list
  1455. glDrawArrays(GL_TRIANGLES, 0, pMesh->nNumFaces*3);
  1456. }
  1457. }
  1458. else
  1459. {
  1460. for(int i = 0; i < (int)pMesh->nNumStrips; ++i)
  1461. {
  1462. int offset = 0;
  1463. if(m_apuiModelIndexVbo[uiModelNo][i32MeshIndex])
  1464. {
  1465. // Indexed Triangle strips
  1466. glDrawElements(GL_TRIANGLE_STRIP, pMesh->pnStripLength[i]+2, GL_UNSIGNED_SHORT, (GLshort*)(offset*2));
  1467. }
  1468. else
  1469. {
  1470. // Non-Indexed Triangle strips
  1471. glDrawArrays(GL_TRIANGLE_STRIP, offset, pMesh->pnStripLength[i]+2);
  1472. }
  1473. offset += pMesh->pnStripLength[i]+2;
  1474. }
  1475. }
  1476. // Safely disable the vertex attribute arrays
  1477. glDisableVertexAttribArray(VERTEX_ARRAY);
  1478. glDisableVertexAttribArray(NORMAL_ARRAY);
  1479. glDisableVertexAttribArray(TEXCOORD_ARRAY);
  1480. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1481. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  1482. }
  1483. /*!****************************************************************************
  1484. @Function DrawMeshScene
  1485. @Input shaderProgram The shader program that needs to be applied to all meshes
  1486. @Description Draws all of the meshes in the scene with the given shader program
  1487. ******************************************************************************/
  1488. void OGLES2Water::DrawMeshScene(const ModelShader &shaderProgram)
  1489. {
  1490. for (unsigned int i = 0; i < m_Mesh[0].nNumMeshNode; ++i)
  1491. {
  1492. DrawMesh(0, i, shaderProgram);
  1493. }
  1494. }
  1495. /*!****************************************************************************
  1496. @Function DrawInfinitePlane
  1497. @Input vPlane The plane (in the form (A,B,C,D)) that represents the plane in the world
  1498. @Input fFarDistance The far clip plane distance
  1499. @Description Draws an infinite plane using variables from the program
  1500. ******************************************************************************/
  1501. void OGLES2Water::DrawInfinitePlane(const PVRTVec4& vPlane, float fFarDistance)
  1502. {
  1503. // Calc ViewProjInv matrix
  1504. PVRTMat4 mTmp(m_mProjection * m_mView);
  1505. mTmp = mTmp.inverseEx();
  1506. // Calculate the water plane
  1507. m_i32WaterPlaneNo = PVRTMiscCalculateInfinitePlane(&m_pvPlaneWater->x, sizeof(*m_pvPlaneWater), &vPlane, &mTmp, &m_vEyePos, fFarDistance);
  1508. glDisable(GL_CULL_FACE);
  1509. // Enable the vertex attribute arrays
  1510. glEnableVertexAttribArray(VERTEX_ARRAY);
  1511. // Draw water
  1512. if(m_i32WaterPlaneNo)
  1513. {
  1514. // Set the vertex attribute offsets
  1515. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, &m_pvPlaneWater->x);
  1516. // Draw primitive
  1517. glDrawArrays(GL_TRIANGLE_FAN, 0, m_i32WaterPlaneNo);
  1518. }
  1519. // Safely disable the vertex attribute arrays
  1520. glDisableVertexAttribArray(VERTEX_ARRAY);
  1521. glEnable(GL_CULL_FACE);
  1522. }
  1523. /*!****************************************************************************
  1524. @Function DrawWater
  1525. @Input shaderProgram The shader to be applied to the water plane
  1526. @Input uiViewPortWidth The width of current viewport
  1527. @Input uiViewPortHeight The height of the current viewport
  1528. @Input vPlane The plane (in the form (A,B,C,D)) that represents the plane in the world
  1529. @Input fFarDistance The far clip plane distance
  1530. @Description Draws the water
  1531. ******************************************************************************/
  1532. void OGLES2Water::DrawWater(const WaterShader& shaderProgram, GLuint uiViewPortWidth, GLuint uiViewPortHeight, const PVRTVec4& vPlane, float fFarDistance)
  1533. {
  1534. // Use shader program
  1535. glUseProgram(shaderProgram.uiId);
  1536. // Bind texture
  1537. glActiveTexture(GL_TEXTURE0);
  1538. glBindTexture(GL_TEXTURE_2D, m_auiTextureIds[eWATER_NORMAL_TEX]);
  1539. glActiveTexture(GL_TEXTURE1);
  1540. glBindTexture(GL_TEXTURE_2D, m_auiRendToTexture[eREFLECTION_FBO]);
  1541. glActiveTexture(GL_TEXTURE2);
  1542. glBindTexture(GL_TEXTURE_2D, m_auiRendToTexture[eREFRACTION_FBO]);
  1543. glActiveTexture(GL_TEXTURE3);
  1544. glBindTexture(GL_TEXTURE_CUBE_MAP, m_uiNormalisationCubeMap);
  1545. // Set model view matrix for water
  1546. PVRTMat4 mModelView(m_mView); // Model matrix is assumed to be identity
  1547. glUniformMatrix4fv(shaderProgram.uiMVMatrixLoc, 1, GL_FALSE, mModelView.ptr());
  1548. // Set model view projection matrix for water
  1549. PVRTMat4 mMVP(m_mProjection * mModelView);
  1550. glUniformMatrix4fv(shaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.ptr());
  1551. // Set eye position in model space
  1552. PVRTVec4 vEyePosModel(mModelView.inverseEx() * PVRTVec4(0.0f, 0.0f, 0.0f, 1.0f));
  1553. glUniform3fv(shaderProgram.uiEyePosLoc, 1, &vEyePosModel.x);
  1554. /*
  1555. Set the remaining shader parameters
  1556. */
  1557. glUniform4fv(shaderProgram.uiWaterColourLoc,1, &m_vWaterColour.x);
  1558. if(!m_bPause)
  1559. {
  1560. m_vBumpTranslation0 += m_vBumpVelocity0 * m_fDeltaTime;
  1561. m_vBumpTranslation0 = PVRTVec2( fmod(m_vBumpTranslation0.x, 1.0f),
  1562. fmod(m_vBumpTranslation0.y, 1.0f));
  1563. m_vBumpTranslation1 += m_vBumpVelocity1 * m_fDeltaTime;
  1564. m_vBumpTranslation1 = PVRTVec2( fmod(m_vBumpTranslation1.x, 1.0f),
  1565. fmod(m_vBumpTranslation1.y, 1.0f));
  1566. }
  1567. glUniform2fv(shaderProgram.uiBumpTranslation0Loc,1, &m_vBumpTranslation0.x);
  1568. glUniform2fv(shaderProgram.uiBumpScale0Loc,1, &m_vBumpScale0.x);
  1569. glUniform2fv(shaderProgram.uiBumpTranslation0Loc,1, &m_vBumpTranslation1.x);
  1570. glUniform2fv(shaderProgram.uiBumpScale1Loc,1, &m_vBumpScale1.x);
  1571. glUniform1f(shaderProgram.uiWaveDistortionLoc, m_fWaveDistortion);
  1572. m_vRcpWindowSize.x = 1.0f/uiViewPortWidth;
  1573. m_vRcpWindowSize.y = 1.0f/uiViewPortHeight;
  1574. glUniform2fv(shaderProgram.uiRcpWindowSizeLoc,1, &m_vRcpWindowSize.x);
  1575. DrawInfinitePlane(vPlane, fFarDistance);
  1576. }
  1577. /*!****************************************************************************
  1578. @Function DrawWaterFromTexture
  1579. @Input fFarDistance The far clip plane distance
  1580. @Description Renders a plane that is textured with the texture created in the
  1581. water texture render pass
  1582. ******************************************************************************/
  1583. void OGLES2Water::DrawWaterFromTexture(float fFarDistance)
  1584. {
  1585. // Use shader program
  1586. glUseProgram(m_PlaneTexShader.uiId);
  1587. // Bind texture
  1588. glActiveTexture(GL_TEXTURE0);
  1589. glBindTexture(GL_TEXTURE_2D, m_auiRendToTexture[eWATER_FBO]);
  1590. PVRTMat4 mModelView(m_mView); // Model is assumed to be the identity matrix
  1591. PVRTMat4 mMVP(m_mProjection * mModelView);
  1592. glUniformMatrix4fv(m_PlaneTexShader.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.ptr());
  1593. m_vRcpWindowSize.x = 1.0f/PVRShellGet(prefWidth);
  1594. m_vRcpWindowSize.y = 1.0f/PVRShellGet(prefHeight);
  1595. glUniform2fv(m_PlaneTexShader.uiRcpWindowSizeLoc,1, &m_vRcpWindowSize.x);
  1596. DrawInfinitePlane(m_vPlaneWater, fFarDistance);
  1597. }
  1598. /*!****************************************************************************
  1599. @Function DrawSkybox
  1600. @Input uiCubeMapHandle The handle to the skybox's cube map
  1601. @Input shaderProgram The shader to apply to the skybox
  1602. @Input uiVboId The id of the skybox's VBO
  1603. @Input vTranslation The translation appied to the skybox
  1604. @Description Draws the skybox
  1605. ******************************************************************************/
  1606. void OGLES2Water::DrawSkybox(GLuint uiCubeMapHandle, const SkyboxShader& shaderProgram, GLuint uiVboId,
  1607. const PVRTVec3& vTranslation)
  1608. {
  1609. // Use shader program
  1610. glUseProgram(shaderProgram.uiId);
  1611. // Bind texture
  1612. glActiveTexture(GL_TEXTURE0);
  1613. glBindTexture(GL_TEXTURE_CUBE_MAP, uiCubeMapHandle);
  1614. // Rotate and Translate the model matrix (if required)
  1615. PVRTMat4 mModel(PVRTMat4::Identity());
  1616. mModel *= mModel.Translation(vTranslation.x,vTranslation.y,vTranslation.z);
  1617. glUniformMatrix4fv(shaderProgram.uiModelMatrixLoc, 1, GL_FALSE, mModel.ptr());
  1618. // Set model view projection matrix
  1619. PVRTMat4 mModelView(m_mView * mModel);
  1620. PVRTMat4 mMVP(m_mProjection * mModelView);
  1621. glUniformMatrix4fv(shaderProgram.uiMVPMatrixLoc, 1, GL_FALSE, mMVP.ptr());
  1622. // Set eye position in model space
  1623. PVRTVec4 vEyePosModel(mModelView.inverse() * PVRTVec4(0.0f, 0.0f, 0.0f, 1.0f));
  1624. glUniform3fv(shaderProgram.uiEyePosLoc, 1, &vEyePosModel.x);
  1625. glUniform1f(shaderProgram.uiWaterHeightLoc, -m_vPlaneWater.w); // Negate the scale to represent it in world sapce
  1626. glUniform3fv(shaderProgram.uiFogColourLoc,1, &m_vWaterColour.x); // Only requires the rgb values of colour
  1627. glUniform1f(shaderProgram.uiMaxFogDepthLoc, 1.0f/m_fMaxFogDepth); // Invert fog depth to save division in fragment shader
  1628. glDisable(GL_CULL_FACE);
  1629. // bind the VBO for the mesh
  1630. glBindBuffer(GL_ARRAY_BUFFER, m_auiVBOIds[uiVboId]);
  1631. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, NULL);
  1632. // Enable the vertex attribute arrays
  1633. glEnableVertexAttribArray(VERTEX_ARRAY);
  1634. for(int i = 0; i < 6; ++i)
  1635. {
  1636. // Draw primitive
  1637. glDrawArrays(GL_TRIANGLE_STRIP, i*4, 4);
  1638. }
  1639. // Safely disable the vertex attribute arrays
  1640. glDisableVertexAttribArray(VERTEX_ARRAY);
  1641. glEnable(GL_CULL_FACE);
  1642. glBindBuffer(GL_ARRAY_BUFFER, 0);
  1643. }
  1644. /*!****************************************************************************
  1645. @Function DrawTestQuad
  1646. @Input uiTextureHandle The texture to apply to the quad
  1647. @Input vBottomLeftPosition The bottom left position of the quad on the screen
  1648. @Description Draws a small quad to the screen where textures like reflection etc
  1649. can be drawn for debugging purposes
  1650. ******************************************************************************/
  1651. void OGLES2Water::DrawTestQuad(GLuint uiTextureHandle, const PVRTVec2 &vBottomLeftPosition)
  1652. {
  1653. // Check the ortho values!
  1654. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  1655. m_mProjection = PVRTMat4::Ortho(-1,1,1,-1,0,1,PVRTMat4::OGL, bRotate);
  1656. PVRTVec4 vVertices[4];
  1657. PVRTVec2 vTexCoords[4];
  1658. GLfloat fQuadSize = 0.5f;
  1659. vVertices[0] = PVRTVec4(vBottomLeftPosition.x, vBottomLeftPosition.y + fQuadSize, 0, 1);
  1660. vVertices[1] = PVRTVec4(vBottomLeftPosition.x, vBottomLeftPosition.y, 0, 1);
  1661. vVertices[2] = PVRTVec4(vBottomLeftPosition.x + fQuadSize, vBottomLeftPosition.y, 0, 1);
  1662. vVertices[3] = PVRTVec4(vBottomLeftPosition.x + fQuadSize, vBottomLeftPosition.y + fQuadSize, 0, 1);
  1663. vTexCoords[0] = PVRTVec2(0,1);
  1664. vTexCoords[1] = PVRTVec2(0,0);
  1665. vTexCoords[2] = PVRTVec2(1,0);
  1666. vTexCoords[3] = PVRTVec2(1,1);
  1667. // Use shader program
  1668. glUseProgram(m_Tex2DShader.uiId);
  1669. glActiveTexture(GL_TEXTURE0);
  1670. glBindTexture(GL_TEXTURE_2D, uiTextureHandle);
  1671. // Dont pass in MVP as you want to align quad with screen (projection will distort)
  1672. glUniformMatrix4fv(m_Tex2DShader.uiMVPMatrixLoc, 1, GL_FALSE, m_mProjection.ptr());
  1673. glDisable(GL_CULL_FACE);
  1674. // Enable the vertex attribute arrays
  1675. glEnableVertexAttribArray(VERTEX_ARRAY);
  1676. glEnableVertexAttribArray(TEXCOORD_ARRAY);
  1677. glVertexAttribPointer(VERTEX_ARRAY, 4, GL_FLOAT, GL_FALSE, 0, &vVertices);
  1678. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, &vTexCoords);
  1679. // Draw primitive
  1680. glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  1681. // Safely disable the vertex attribute arrays
  1682. glDisableVertexAttribArray(VERTEX_ARRAY);
  1683. glDisableVertexAttribArray(TEXCOORD_ARRAY);
  1684. glEnable(GL_CULL_FACE);
  1685. }
  1686. /*!****************************************************************************
  1687. @Function SetProjection
  1688. @Input fVOV The field of view required.
  1689. @Input fFarClip The far clip plane
  1690. @Description Sets the projection matrix using the width, height, near clipping,
  1691. far clipping etc.
  1692. ******************************************************************************/
  1693. void OGLES2Water::SetProjection(const float fFOV, const float fFarClip)
  1694. {
  1695. bool bRotate = PVRShellGet(prefIsRotated) && PVRShellGet(prefFullScreen);
  1696. const float fAspect = (float)PVRShellGet(prefWidth)/(float)PVRShellGet(prefHeight);
  1697. m_mProjection = PVRTMat4::PerspectiveFovRH(fFOV, fAspect, CAM_NEAR, fFarClip, PVRTMat4::OGL, bRotate);
  1698. }
  1699. /*!****************************************************************************
  1700. @Function SetView
  1701. @Description Sets the view matrix using the camera variables
  1702. ******************************************************************************/
  1703. void OGLES2Water::SetView()
  1704. {
  1705. #ifdef FREE_CAMERA_MODE
  1706. m_mView = PVRTMat4::LookAtRH(m_vEyePos, m_vLookAt, m_vCamUp);
  1707. #else
  1708. int i32CamID = m_Mesh[0].pNode[m_Mesh[0].nNumMeshNode + m_Mesh[0].nNumLight + c_uiCamera].nIdx;
  1709. // Get the camera position, target and field of view
  1710. if(m_Mesh[0].pCamera[i32CamID].nIdxTarget != -1)
  1711. {
  1712. m_fFOV = m_Mesh[0].GetCameraPos(m_vEyePos, m_vLookAt, c_uiCamera); // vLookAt is taken from the target node
  1713. }
  1714. else
  1715. {
  1716. m_fFOV = m_Mesh[0].GetCamera(m_vEyePos, m_vLookAt, m_vCamUp, c_uiCamera); // vLookAt is calculated from the rotation
  1717. }
  1718. // Create the view matrix from the camera information extracted from the pod
  1719. m_mView = PVRTMat4::LookAtRH(m_vEyePos, m_vLookAt, m_vCamUp);
  1720. #endif
  1721. }
  1722. /*!****************************************************************************
  1723. @Function ModifyProjectionForClipping
  1724. @Input vClipPlane The user defined clip plane
  1725. @Description Modifies the projection matrix so that the near clipping plane
  1726. matches that of the clip plane that has been passed in. This allows
  1727. the projection matrix to be used to perform clipping -
  1728. See section 3.1 of the corresponding white paper for more information
  1729. ******************************************************************************/
  1730. void OGLES2Water::ModifyProjectionForClipping(const PVRTVec4 &vClipPlane)
  1731. {
  1732. PVRTVec4 vClipPlaneView(vClipPlane * m_mView.inverseEx()); // put clip plane into view coords
  1733. /*
  1734. Calculate the clip-space corner point opposite the clipping plane
  1735. and transform it into camera space by multiplying it by the inverse
  1736. projection matrix.
  1737. */
  1738. PVRTVec4 vClipSpaceCorner(sgn(vClipPlaneView.x),sgn(vClipPlaneView.y),1.0f,1.0f);
  1739. vClipSpaceCorner *= m_mProjection.inverseEx();
  1740. // Calculate the scaled plane vector
  1741. PVRTVec4 vScaledPlane = vClipPlaneView * (2.0f / vClipSpaceCorner.dot(vClipPlaneView));
  1742. // Replace the third row of the matrix
  1743. m_mProjection.ptr()[2] = vScaledPlane.x;
  1744. m_mProjection.ptr()[6] = vScaledPlane.y;
  1745. m_mProjection.ptr()[10] = vScaledPlane.z + 1.0f;
  1746. m_mProjection.ptr()[14] = vScaledPlane.w;
  1747. }
  1748. //////////////////////////////////////////////////////////////////////////////////////////
  1749. // // Generate normalisation cube map
  1750. // Downloaded from: www.paulsprojects.net
  1751. // Created: 20th July 2002
  1752. //
  1753. // Copyright (c) 2006, Paul Baker
  1754. // Distributed under the New BSD Licence. (http://www.paulsprojects.net/NewBSDLicense.txt)
  1755. //////////////////////////////////////////////////////////////////////////////////////////
  1756. /*!****************************************************************************
  1757. @Function GenerateNormalisationCubeMap
  1758. @Input uiTextureSize The size of the cube map's textures
  1759. @Description Generates a normalization cube map for the shaders to use -
  1760. See section 3.3.1 of the whitepaper for more information
  1761. ******************************************************************************/
  1762. bool OGLES2Water::GenerateNormalisationCubeMap(int uiTextureSize)
  1763. {
  1764. // variables
  1765. float fOffset = 0.5f;
  1766. float fHalfSize = uiTextureSize *0.5f;
  1767. PVRTVec3 vTemp;
  1768. unsigned char* pByte;
  1769. unsigned char* pData = new unsigned char[uiTextureSize*uiTextureSize*3];
  1770. if(!pData)
  1771. {
  1772. PVRShellOutputDebug("Unable to allocate memory for texture data for cube map\n");
  1773. return false;
  1774. }
  1775. // Positive X
  1776. pByte = pData;
  1777. for(int j = 0; j < uiTextureSize; ++j)
  1778. {
  1779. for(int i = 0; i < uiTextureSize; ++i)
  1780. {
  1781. vTemp.x = fHalfSize;
  1782. vTemp.y = -(j + fOffset - fHalfSize);
  1783. vTemp.z = -(i + fOffset - fHalfSize);
  1784. // normalize, pack 0 to 1 here, and normalize again
  1785. vTemp = vTemp.normalize() *0.5 + 0.5;
  1786. pByte[0] = (unsigned char)(vTemp.x * 255);
  1787. pByte[1] = (unsigned char)(vTemp.y * 255);
  1788. pByte[2] = (unsigned char)(vTemp.z * 255);
  1789. pByte += 3;
  1790. }
  1791. }
  1792. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1793. // Negative X
  1794. pByte = pData;
  1795. for(int j = 0; j < uiTextureSize; ++j)
  1796. {
  1797. for(int i = 0; i < uiTextureSize; ++i)
  1798. {
  1799. vTemp.x = -fHalfSize;
  1800. vTemp.y = -(j + fOffset - fHalfSize);
  1801. vTemp.z = (i + fOffset - fHalfSize);
  1802. // normalize, pack 0 to 1 here, and normalize again
  1803. vTemp = vTemp.normalize() *0.5 + 0.5;
  1804. pByte[0] = (unsigned char)(vTemp.x * 255);
  1805. pByte[1] = (unsigned char)(vTemp.y * 255);
  1806. pByte[2] = (unsigned char)(vTemp.z * 255);
  1807. pByte += 3;
  1808. }
  1809. }
  1810. glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1811. // Positive Y
  1812. pByte = pData;
  1813. for(int j = 0; j < uiTextureSize; ++j)
  1814. {
  1815. for(int i = 0; i < uiTextureSize; ++i)
  1816. {
  1817. vTemp.x = i + fOffset - fHalfSize;
  1818. vTemp.y = fHalfSize;
  1819. vTemp.z = j + fOffset - fHalfSize;
  1820. // normalize, pack 0 to 1 here, and normalize again
  1821. vTemp = vTemp.normalize() *0.5 + 0.5;
  1822. pByte[0] = (unsigned char)(vTemp.x * 255);
  1823. pByte[1] = (unsigned char)(vTemp.y * 255);
  1824. pByte[2] = (unsigned char)(vTemp.z * 255);
  1825. pByte += 3;
  1826. }
  1827. }
  1828. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1829. // Negative Y
  1830. pByte = pData;
  1831. for(int j = 0; j < uiTextureSize; ++j)
  1832. {
  1833. for(int i = 0; i < uiTextureSize; ++i)
  1834. {
  1835. vTemp.x = i + fOffset - fHalfSize;
  1836. vTemp.y = -fHalfSize;
  1837. vTemp.z = -(j + fOffset - fHalfSize);
  1838. // normalize, pack 0 to 1 here, and normalize again
  1839. vTemp = vTemp.normalize() *0.5 + 0.5;
  1840. pByte[0] = (unsigned char)(vTemp.x * 255);
  1841. pByte[1] = (unsigned char)(vTemp.y * 255);
  1842. pByte[2] = (unsigned char)(vTemp.z * 255);
  1843. pByte += 3;
  1844. }
  1845. }
  1846. glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1847. // Positive Z
  1848. pByte = pData;
  1849. for(int j = 0; j < uiTextureSize; ++j)
  1850. {
  1851. for(int i = 0; i < uiTextureSize; ++i)
  1852. {
  1853. vTemp.x = i + fOffset - fHalfSize;
  1854. vTemp.y = -(j + fOffset - fHalfSize);
  1855. vTemp.z = fHalfSize;
  1856. // normalize, pack 0 to 1 here, and normalize again
  1857. vTemp = vTemp.normalize() *0.5 + 0.5;
  1858. pByte[0] = (unsigned char)(vTemp.x * 255);
  1859. pByte[1] = (unsigned char)(vTemp.y * 255);
  1860. pByte[2] = (unsigned char)(vTemp.z * 255);
  1861. pByte += 3;
  1862. }
  1863. }
  1864. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1865. // Negative Z
  1866. pByte = pData;
  1867. for(int j = 0; j < uiTextureSize; ++j)
  1868. {
  1869. for(int i = 0; i < uiTextureSize; ++i)
  1870. {
  1871. vTemp.x = -(i + fOffset - fHalfSize);
  1872. vTemp.y = -(j + fOffset - fHalfSize);
  1873. vTemp.z = -fHalfSize;
  1874. // normalize, pack 0 to 1 here, and normalize again
  1875. vTemp = vTemp.normalize() *0.5 + 0.5;
  1876. pByte[0] = (unsigned char)(vTemp.x * 255);
  1877. pByte[1] = (unsigned char)(vTemp.y * 255);
  1878. pByte[2] = (unsigned char)(vTemp.z * 255);
  1879. pByte += 3;
  1880. }
  1881. }
  1882. glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB /*GL_RGBA8*/, uiTextureSize, uiTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
  1883. delete[] pData;
  1884. return true;
  1885. }
  1886. /*!****************************************************************************
  1887. @Function UpdateTimer
  1888. @Input none
  1889. @Description Updates the values of the current time, previous time, current time
  1890. in seconds, delta time and the FPS counter used in the program
  1891. ******************************************************************************/
  1892. void OGLES2Water::UpdateTimer()
  1893. {
  1894. m_uiFrameCount++;
  1895. m_ulPreviousTime = m_ulCurrentTime;
  1896. m_ulCurrentTime = PVRShellGetTime();
  1897. m_fElapsedTimeInSecs = m_ulCurrentTime * 0.001f;
  1898. m_fDeltaTime = ((float)(m_ulCurrentTime - m_ulPreviousTime))*0.001f;
  1899. m_fCount += m_fDeltaTime;
  1900. if(m_fCount >= 1.0f) // Update FPS once a second
  1901. {
  1902. m_uiFPS = m_uiFrameCount;
  1903. m_uiFrameCount = 0;
  1904. m_fCount = 0;
  1905. }
  1906. }
  1907. /*!****************************************************************************
  1908. @Function NewDemo
  1909. @Return PVRShell* The demo supplied by the user
  1910. @Description This function must be implemented by the user of the shell.
  1911. The user should return its PVRShell object defining the
  1912. behaviour of the application.
  1913. ******************************************************************************/
  1914. PVRShell* NewDemo()
  1915. {
  1916. return new OGLES2Water();
  1917. }
  1918. /******************************************************************************
  1919. End of file (OGLES2Water.cpp)
  1920. ******************************************************************************/