WaterSample.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include "WaterSample.h"
  2. #include "SamplesGame.h"
  3. #if defined(ADD_SAMPLE)
  4. ADD_SAMPLE("Graphics", "Water", WaterSample, 13);
  5. #endif
  6. // Camera movement consts
  7. static const float MOUSE_SPEED = 0.125f;
  8. static const float MASS = 1.8f;
  9. static const float FRICTION = 0.9f;
  10. static const float SPEED = 5.5f;
  11. static const unsigned int BUFFER_SIZE = 512;
  12. static const float WATER_OFFSET = 0.55f;
  13. WaterSample::WaterSample()
  14. : _font(NULL), _scene(NULL), _cameraNode(NULL),
  15. _reflectCameraNode(NULL), _inputMask(0u), _prevX(0),
  16. _prevY(0), _waterHeight(0.f),
  17. _refractBuffer(NULL), _refractBatch(NULL), _reflectBuffer(NULL), _reflectBatch(NULL),
  18. _showBuffers(false), _gamepad(NULL)
  19. {
  20. }
  21. void WaterSample::initialize()
  22. {
  23. // Create the font for drawing the framerate.
  24. _font = Font::create("res/ui/arial.gpb");
  25. // Load the scene file
  26. _scene = Scene::load("res/common/water/watersample.scene");
  27. _waterHeight = _scene->findNode("Water")->getTranslationY();
  28. // Set up a first person style camera
  29. const Vector3 camStartPosition(0.f, 10.f, -30.f);
  30. _cameraNode = Node::create("cameraNode");
  31. _cameraNode->setTranslation(camStartPosition);
  32. Node* camPitchNode = Node::create();
  33. Matrix m;
  34. Matrix::createLookAt(_cameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
  35. camPitchNode->rotate(m);
  36. _cameraNode->addChild(camPitchNode);
  37. _scene->addNode(_cameraNode);
  38. Camera* camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
  39. camPitchNode->setCamera(camera);
  40. _scene->setActiveCamera(camera);
  41. SAFE_RELEASE(camera);
  42. SAFE_RELEASE(camPitchNode);
  43. // Add a second camera do draw the reflections
  44. _reflectCameraNode = Node::create("reflectCamNode");
  45. _reflectCameraNode->setTranslation(camStartPosition.x, -camStartPosition.y, camStartPosition.z);
  46. camPitchNode = Node::create();
  47. Matrix::createLookAt(_reflectCameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
  48. camPitchNode->rotate(m);
  49. _reflectCameraNode->addChild(camPitchNode);
  50. camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
  51. camPitchNode->setCamera(camera);
  52. SAFE_RELEASE(camera);
  53. SAFE_RELEASE(camPitchNode);
  54. // Render buffer and preview for refraction
  55. _refractBuffer = FrameBuffer::create("refractBuffer", BUFFER_SIZE, BUFFER_SIZE);
  56. DepthStencilTarget* refractDepthTarget = DepthStencilTarget::create("refractDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
  57. _refractBuffer->setDepthStencilTarget(refractDepthTarget);
  58. SAFE_RELEASE(refractDepthTarget);
  59. _refractBatch = SpriteBatch::create(_refractBuffer->getRenderTarget()->getTexture());
  60. // Render buffer and preview for reflection
  61. _reflectBuffer = FrameBuffer::create("reflectBuffer", BUFFER_SIZE, BUFFER_SIZE);
  62. DepthStencilTarget* reflectDepthTarget = DepthStencilTarget::create("reflectDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
  63. _reflectBuffer->setDepthStencilTarget(reflectDepthTarget);
  64. SAFE_RELEASE(reflectDepthTarget);
  65. _reflectBatch = SpriteBatch::create(_reflectBuffer->getRenderTarget()->getTexture());
  66. // Add a node to provide light direction
  67. Node* lightNode = Node::create("lightNode");
  68. lightNode->rotateX(-MATH_DEG_TO_RAD(90));
  69. _scene->addNode(lightNode);
  70. // Bind material properties
  71. Material* groundMaterial = _scene->findNode("Ground")->getModel()->getMaterial();
  72. groundMaterial->getParameter("u_clipPlane")->bindValue(this, &WaterSample::getClipPlane);
  73. groundMaterial->getParameter("u_directionalLightDirection[0]")->bindValue(lightNode, &Node::getForwardVectorView);
  74. auto waterMaterial = _scene->findNode("Water")->getModel()->getMaterial();
  75. auto refractSampler = Texture::Sampler::create(_refractBuffer->getRenderTarget()->getTexture());
  76. waterMaterial->getParameter("u_refractionTexture")->setSampler(refractSampler);
  77. SAFE_RELEASE(refractSampler);
  78. auto reflectSampler = Texture::Sampler::create(_reflectBuffer->getRenderTarget()->getTexture());
  79. waterMaterial->getParameter("u_reflectionTexture")->setSampler(reflectSampler);
  80. SAFE_RELEASE(reflectSampler);
  81. waterMaterial->getParameter("u_worldViewProjectionReflectionMatrix")->bindValue(this, &WaterSample::getReflectionMatrix);
  82. waterMaterial->getParameter("u_time")->bindValue(this, &WaterSample::getTime);
  83. SAFE_RELEASE(lightNode);
  84. setMouseCaptured(true);
  85. setMultiTouch(true);
  86. _gamepad = getGamepad(0);
  87. if (_gamepad && _gamepad->isVirtual())
  88. _gamepad->getForm()->setEnabled(true);
  89. }
  90. void WaterSample::finalize()
  91. {
  92. setMouseCaptured(false);
  93. SAFE_DELETE(_reflectBatch);
  94. SAFE_RELEASE(_reflectBuffer);
  95. SAFE_DELETE(_refractBatch);
  96. SAFE_RELEASE(_refractBuffer);
  97. SAFE_RELEASE(_reflectCameraNode);
  98. SAFE_RELEASE(_cameraNode);
  99. SAFE_RELEASE(_scene);
  100. SAFE_RELEASE(_font);
  101. }
  102. void WaterSample::update(float elapsedTime)
  103. {
  104. Vector2 axis;
  105. const float minVal = 0.1f;
  106. if (_gamepad && _gamepad->getJoystickCount())
  107. _gamepad->getJoystickValues(0, &axis);
  108. // Move the camera by applying a force
  109. Vector3 force;
  110. if ((_inputMask & MOVE_FORWARD) || axis.y > minVal)
  111. force += _cameraNode->getFirstChild()->getForwardVectorWorld();
  112. if (_inputMask & MOVE_BACKWARD || axis.y < -minVal)
  113. force -= _cameraNode->getFirstChild()->getForwardVectorWorld();
  114. if (_inputMask & MOVE_LEFT || axis.x < -minVal)
  115. force += _cameraNode->getRightVectorWorld();
  116. if (_inputMask & MOVE_RIGHT || axis.y > minVal)
  117. force -= _cameraNode->getRightVectorWorld();
  118. if (force.lengthSquared() > 1.f) force.normalize();
  119. _cameraAcceleration += force / MASS;
  120. _cameraAcceleration *= FRICTION;
  121. if (_cameraAcceleration.lengthSquared() < 0.01f)
  122. _cameraAcceleration = Vector3::zero();
  123. _cameraNode->translate(_cameraAcceleration * SPEED * (elapsedTime / 1000.f));
  124. // Make sure the reflection camera follows
  125. Vector3 position = _cameraNode->getTranslation();
  126. position.y = -position.y + _waterHeight * 2.f;
  127. _reflectCameraNode->setTranslation(position);
  128. }
  129. void WaterSample::render(float elapsedTime)
  130. {
  131. const Vector4 clearColour(0.84f, 0.89f, 1.f, 1.f);
  132. // Update the refract buffer
  133. FrameBuffer* defaultBuffer = _refractBuffer->bind();
  134. Rectangle defaultViewport = getViewport();
  135. setViewport(Rectangle(BUFFER_SIZE, BUFFER_SIZE));
  136. _clipPlane.y = -1.f;
  137. _clipPlane.w = _waterHeight + WATER_OFFSET;
  138. clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
  139. _scene->visit(this, &WaterSample::drawScene, false);
  140. // Switch plane direction and camera, and update reflection buffer
  141. _reflectBuffer->bind();
  142. _clipPlane.y = 1.f;
  143. _clipPlane.w = -_waterHeight + WATER_OFFSET;
  144. Camera* defaultCamera = _scene->getActiveCamera();
  145. _scene->setActiveCamera(_reflectCameraNode->getFirstChild()->getCamera());
  146. // Store the mvp matrix here as it is only valid when reflect camera is active
  147. m_worldViewProjectionReflection = _scene->findNode("Water")->getWorldViewProjectionMatrix();
  148. clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
  149. _scene->visit(this, &WaterSample::drawScene, false);
  150. // Draw the final scene
  151. defaultBuffer->bind();
  152. setViewport(defaultViewport);
  153. _clipPlane = Vector4::zero();
  154. _scene->setActiveCamera(defaultCamera);
  155. clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
  156. _scene->visit(this, &WaterSample::drawScene, true);
  157. // Draw preview if enabled
  158. if (_showBuffers)
  159. {
  160. _refractBatch->start();
  161. _refractBatch->draw(Vector3(0.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
  162. _refractBatch->finish();
  163. _reflectBatch->start();
  164. _reflectBatch->draw(Vector3(430.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
  165. _reflectBatch->finish();
  166. }
  167. // Draw the gamepad
  168. _gamepad->draw();
  169. drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 1, getFrameRate());
  170. }
  171. void WaterSample::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  172. {
  173. switch (evt)
  174. {
  175. case Touch::TOUCH_PRESS:
  176. if (x < 75 && y < 50)
  177. {
  178. // Toggle buffer preview if the user touches the top left corner
  179. _showBuffers = !_showBuffers;
  180. }
  181. _prevX = x;
  182. _prevY = y;
  183. break;
  184. case Touch::TOUCH_RELEASE:
  185. _prevX = x;
  186. _prevY = y;
  187. break;
  188. case Touch::TOUCH_MOVE:
  189. {
  190. int deltaX = x - _prevX;
  191. int deltaY = y - _prevY;
  192. _prevX = x;
  193. _prevY = y;
  194. float xMovement = MATH_DEG_TO_RAD(deltaX * 0.25f);
  195. float yMovement = MATH_DEG_TO_RAD(-deltaY * 0.25f);
  196. _cameraNode->rotateY(-xMovement);
  197. _cameraNode->getFirstChild()->rotateX(yMovement);
  198. _reflectCameraNode->rotateY(-xMovement);
  199. _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
  200. }
  201. break;
  202. };
  203. }
  204. void WaterSample::keyEvent(Keyboard::KeyEvent evt, int key)
  205. {
  206. if (evt == Keyboard::KEY_PRESS)
  207. {
  208. switch (key)
  209. {
  210. case Keyboard::KEY_SPACE:
  211. _showBuffers = !_showBuffers;
  212. break;
  213. case Keyboard::KEY_W:
  214. case Keyboard::KEY_UP_ARROW:
  215. _inputMask |= MOVE_FORWARD;
  216. break;
  217. case Keyboard::KEY_S:
  218. case Keyboard::KEY_DOWN_ARROW:
  219. _inputMask |= MOVE_BACKWARD;
  220. break;
  221. case Keyboard::KEY_A:
  222. case Keyboard::KEY_LEFT_ARROW:
  223. _inputMask |= MOVE_LEFT;
  224. break;
  225. case Keyboard::KEY_D:
  226. case Keyboard::KEY_RIGHT_ARROW:
  227. _inputMask |= MOVE_RIGHT;
  228. break;
  229. }
  230. }
  231. else if (evt == Keyboard::KEY_RELEASE)
  232. {
  233. switch (key)
  234. {
  235. case Keyboard::KEY_W:
  236. case Keyboard::KEY_UP_ARROW:
  237. _inputMask &= ~MOVE_FORWARD;
  238. break;
  239. case Keyboard::KEY_S:
  240. case Keyboard::KEY_DOWN_ARROW:
  241. _inputMask &= ~MOVE_BACKWARD;
  242. break;
  243. case Keyboard::KEY_A:
  244. case Keyboard::KEY_LEFT_ARROW:
  245. _inputMask &= ~MOVE_LEFT;
  246. break;
  247. case Keyboard::KEY_D:
  248. case Keyboard::KEY_RIGHT_ARROW:
  249. _inputMask &= ~MOVE_RIGHT;
  250. break;
  251. }
  252. }
  253. }
  254. bool WaterSample::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  255. {
  256. switch (evt)
  257. {
  258. case Mouse::MOUSE_MOVE:
  259. {
  260. float xMovement = MATH_DEG_TO_RAD(-x * MOUSE_SPEED);
  261. float yMovement = MATH_DEG_TO_RAD(-y * MOUSE_SPEED);
  262. _cameraNode->rotateY(xMovement);
  263. _cameraNode->getFirstChild()->rotateX(yMovement);
  264. _reflectCameraNode->rotateY(xMovement);
  265. _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
  266. }
  267. return true;
  268. case Mouse::MOUSE_PRESS_LEFT_BUTTON:
  269. _inputMask |= MOVE_FORWARD;
  270. return true;
  271. case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
  272. _inputMask &= ~MOVE_FORWARD;
  273. return true;
  274. case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
  275. _inputMask |= MOVE_BACKWARD;
  276. return true;
  277. case Mouse::MOUSE_RELEASE_RIGHT_BUTTON:
  278. _inputMask &= ~MOVE_BACKWARD;
  279. return true;
  280. default: return false;
  281. }
  282. return false;
  283. }
  284. void WaterSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
  285. {
  286. switch (evt)
  287. {
  288. case Gamepad::CONNECTED_EVENT:
  289. case Gamepad::DISCONNECTED_EVENT:
  290. _gamepad = getGamepad(0);
  291. if (_gamepad && _gamepad->isVirtual())
  292. _gamepad->getForm()->setEnabled(true);
  293. break;
  294. }
  295. }
  296. bool WaterSample::drawScene(Node* node, bool drawWater)
  297. {
  298. std::string id = node->getId();
  299. if (!drawWater && id == "Water") return true;
  300. Model* model = node->getModel();
  301. if (model)
  302. model->draw();
  303. return true;
  304. }