| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- #include "WaterSample.h"
- #include "SamplesGame.h"
- #if defined(ADD_SAMPLE)
- ADD_SAMPLE("Graphics", "Water", WaterSample, 13);
- #endif
- // Camera movement consts
- static const float MOUSE_SPEED = 0.125f;
- static const float MASS = 1.8f;
- static const float FRICTION = 0.9f;
- static const float SPEED = 5.5f;
- static const unsigned int BUFFER_SIZE = 512;
- static const float WATER_OFFSET = 0.55f;
- WaterSample::WaterSample()
- : _font(NULL), _scene(NULL), _cameraNode(NULL),
- _reflectCameraNode(NULL), _inputMask(0u), _prevX(0),
- _prevY(0), _waterHeight(0.f),
- _refractBuffer(NULL), _refractBatch(NULL), _reflectBuffer(NULL), _reflectBatch(NULL),
- _showBuffers(false), _gamepad(NULL)
- {
- }
- void WaterSample::initialize()
- {
- // Create the font for drawing the framerate.
- _font = Font::create("res/ui/arial.gpb");
- // Load the scene file
- _scene = Scene::load("res/common/water/watersample.scene");
- _waterHeight = _scene->findNode("Water")->getTranslationY();
- // Set up a first person style camera
- const Vector3 camStartPosition(0.f, 10.f, -30.f);
- _cameraNode = Node::create("cameraNode");
- _cameraNode->setTranslation(camStartPosition);
- Node* camPitchNode = Node::create();
- Matrix m;
- Matrix::createLookAt(_cameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
- camPitchNode->rotate(m);
- _cameraNode->addChild(camPitchNode);
- _scene->addNode(_cameraNode);
- Camera* camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
- camPitchNode->setCamera(camera);
- _scene->setActiveCamera(camera);
- SAFE_RELEASE(camera);
- SAFE_RELEASE(camPitchNode);
- // Add a second camera do draw the reflections
- _reflectCameraNode = Node::create("reflectCamNode");
- _reflectCameraNode->setTranslation(camStartPosition.x, -camStartPosition.y, camStartPosition.z);
- camPitchNode = Node::create();
- Matrix::createLookAt(_reflectCameraNode->getTranslation(), Vector3::zero(), Vector3::unitY(), &m);
- camPitchNode->rotate(m);
- _reflectCameraNode->addChild(camPitchNode);
- camera = Camera::createPerspective(45.f, Game::getInstance()->getAspectRatio(), 0.1f, 150.f);
- camPitchNode->setCamera(camera);
- SAFE_RELEASE(camera);
- SAFE_RELEASE(camPitchNode);
- // Render buffer and preview for refraction
- _refractBuffer = FrameBuffer::create("refractBuffer", BUFFER_SIZE, BUFFER_SIZE);
- DepthStencilTarget* refractDepthTarget = DepthStencilTarget::create("refractDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
- _refractBuffer->setDepthStencilTarget(refractDepthTarget);
- SAFE_RELEASE(refractDepthTarget);
- _refractBatch = SpriteBatch::create(_refractBuffer->getRenderTarget()->getTexture());
- // Render buffer and preview for reflection
- _reflectBuffer = FrameBuffer::create("reflectBuffer", BUFFER_SIZE, BUFFER_SIZE);
- DepthStencilTarget* reflectDepthTarget = DepthStencilTarget::create("reflectDepth", DepthStencilTarget::DEPTH, BUFFER_SIZE, BUFFER_SIZE);
- _reflectBuffer->setDepthStencilTarget(reflectDepthTarget);
- SAFE_RELEASE(reflectDepthTarget);
- _reflectBatch = SpriteBatch::create(_reflectBuffer->getRenderTarget()->getTexture());
- // Add a node to provide light direction
- Node* lightNode = Node::create("lightNode");
- lightNode->rotateX(-MATH_DEG_TO_RAD(90));
- _scene->addNode(lightNode);
- // Bind material properties
- Material* groundMaterial = _scene->findNode("Ground")->getModel()->getMaterial();
- groundMaterial->getParameter("u_clipPlane")->bindValue(this, &WaterSample::getClipPlane);
- groundMaterial->getParameter("u_directionalLightDirection[0]")->bindValue(lightNode, &Node::getForwardVectorView);
- auto waterMaterial = _scene->findNode("Water")->getModel()->getMaterial();
- auto refractSampler = Texture::Sampler::create(_refractBuffer->getRenderTarget()->getTexture());
- waterMaterial->getParameter("u_refractionTexture")->setSampler(refractSampler);
- SAFE_RELEASE(refractSampler);
- auto reflectSampler = Texture::Sampler::create(_reflectBuffer->getRenderTarget()->getTexture());
- waterMaterial->getParameter("u_reflectionTexture")->setSampler(reflectSampler);
- SAFE_RELEASE(reflectSampler);
- waterMaterial->getParameter("u_worldViewProjectionReflectionMatrix")->bindValue(this, &WaterSample::getReflectionMatrix);
- waterMaterial->getParameter("u_time")->bindValue(this, &WaterSample::getTime);
- SAFE_RELEASE(lightNode);
- setMouseCaptured(true);
- setMultiTouch(true);
- _gamepad = getGamepad(0);
- if (_gamepad && _gamepad->isVirtual())
- _gamepad->getForm()->setEnabled(true);
- }
- void WaterSample::finalize()
- {
- setMouseCaptured(false);
- SAFE_DELETE(_reflectBatch);
- SAFE_RELEASE(_reflectBuffer);
- SAFE_DELETE(_refractBatch);
- SAFE_RELEASE(_refractBuffer);
- SAFE_RELEASE(_reflectCameraNode);
- SAFE_RELEASE(_cameraNode);
- SAFE_RELEASE(_scene);
- SAFE_RELEASE(_font);
- }
- void WaterSample::update(float elapsedTime)
- {
- Vector2 axis;
- const float minVal = 0.1f;
- if (_gamepad && _gamepad->getJoystickCount())
- _gamepad->getJoystickValues(0, &axis);
-
- // Move the camera by applying a force
- Vector3 force;
- if ((_inputMask & MOVE_FORWARD) || axis.y > minVal)
- force += _cameraNode->getFirstChild()->getForwardVectorWorld();
- if (_inputMask & MOVE_BACKWARD || axis.y < -minVal)
- force -= _cameraNode->getFirstChild()->getForwardVectorWorld();
- if (_inputMask & MOVE_LEFT || axis.x < -minVal)
- force += _cameraNode->getRightVectorWorld();
- if (_inputMask & MOVE_RIGHT || axis.y > minVal)
- force -= _cameraNode->getRightVectorWorld();
- if (force.lengthSquared() > 1.f) force.normalize();
- _cameraAcceleration += force / MASS;
- _cameraAcceleration *= FRICTION;
- if (_cameraAcceleration.lengthSquared() < 0.01f)
- _cameraAcceleration = Vector3::zero();
- _cameraNode->translate(_cameraAcceleration * SPEED * (elapsedTime / 1000.f));
-
- // Make sure the reflection camera follows
- Vector3 position = _cameraNode->getTranslation();
- position.y = -position.y + _waterHeight * 2.f;
- _reflectCameraNode->setTranslation(position);
- }
- void WaterSample::render(float elapsedTime)
- {
- const Vector4 clearColour(0.84f, 0.89f, 1.f, 1.f);
-
- // Update the refract buffer
- FrameBuffer* defaultBuffer = _refractBuffer->bind();
- Rectangle defaultViewport = getViewport();
- setViewport(Rectangle(BUFFER_SIZE, BUFFER_SIZE));
- _clipPlane.y = -1.f;
- _clipPlane.w = _waterHeight + WATER_OFFSET;
- clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
- _scene->visit(this, &WaterSample::drawScene, false);
- // Switch plane direction and camera, and update reflection buffer
- _reflectBuffer->bind();
- _clipPlane.y = 1.f;
- _clipPlane.w = -_waterHeight + WATER_OFFSET;
- Camera* defaultCamera = _scene->getActiveCamera();
- _scene->setActiveCamera(_reflectCameraNode->getFirstChild()->getCamera());
- // Store the mvp matrix here as it is only valid when reflect camera is active
- m_worldViewProjectionReflection = _scene->findNode("Water")->getWorldViewProjectionMatrix();
- clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
- _scene->visit(this, &WaterSample::drawScene, false);
- // Draw the final scene
- defaultBuffer->bind();
- setViewport(defaultViewport);
- _clipPlane = Vector4::zero();
- _scene->setActiveCamera(defaultCamera);
- clear(CLEAR_COLOR_DEPTH, clearColour, 1.0f, 0);
- _scene->visit(this, &WaterSample::drawScene, true);
- // Draw preview if enabled
- if (_showBuffers)
- {
- _refractBatch->start();
- _refractBatch->draw(Vector3(0.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
- _refractBatch->finish();
- _reflectBatch->start();
- _reflectBatch->draw(Vector3(430.f, 4.f, 0.f), Rectangle(BUFFER_SIZE, BUFFER_SIZE), Vector2(426.f, 240.f));
- _reflectBatch->finish();
- }
- // Draw the gamepad
- _gamepad->draw();
- drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 1, getFrameRate());
- }
- void WaterSample::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
- {
- switch (evt)
- {
- case Touch::TOUCH_PRESS:
- if (x < 75 && y < 50)
- {
- // Toggle buffer preview if the user touches the top left corner
- _showBuffers = !_showBuffers;
- }
- _prevX = x;
- _prevY = y;
- break;
- case Touch::TOUCH_RELEASE:
- _prevX = x;
- _prevY = y;
- break;
- case Touch::TOUCH_MOVE:
- {
- int deltaX = x - _prevX;
- int deltaY = y - _prevY;
- _prevX = x;
- _prevY = y;
-
- float xMovement = MATH_DEG_TO_RAD(deltaX * 0.25f);
- float yMovement = MATH_DEG_TO_RAD(-deltaY * 0.25f);
- _cameraNode->rotateY(-xMovement);
- _cameraNode->getFirstChild()->rotateX(yMovement);
- _reflectCameraNode->rotateY(-xMovement);
- _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
- }
- break;
- };
- }
- void WaterSample::keyEvent(Keyboard::KeyEvent evt, int key)
- {
- if (evt == Keyboard::KEY_PRESS)
- {
- switch (key)
- {
- case Keyboard::KEY_SPACE:
- _showBuffers = !_showBuffers;
- break;
- case Keyboard::KEY_W:
- case Keyboard::KEY_UP_ARROW:
- _inputMask |= MOVE_FORWARD;
- break;
- case Keyboard::KEY_S:
- case Keyboard::KEY_DOWN_ARROW:
- _inputMask |= MOVE_BACKWARD;
- break;
- case Keyboard::KEY_A:
- case Keyboard::KEY_LEFT_ARROW:
- _inputMask |= MOVE_LEFT;
- break;
- case Keyboard::KEY_D:
- case Keyboard::KEY_RIGHT_ARROW:
- _inputMask |= MOVE_RIGHT;
- break;
- }
- }
- else if (evt == Keyboard::KEY_RELEASE)
- {
- switch (key)
- {
- case Keyboard::KEY_W:
- case Keyboard::KEY_UP_ARROW:
- _inputMask &= ~MOVE_FORWARD;
- break;
- case Keyboard::KEY_S:
- case Keyboard::KEY_DOWN_ARROW:
- _inputMask &= ~MOVE_BACKWARD;
- break;
- case Keyboard::KEY_A:
- case Keyboard::KEY_LEFT_ARROW:
- _inputMask &= ~MOVE_LEFT;
- break;
- case Keyboard::KEY_D:
- case Keyboard::KEY_RIGHT_ARROW:
- _inputMask &= ~MOVE_RIGHT;
- break;
- }
- }
- }
- bool WaterSample::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
- {
- switch (evt)
- {
- case Mouse::MOUSE_MOVE:
- {
- float xMovement = MATH_DEG_TO_RAD(-x * MOUSE_SPEED);
- float yMovement = MATH_DEG_TO_RAD(-y * MOUSE_SPEED);
- _cameraNode->rotateY(xMovement);
- _cameraNode->getFirstChild()->rotateX(yMovement);
- _reflectCameraNode->rotateY(xMovement);
- _reflectCameraNode->getFirstChild()->rotateX(-yMovement);
- }
- return true;
- case Mouse::MOUSE_PRESS_LEFT_BUTTON:
- _inputMask |= MOVE_FORWARD;
- return true;
- case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
- _inputMask &= ~MOVE_FORWARD;
- return true;
- case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
- _inputMask |= MOVE_BACKWARD;
- return true;
- case Mouse::MOUSE_RELEASE_RIGHT_BUTTON:
- _inputMask &= ~MOVE_BACKWARD;
- return true;
- default: return false;
- }
- return false;
- }
- void WaterSample::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad)
- {
- switch (evt)
- {
- case Gamepad::CONNECTED_EVENT:
- case Gamepad::DISCONNECTED_EVENT:
- _gamepad = getGamepad(0);
- if (_gamepad && _gamepad->isVirtual())
- _gamepad->getForm()->setEnabled(true);
- break;
- }
- }
- bool WaterSample::drawScene(Node* node, bool drawWater)
- {
- std::string id = node->getId();
- if (!drawWater && id == "Water") return true;
-
- Model* model = node->getModel();
- if (model)
- model->draw();
- return true;
- }
|