PhoenixMee

Untitled

Apr 11th, 2019
112
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include "GL/glew.h"
  3. #include "GL/3dgl.h"
  4. #include "GL/glut.h"
  5. #include "GL/freeglut_ext.h"
  6.  
  7. #pragma comment (lib, "glew32.lib")
  8.  
  9. using namespace std;
  10. using namespace _3dgl;
  11.  
  12. //bool reverseskybox = true;
  13. //
  14. const char * skyboxtextures[6] = { "models\\skyboxfront2.jpg", "models\\skyboxleft2.jpg", "models\\skyboxback2.jpg",
  15. "models\\skyboxright2.jpg", "models\\skyboxup.jpg", "models\\skyboxup2.jpg" };
  16.  
  17. // window size (used for FBO)
  18. int ScreenWidth = 800;
  19. int ScreenHeight = 600;
  20.  
  21. // 3D Models
  22. C3dglTerrain terrain, reflectedterrain, water;
  23.  
  24. // Skybox
  25. C3dglSkyBox skybox, reflectedskybox;
  26.  
  27. // texture ids
  28. GLuint idTexGrass; // grass texture
  29. GLuint idTexSand; // sand texture
  30. GLuint idTexWater; // water texture
  31. GLuint idTexNone;
  32. GLuint stencilTexture, fb, depth_stencil_rb;
  33.  
  34. // particle ids
  35. GLuint idBufferVelocity;
  36. GLuint idBufferStartTime;
  37.  
  38. // GLSL Objects (Shader Program)
  39. C3dglProgram ProgramBasic;
  40. C3dglProgram ProgramWater;
  41. C3dglProgram ProgramTerrain;
  42. C3dglProgram ProgramParticle;
  43.  
  44. // Water specific variables
  45. float waterLevel = 4.6f;
  46.  
  47. // setup clipping plane array
  48. float Nx = 0, Ny = 1, Nz = 0, d = 0;
  49. float clipPlane[4] = { Nx, Ny, Nz, d };
  50.  
  51. // camera position (for first person type camera navigation)
  52. float matrixView[16]; // The View Matrix
  53. float angleTilt = 0; // Tilt Angle
  54. float deltaX = 0, deltaY = 0, deltaZ = 0; // Camera movement values
  55.  
  56. // world camera position (used for reflection texture)
  57. float cameraVector[3];
  58. GLfloat cameraMatrix[16];
  59.  
  60. // Particle System Params
  61. const float PERIOD = 0.000075f; // each recycled particle will obtain it's start time PERIOD seconds after the previous has died
  62. const float LIFETIME = 6; // life time of each particle
  63. const int NPARTICLES = (int)(LIFETIME / PERIOD); // number of particles that need to be present before any new particles are born (8000, in this case)
  64.  
  65. bool init()
  66. {
  67. // rendering states
  68. glEnable(GL_DEPTH_TEST); // depth test is necessary for most 3D scenes
  69. glEnable(GL_NORMALIZE); // normalization is needed by AssImp library models
  70. glShadeModel(GL_SMOOTH); // smooth shading mode is the default one; try GL_FLAT here!
  71. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // this is the default one; try GL_LINE!
  72.  
  73. glEnable(GL_BLEND);
  74. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  75.  
  76.  
  77.  
  78. // Initialise Shaders
  79. C3dglShader VertexShader;
  80. C3dglShader FragmentShader;
  81.  
  82. if (!VertexShader.Create(GL_VERTEX_SHADER)) return false;
  83. if (!VertexShader.LoadFromFile("shaders/basic.vert")) return false;
  84. if (!VertexShader.Compile()) return false;
  85.  
  86. if (!FragmentShader.Create(GL_FRAGMENT_SHADER)) return false;
  87. if (!FragmentShader.LoadFromFile("shaders/basic.frag")) return false;
  88. if (!FragmentShader.Compile()) return false;
  89.  
  90. if (!ProgramBasic.Create()) return false;
  91. if (!ProgramBasic.Attach(VertexShader)) return false;
  92. if (!ProgramBasic.Attach(FragmentShader)) return false;
  93. if (!ProgramBasic.Link()) return false;
  94. if (!ProgramBasic.Use(true)) return false;
  95.  
  96. if (!VertexShader.Create(GL_VERTEX_SHADER)) return false;
  97. if (!VertexShader.LoadFromFile("shaders/water.vert")) return false;
  98. if (!VertexShader.Compile()) return false;
  99.  
  100. if (!FragmentShader.Create(GL_FRAGMENT_SHADER)) return false;
  101. if (!FragmentShader.LoadFromFile("shaders/water.frag")) return false;
  102. if (!FragmentShader.Compile()) return false;
  103.  
  104. if (!ProgramWater.Create()) return false;
  105. if (!ProgramWater.Attach(VertexShader)) return false;
  106. if (!ProgramWater.Attach(FragmentShader)) return false;
  107. if (!ProgramWater.Link()) return false;
  108. if (!ProgramWater.Use(true)) return false;
  109.  
  110. if (!VertexShader.Create(GL_VERTEX_SHADER)) return false;
  111. if (!VertexShader.LoadFromFile("shaders/terrain.vert")) return false;
  112. if (!VertexShader.Compile()) return false;
  113.  
  114. if (!FragmentShader.Create(GL_FRAGMENT_SHADER)) return false;
  115. if (!FragmentShader.LoadFromFile("shaders/terrain.frag")) return false;
  116. if (!FragmentShader.Compile()) return false;
  117.  
  118. if (!ProgramTerrain.Create()) return false;
  119. if (!ProgramTerrain.Attach(VertexShader)) return false;
  120. if (!ProgramTerrain.Attach(FragmentShader)) return false;
  121. if (!ProgramTerrain.Link()) return false;
  122. if (!ProgramTerrain.Use(true)) return false;
  123.  
  124. //if (!VertexShader.Create(GL_VERTEX_SHADER)) return false;
  125. //if (!VertexShader.LoadFromFile("shaders/particle.vert")) return false;
  126. //if (!VertexShader.Compile()) return false;
  127.  
  128. //if (!FragmentShader.Create(GL_FRAGMENT_SHADER)) return false;
  129. //if (!FragmentShader.LoadFromFile("shaders/particle.frag")) return false;
  130. //if (!FragmentShader.Compile()) return false;
  131.  
  132. //if (!ProgramParticle.Create()) return false;
  133. //if (!ProgramParticle.Attach(VertexShader)) return false;
  134. //if (!ProgramParticle.Attach(FragmentShader)) return false;
  135. //if (!ProgramParticle.Link()) return false;
  136. //if (!ProgramParticle.Use(true)) return false;
  137.  
  138. // glut additional setup
  139. glutSetVertexAttribCoord3(ProgramBasic.GetAttribLocation("aVertex"));
  140. glutSetVertexAttribNormal(ProgramBasic.GetAttribLocation("aNormal"));
  141.  
  142. // enable alpha blending
  143. glEnable(GL_BLEND);
  144. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  145.  
  146. // load your 3D models here!
  147. if (!terrain.loadHeightmap("models\\heightmap.png", 10)) return false;
  148. if (!reflectedterrain.loadHeightmap("models\\heightmap.png", -10)) return false;
  149. if (!water.loadHeightmap("models\\watermap.png", 10)) return false;
  150. if (!skybox.load(skyboxtextures[0], skyboxtextures[1], skyboxtextures[2],
  151. skyboxtextures[3], skyboxtextures[4], skyboxtextures[5])) return false;
  152. if (!reflectedskybox.load("models\\skyboxback.jpg", "models\\skyboxright.jpg", "models\\skyboxfront.jpg",
  153. "models\\skyboxleft.jpg", "models\\skyboxdown.jpg", "models\\skyboxup.jpg")) return false;
  154.  
  155. // create & load textures
  156. C3dglBitmap bm, bm2;
  157. glActiveTexture(GL_TEXTURE0);
  158.  
  159. // Grass texture
  160. bm.Load("models/grass.png", GL_RGBA);
  161. glGenTextures(1, &idTexGrass);
  162. glBindTexture(GL_TEXTURE_2D, idTexGrass);
  163. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  164. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bm.GetWidth(), bm.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bm.GetBits());
  165.  
  166. // Sand texture
  167. bm.Load("models/sand.png", GL_RGBA);
  168. glGenTextures(1, &idTexSand);
  169. glBindTexture(GL_TEXTURE_2D, idTexSand);
  170. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  171. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bm.GetWidth(), bm.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bm.GetBits());
  172.  
  173. // Water texture
  174. bm.Load("models/water.png", GL_RGBA);
  175. glGenTextures(1, &idTexWater);
  176. glBindTexture(GL_TEXTURE_2D, idTexWater);
  177. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  178. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bm.GetWidth(), bm.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, bm.GetBits());
  179.  
  180. // the textures to mix for terrain
  181. glActiveTexture(GL_TEXTURE1);
  182. glBindTexture(GL_TEXTURE_2D, idTexSand);
  183.  
  184. glActiveTexture(GL_TEXTURE2);
  185. glBindTexture(GL_TEXTURE_2D, idTexGrass);
  186.  
  187. // Prepare the particle buffers
  188. std::vector<float> bufferVelocity;
  189. std::vector<float> bufferStartTime;
  190. float time = 0;
  191. float M_PI = 3.14;
  192.  
  193. for (int i = 0; i < NPARTICLES; i++)
  194. {
  195. float theta = (float)M_PI / 6.f * (float)rand() / (float)RAND_MAX;
  196. float phi = (float)M_PI * 2.f * (float)rand() / (float)RAND_MAX;
  197. float x = sin(theta) * cos(phi);
  198. float y = cos(theta);
  199. float z = sin(theta) * sin(phi);
  200. float v = 2 + 0.5f * (float)rand() / (float)RAND_MAX;
  201.  
  202. bufferVelocity.push_back(x * v);
  203. bufferVelocity.push_back(y * v);
  204. bufferVelocity.push_back(z * v);
  205. bufferStartTime.push_back(time);
  206.  
  207. time += PERIOD;
  208. }
  209.  
  210. glGenBuffers(1, &idBufferVelocity);
  211. glBindBuffer(GL_ARRAY_BUFFER, idBufferVelocity);
  212. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * bufferVelocity.size(), &bufferVelocity[0], GL_STATIC_DRAW);
  213. glGenBuffers(1, &idBufferStartTime); glBindBuffer(GL_ARRAY_BUFFER, idBufferStartTime);
  214. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * bufferStartTime.size(), &bufferStartTime[0], GL_STATIC_DRAW);
  215.  
  216. // send texture channel info to shaders
  217. ProgramBasic.SendUniform("texture0", 0);
  218. ProgramTerrain.SendUniform("texture0", 0);
  219. ProgramWater.SendUniform("texture0", 0);
  220. ProgramParticle.SendUniform("texture0", 0);
  221. ProgramTerrain.SendUniform("textureUnderwater", 1);
  222. ProgramTerrain.SendUniform("textureShore", 2);
  223. ProgramWater.SendUniform("texture3", 3);
  224.  
  225. // setup lights (for basic and terrain programs only, water does not use these lights)
  226. ProgramBasic.SendUniform("lightAmbient.on", 1);
  227. ProgramBasic.SendUniform("lightAmbient.color", 0.1, 0.1, 0.1);
  228. ProgramBasic.SendUniform("lightDir.on", 1);
  229. ProgramBasic.SendUniform("lightDir.direction", 1.0, 0.5, 1.0);
  230. ProgramBasic.SendUniform("lightDir.diffuse", 1.0, 1.0, 1.0);
  231.  
  232. ProgramTerrain.SendUniform("lightAmbient.on", 1);
  233. ProgramTerrain.SendUniform("lightAmbient.color", 0.1, 0.1, 0.1);
  234. ProgramTerrain.SendUniform("lightDir.on", 1);
  235. ProgramTerrain.SendUniform("lightDir.direction", 1.0, 0.5, 1.0);
  236. ProgramTerrain.SendUniform("lightDir.diffuse", 1.0, 1.0, 1.0);
  237.  
  238. // base material setup (basic and terrain shaders only)
  239. ProgramBasic.SendUniform("materialAmbient", 1.0, 1.0, 1.0); // full power (note: ambient light is extremely dim)
  240. ProgramBasic.SendUniform("materialDiffuse", 1.0, 1.0, 1.0);
  241.  
  242. ProgramTerrain.SendUniform("materialAmbient", 1.0, 1.0, 1.0); // full power (note: ambient light is extremely dim)
  243. ProgramTerrain.SendUniform("materialDiffuse", 1.0, 1.0, 1.0);
  244.  
  245. // setup water colour and water level
  246. ProgramWater.SendUniform("waterColor", 0.2f, 0.22f, 0.2f);
  247. ProgramWater.SendUniform("skyColor", 0.2f, 0.6f, 1.0f);
  248.  
  249. // send waterLevel to terrain shader
  250. ProgramTerrain.SendUniform("waterLevel", waterLevel);
  251.  
  252. // underwater fog values sending to terrain shaders
  253. ProgramTerrain.SendUniform("fogColor", 0.2f, 0.22f, 0.2f);
  254. ProgramTerrain.SendUniform("fogThickness", 0.3); // higher value for more thickness
  255.  
  256. // send terrain clip plane info
  257. //ProgramTerrain.SendUniform("clipPlane", clipPlane);
  258.  
  259. // set flip terrain textures to false initially (use when rendering terrain upside down to match blended above-water texture)
  260. ProgramTerrain.SendUniform("flipTextures", 0);
  261.  
  262. // Setup the particle system
  263. //ProgramParticle.SendUniform("initialPos", -10.7865f, 8.21369f, 12.5494f);
  264. ProgramParticle.SendUniform("gravity", 0.0f, -0.5f, 0.0f);
  265. ProgramParticle.SendUniform("particleLifetime", LIFETIME);
  266.  
  267. // Initialise the View Matrix (initial position for the first-person camera)
  268. glMatrixMode(GL_MODELVIEW);
  269. angleTilt = 15;
  270. glLoadIdentity();
  271. glRotatef(angleTilt, 1, 0, 0);
  272. gluLookAt(4.0, 0.4, 30.0,
  273. 4.0, 0.4, 0.0,
  274. 0.0, 1.0, 0.0);
  275. glGetFloatv(GL_MODELVIEW_MATRIX, matrixView);
  276.  
  277. cout << endl;
  278. cout << "Use:" << endl;
  279. cout << " WASD or arrow key to navigate" << endl;
  280. cout << " QE or PgUp/Dn to move the camera up and down" << endl;
  281. cout << " Drag the mouse to look around" << endl;
  282. cout << endl;
  283.  
  284. return true;
  285. }
  286.  
  287. void getCamPos()
  288. {
  289. // getting position of camera in 'world space'
  290. GLfloat cameraMatrix[16];
  291. glGetFloatv(GL_MODELVIEW_MATRIX, cameraMatrix);
  292. cameraVector[0] = -(cameraMatrix[0] * cameraMatrix[12] + cameraMatrix[1] * cameraMatrix[13] + cameraMatrix[2] * cameraMatrix[14]); // x
  293. cameraVector[1] = -(cameraMatrix[4] * cameraMatrix[12] + cameraMatrix[5] * cameraMatrix[13] + cameraMatrix[6] * cameraMatrix[14]); // y
  294. cameraVector[2] = -(cameraMatrix[8] * cameraMatrix[12] + cameraMatrix[9] * cameraMatrix[13] + cameraMatrix[10] * cameraMatrix[14]); // z
  295. cout << "x, y, z \n";
  296. cout << cameraVector[0]; cout << "f, ";
  297. cout << cameraVector[1]; cout << "f, ";
  298. cout << cameraVector[2]; cout << "f, ";
  299. cout << "\n";
  300. }
  301.  
  302. void done()
  303. {
  304. }
  305.  
  306. // called before window opened or resized - to setup the Projection Matrix
  307. void reshape(int w, int h)
  308. {
  309. // find screen aspect ratio
  310. float ratio = w * 1.0f / h; // we hope that h is not zero
  311.  
  312. // setup the projection matrix
  313. glMatrixMode(GL_PROJECTION);
  314. glLoadIdentity();
  315. glViewport(0, 0, w, h);
  316. gluPerspective(60.0, ratio, 0.02, 1000.0);
  317.  
  318. float matrix[16];
  319. glGetFloatv(GL_PROJECTION_MATRIX, matrix);
  320. ProgramBasic.SendUniform("matrixProjection", matrix);
  321. ProgramTerrain.SendUniform("matrixProjection", matrix);
  322. ProgramWater.SendUniform("matrixProjection", matrix);
  323. ProgramParticle.SendUniform("matrixProjection", matrix);
  324. }
  325.  
  326. void renderTerrain()
  327. {
  328. float matrix[16];
  329. float matrixinvert[16];
  330.  
  331. // upright terrain
  332. glEnable(GL_CLIP_DISTANCE0);
  333. gluInvertMatrix(matrixView, matrixinvert);
  334. ProgramTerrain.SendUniform("matrixViewInvert", matrixinvert);
  335. glActiveTexture(GL_TEXTURE0);
  336. glBindTexture(GL_TEXTURE_2D, idTexGrass);
  337. ProgramTerrain.Use();
  338. glPushMatrix();
  339. //glTranslatef(0.0f, 9.5f, 0.0f);
  340. glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  341. ProgramTerrain.SendUniform("matrixModelView", matrix);
  342. terrain.render();
  343. glPopMatrix();
  344. glDisable(GL_CLIP_DISTANCE0);
  345. }
  346.  
  347. void renderWater()
  348. {
  349. float matrix[16];
  350.  
  351. // water
  352. glActiveTexture(GL_TEXTURE3);
  353. glBindTexture(GL_TEXTURE_2D, stencilTexture);
  354. ProgramWater.Use();
  355. glPushMatrix();
  356. glTranslatef(0.0f, waterLevel, 0.0f);
  357. glScalef(0.5f, 1.0f, 0.5f);
  358. glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  359. ProgramWater.SendUniform("matrixModelView", matrix);
  360. water.render();
  361. glPopMatrix();
  362. }
  363.  
  364. void reflectedTerrain()
  365. {
  366. float matrix[16];
  367. float matrixinvert[16];
  368.  
  369. // ..and reverse lighting
  370. ProgramTerrain.SendUniform("lightDir.direction", -1.0, 0.5, -1.0);
  371. // upside-down terrain
  372. glEnable(GL_CLIP_DISTANCE1);
  373. gluInvertMatrix(matrixView, matrixinvert);
  374. ProgramTerrain.SendUniform("matrixViewInvert", matrixinvert);
  375. glActiveTexture(GL_TEXTURE0);
  376. glBindTexture(GL_TEXTURE_2D, idTexGrass);
  377. ProgramTerrain.SendUniform("flipTextures", 1);
  378. ProgramTerrain.Use();
  379. glPushMatrix();
  380. glTranslatef(0.0f, 9.2f, 0.0f);
  381. glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  382. ProgramTerrain.SendUniform("matrixModelView", matrix);
  383. reflectedterrain.render();
  384. glPopMatrix();
  385. ProgramTerrain.SendUniform("flipTextures", 0);
  386. glDisable(GL_CLIP_DISTANCE1);
  387. ProgramTerrain.SendUniform("lightDir.direction", 1.0, 0.5, 1.0);
  388. }
  389.  
  390. void particleSystem()
  391. {
  392. float matrix[16];
  393.  
  394. ProgramParticle.Use();
  395.  
  396. glPointSize(55);
  397. glEnable(GL_POINT_SPRITE);
  398. glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  399.  
  400. ProgramParticle.SendUniform("initialPos", cameraVector[0], cameraVector[1] + 1, cameraVector[2]);
  401.  
  402. glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  403. ProgramParticle.SendUniform("matrixModelView", matrix);
  404.  
  405. // render the buffer
  406. glEnableVertexAttribArray(0);
  407. // velocity
  408. glEnableVertexAttribArray(1);
  409. // start time
  410. glBindBuffer(GL_ARRAY_BUFFER, idBufferVelocity);
  411. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  412. glBindBuffer(GL_ARRAY_BUFFER, idBufferStartTime);
  413. glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
  414. glDrawArrays(GL_POINTS, 0, NPARTICLES);
  415. glDisableVertexAttribArray(0);
  416. glDisableVertexAttribArray(1);
  417. }
  418.  
  419. void stencilTest()
  420. {
  421. // Don't update color or depth
  422. glDisable(GL_DEPTH_TEST);
  423. glDepthMask(GL_FALSE);
  424. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  425.  
  426. // draw 1 into the stencil buffer.
  427. glEnable(GL_STENCIL_TEST);
  428. glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
  429. glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
  430.  
  431. renderWater();
  432.  
  433. // re-enable update of color and depth
  434. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  435. glEnable(GL_DEPTH_TEST);
  436. glDepthMask(GL_TRUE);
  437.  
  438. // only render where stencil is set to 1
  439. glStencilFunc(GL_EQUAL, 1, 0xffffffff); // draw if stencil == 1
  440. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  441.  
  442. reflectedTerrain();
  443.  
  444. glDisable(GL_STENCIL_TEST);
  445. }
  446.  
  447. void render()
  448. {
  449. // getting position of camera in 'world space'
  450. glGetFloatv(GL_MODELVIEW_MATRIX, cameraMatrix);
  451. cameraVector[0] = -(cameraMatrix[0] * cameraMatrix[12] + cameraMatrix[1] * cameraMatrix[13] + cameraMatrix[2] * cameraMatrix[14]); // x
  452. cameraVector[1] = -(cameraMatrix[4] * cameraMatrix[12] + cameraMatrix[5] * cameraMatrix[13] + cameraMatrix[6] * cameraMatrix[14]); // y
  453. cameraVector[2] = -(cameraMatrix[8] * cameraMatrix[12] + cameraMatrix[9] * cameraMatrix[13] + cameraMatrix[10] * cameraMatrix[14]); // z
  454.  
  455. //prepareReflectionTexture();
  456.  
  457. float matrix[16];
  458. float matrixinvert[16];
  459.  
  460. // clear screen and buffers
  461. glClearColor(0.2f, 0.6f, 1.f, 1.0f); // blue sky colour
  462. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  463.  
  464. // setup the View Matrix (camera)
  465. glMatrixMode(GL_MODELVIEW);
  466. glLoadIdentity();
  467. glRotatef(angleTilt, 1, 0, 0); // switch tilt off
  468. glTranslatef(deltaX, deltaY, deltaZ); // animate camera motion (controlled by WASD keys)
  469. glRotatef(-angleTilt, 1, 0, 0); // switch tilt on
  470. glMultMatrixf(matrixView);
  471. glGetFloatv(GL_MODELVIEW_MATRIX, matrixView);
  472.  
  473. // set the camera height above the ground
  474. //gluInvertMatrix(matrixView, matrix);
  475. glTranslatef(0, -max(terrain.getInterpolatedHeight(matrix[12], matrix[14]), waterLevel), 0);
  476.  
  477. // setup View Matrix
  478. glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  479. ProgramBasic.SendUniform("matrixView", matrix);
  480. ProgramTerrain.SendUniform("matrixView", matrix);
  481.  
  482. // send time 't' to water shaders
  483. ProgramWater.SendUniform("t", glutGet(GLUT_ELAPSED_TIME) / 3000.f);
  484.  
  485. // send time 'time' to particle shaders
  486. ProgramParticle.SendUniform("time", glutGet(GLUT_ELAPSED_TIME) / 1000.f - 2);
  487.  
  488. // render the skybox
  489. ProgramBasic.Use();
  490. ProgramBasic.SendUniform("materialAmbient", 10.0f, 10.0f, 10.0f);
  491. ProgramBasic.SendUniform("materialDiffuse", 0.0f, 0.0f, 0.0f);
  492. skybox.render();
  493.  
  494. stencilTest();
  495.  
  496. renderWater();
  497. renderTerrain();
  498. particleSystem();
  499.  
  500. // essential for double-buffering technique
  501. glutSwapBuffers();
  502.  
  503. // proceed the animation
  504. glutPostRedisplay();
  505. }
  506.  
  507. // Handle WASDQE keys
  508. void onKeyDown(unsigned char key, int x, int y)
  509. {
  510. switch (tolower(key))
  511. {
  512. case 'w': deltaZ = max(deltaZ * 1.05f, 0.01f); break;
  513. case 's': deltaZ = min(deltaZ * 1.05f, -0.01f); break;
  514. case 'a': deltaX = max(deltaX * 1.05f, 0.01f); break;
  515. case 'd': deltaX = min(deltaX * 1.05f, -0.01f); break;
  516. case 'e': deltaY = max(deltaY * 1.05f, 0.01f); break;
  517. case 'q': deltaY = min(deltaY * 1.05f, -0.01f); break;
  518. }
  519. // speed limit
  520. deltaX = max(-0.15f, min(0.15f, deltaX));
  521. deltaY = max(-0.15f, min(0.15f, deltaY));
  522. deltaZ = max(-0.15f, min(0.15f, deltaZ));
  523. }
  524.  
  525. // Handle WASDQE keys (key up)
  526. void onKeyUp(unsigned char key, int x, int y)
  527. {
  528. switch (tolower(key))
  529. {
  530. case 'w': deltaZ = 0; getCamPos(); break;
  531. case 's': deltaZ = 0; break;
  532. case 'a':
  533. case 'd': deltaX = 0; break;
  534. case 'q':
  535. case 'e': deltaY = 0; break;
  536. case ' ': deltaY = 0; break;
  537. }
  538. }
  539.  
  540. // Handle arrow keys and Alt+F4
  541. void onSpecDown(int key, int x, int y)
  542. {
  543. switch (key)
  544. {
  545. case GLUT_KEY_F4: if ((glutGetModifiers() & GLUT_ACTIVE_ALT) != 0) exit(0); break;
  546. case GLUT_KEY_UP: onKeyDown('w', x, y); break;
  547. case GLUT_KEY_DOWN: onKeyDown('s', x, y); break;
  548. case GLUT_KEY_LEFT: onKeyDown('a', x, y); break;
  549. case GLUT_KEY_RIGHT: onKeyDown('d', x, y); break;
  550. case GLUT_KEY_PAGE_UP: onKeyDown('q', x, y); break;
  551. case GLUT_KEY_PAGE_DOWN:onKeyDown('e', x, y); break;
  552. case GLUT_KEY_F11: glutFullScreenToggle();
  553. }
  554. }
  555.  
  556. // Handle arrow keys (key up)
  557. void onSpecUp(int key, int x, int y)
  558. {
  559. switch (key)
  560. {
  561. case GLUT_KEY_UP: onKeyUp('w', x, y); break;
  562. case GLUT_KEY_DOWN: onKeyUp('s', x, y); break;
  563. case GLUT_KEY_LEFT: onKeyUp('a', x, y); break;
  564. case GLUT_KEY_RIGHT: onKeyUp('d', x, y); break;
  565. case GLUT_KEY_PAGE_UP: onKeyUp('q', x, y); break;
  566. case GLUT_KEY_PAGE_DOWN:onKeyUp('e', x, y); break;
  567. }
  568. }
  569.  
  570. // Handle mouse click
  571. void onMouse(int button, int state, int x, int y)
  572. {
  573. int cx = glutGet(GLUT_WINDOW_WIDTH) / 2;
  574. int cy = glutGet(GLUT_WINDOW_HEIGHT) / 2;
  575.  
  576. if (state == GLUT_DOWN)
  577. {
  578. glutSetCursor(GLUT_CURSOR_CROSSHAIR);
  579. glutWarpPointer(cx, cy);
  580. }
  581. else
  582. glutSetCursor(GLUT_CURSOR_INHERIT);
  583. }
  584.  
  585. // handle mouse move
  586. void onMotion(int x, int y)
  587. {
  588. int cx = glutGet(GLUT_WINDOW_WIDTH) / 2;
  589. int cy = glutGet(GLUT_WINDOW_HEIGHT) / 2;
  590. if (x == cx && y == cy)
  591. return; // caused by glutWarpPointer
  592.  
  593. float amp = 0.25;
  594. float deltaTilt = amp * (y - cy);
  595. float deltaPan = amp * (x - cx);
  596.  
  597. glutWarpPointer(cx, cy);
  598.  
  599. // handle camera tilt (mouse move up & down)
  600. glMatrixMode(GL_MODELVIEW);
  601. glLoadIdentity();
  602. glRotatef(deltaTilt, 1, 0, 0);
  603. glMultMatrixf(matrixView);
  604. glGetFloatv(GL_MODELVIEW_MATRIX, matrixView);
  605.  
  606. angleTilt += deltaTilt;
  607.  
  608. // handle camera pan (mouse move left & right)
  609. glMatrixMode(GL_MODELVIEW);
  610. glLoadIdentity();
  611. glRotatef(angleTilt, 1, 0, 0);
  612. glRotatef(deltaPan, 0, 1, 0);
  613. glRotatef(-angleTilt, 1, 0, 0);
  614. glMultMatrixf(matrixView);
  615. glGetFloatv(GL_MODELVIEW_MATRIX, matrixView);
  616. }
  617.  
  618. int main(int argc, char **argv)
  619. {
  620. // init GLUT and create Window
  621. glutInit(&argc, argv);
  622. glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  623. glutInitWindowPosition(100, 100);
  624. glutInitWindowSize(800, 600);
  625. glutCreateWindow("CI5520 3D Graphics Programming");
  626.  
  627. // init glew
  628. GLenum err = glewInit();
  629. if (GLEW_OK != err)
  630. {
  631. cerr << "GLEW Error: " << glewGetErrorString(err) << endl;
  632. return 0;
  633. }
  634. cout << "Using GLEW " << glewGetString(GLEW_VERSION) << endl;
  635.  
  636. // register callbacks
  637. glutDisplayFunc(render);
  638. glutReshapeFunc(reshape);
  639. glutKeyboardFunc(onKeyDown);
  640. glutSpecialFunc(onSpecDown);
  641. glutKeyboardUpFunc(onKeyUp);
  642. glutSpecialUpFunc(onSpecUp);
  643. glutMouseFunc(onMouse);
  644. glutMotionFunc(onMotion);
  645.  
  646. cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
  647. cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
  648. cout << "Version: " << glGetString(GL_VERSION) << endl;
  649.  
  650. // init light and everything – not a GLUT or callback function!
  651. if (!init())
  652. {
  653. cerr << "Application failed to initialise" << endl;
  654. return 0;
  655. }
  656.  
  657. // enter GLUT event processing cycle
  658. glutMainLoop();
  659.  
  660. done();
  661.  
  662. return 1;
  663. }
RAW Paste Data