PostProcessSample.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include "PostProcessSample.h"
  2. #include "SamplesGame.h"
  3. #if defined(ADD_SAMPLE)
  4. ADD_SAMPLE("Graphics", "Post Process", PostProcessSample, 13);
  5. #endif
  6. #define FRAMEBUFFER_WIDTH 1024
  7. #define FRAMEBUFFER_HEIGHT 1024
  8. Model* PostProcessSample::_quadModel = NULL;
  9. Material* PostProcessSample::_compositorMaterial = NULL;
  10. PostProcessSample::Compositor* PostProcessSample::Compositor::create(FrameBuffer* srcBuffer, FrameBuffer* dstBuffer, const char* materialPath, const char* techniqueId)
  11. {
  12. GP_ASSERT(srcBuffer);
  13. Material* material = Material::create(materialPath);
  14. Texture::Sampler* sampler = Texture::Sampler::create(srcBuffer->getRenderTarget()->getTexture());
  15. material->getParameter("u_texture")->setValue(sampler);
  16. SAFE_RELEASE(sampler);
  17. if (_quadModel == NULL)
  18. {
  19. Mesh* mesh = Mesh::createQuadFullscreen();
  20. _quadModel = Model::create(mesh);
  21. SAFE_RELEASE(mesh);
  22. }
  23. return new Compositor(srcBuffer, dstBuffer, material, techniqueId);
  24. }
  25. PostProcessSample::Compositor::Compositor(FrameBuffer* srcBuffer, FrameBuffer* dstBuffer, Material* material, const char* techniqueId)
  26. : _srcBuffer(srcBuffer), _dstBuffer(dstBuffer), _material(material), _techniqueId(techniqueId)
  27. {
  28. }
  29. PostProcessSample::Compositor::~Compositor()
  30. {
  31. SAFE_RELEASE(_material);
  32. }
  33. FrameBuffer* PostProcessSample::Compositor::getSrcFrameBuffer() const
  34. {
  35. return _srcBuffer;
  36. }
  37. FrameBuffer* PostProcessSample::Compositor::getDstFrameBuffer() const
  38. {
  39. return _dstBuffer;
  40. }
  41. const char* PostProcessSample::Compositor::getTechniqueId() const
  42. {
  43. return _techniqueId;
  44. }
  45. Material* PostProcessSample::Compositor::getMaterial() const
  46. {
  47. return _material;
  48. }
  49. void PostProcessSample::Compositor::blit(const Rectangle& dst)
  50. {
  51. if (_compositorMaterial != _material)
  52. {
  53. _compositorMaterial = _material;
  54. _quadModel->setMaterial(_compositorMaterial);
  55. }
  56. _compositorMaterial->setTechnique(_techniqueId);
  57. _quadModel->draw();
  58. }
  59. PostProcessSample::PostProcessSample()
  60. : _font(NULL), _scene(NULL), _modelNode(NULL), _frameBuffer(NULL), _compositorIndex(0)
  61. {
  62. }
  63. void PostProcessSample::initialize()
  64. {
  65. _font = Font::create("res/common/arial.gpb");
  66. // Load game scene from file
  67. _scene = Scene::load("res/common/duck.gpb");
  68. _scene->getActiveCamera()->setAspectRatio(getAspectRatio());
  69. // Initialize box model
  70. _modelNode = _scene->findNode("duck");
  71. Model* model = _modelNode->getModel();
  72. Material* material = model->setMaterial("res/common/duck.material");
  73. // Get light node
  74. Node* lightNode = _scene->findNode("directionalLight1");
  75. Light* light = lightNode->getLight();
  76. material->getParameter("u_directionalLightColor[0]")->setValue(light->getColor());
  77. material->getParameter("u_directionalLightDirection[0]")->setValue(lightNode->getForwardVectorView());
  78. // Create one frame buffer for the full screen compositerss.
  79. _frameBuffer = FrameBuffer::create("PostProcessSample", FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
  80. DepthStencilTarget* dst = DepthStencilTarget::create("PostProcessSample", DepthStencilTarget::DEPTH_STENCIL, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
  81. _frameBuffer->setDepthStencilTarget(dst);
  82. SAFE_RELEASE(dst);
  83. // Create our compositors that all output to the default framebuffer.
  84. Compositor* compositor = NULL;
  85. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Passthrough");
  86. _compositors.push_back(compositor);
  87. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Grayscale");
  88. _compositors.push_back(compositor);
  89. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Sepia");
  90. _compositors.push_back(compositor);
  91. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Pixelate");
  92. _compositors.push_back(compositor);
  93. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Sobel Edge");
  94. _compositors.push_back(compositor);
  95. compositor->getMaterial()->getParameter("u_width")->setValue((float)FRAMEBUFFER_WIDTH / 2.0f);
  96. compositor->getMaterial()->getParameter("u_height")->setValue((float)FRAMEBUFFER_HEIGHT / 2.0f);
  97. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Gaussian Blur");
  98. _compositors.push_back(compositor);
  99. compositor->getMaterial()->getParameter("u_length")->setValue(1.0f / ((float)FRAMEBUFFER_WIDTH / 2.0f));
  100. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Old Film");
  101. _compositors.push_back(compositor);
  102. compositor->getMaterial()->getParameter("u_sepiaValue")->setValue(0.8f);
  103. compositor->getMaterial()->getParameter("u_noiseValue")->setValue(0.4f);
  104. compositor->getMaterial()->getParameter("u_scratchValue")->setValue(0.4f);
  105. compositor->getMaterial()->getParameter("u_innerVignetting")->setValue(0.9f);
  106. compositor->getMaterial()->getParameter("u_outerVignetting")->setValue(0.9f);
  107. }
  108. void PostProcessSample::finalize()
  109. {
  110. SAFE_RELEASE(_font);
  111. SAFE_RELEASE(_scene);
  112. for (std::vector<Compositor*>::iterator it = _compositors.begin(); it != _compositors.end(); ++it)
  113. {
  114. delete *it;
  115. }
  116. _compositors.clear();
  117. SAFE_RELEASE(_quadModel);
  118. SAFE_RELEASE(_frameBuffer);
  119. }
  120. void PostProcessSample::update(float elapsedTime)
  121. {
  122. _modelNode->rotateY(elapsedTime * MATH_DEG_TO_RAD(0.25f));
  123. // Only the last sample will check live updating of material parameters
  124. if (_compositorIndex == _compositors.size() - 1)
  125. {
  126. Compositor* compositor = _compositors[_compositorIndex];
  127. MaterialParameter* elapsedParam = compositor->getMaterial()->getParameter("u_elapsedTime");
  128. if (elapsedParam)
  129. elapsedParam->setValue(elapsedTime);
  130. MaterialParameter* randomParam = compositor->getMaterial()->getParameter("u_random");
  131. if (randomParam)
  132. randomParam->setValue(MATH_RANDOM_0_1());
  133. }
  134. }
  135. void PostProcessSample::render(float elapsedTime)
  136. {
  137. Rectangle defaultViewport = Game::getInstance()->getViewport();
  138. // Draw into the framebuffer
  139. Game::getInstance()->setViewport(Rectangle(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT));
  140. FrameBuffer* previousFrameBuffer = _frameBuffer->bind();
  141. clear(CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0f, 0);
  142. _scene->visit(this, &PostProcessSample::drawScene);
  143. // Bind the current compositor
  144. Game::getInstance()->setViewport(defaultViewport);
  145. Compositor* compositor = _compositors[_compositorIndex];
  146. FrameBuffer* compositorDstFrameBuffer = compositor->getDstFrameBuffer();
  147. FrameBuffer* prevToCompositeFrameBuffer = NULL;
  148. if (compositorDstFrameBuffer)
  149. {
  150. prevToCompositeFrameBuffer = compositorDstFrameBuffer->bind();
  151. }
  152. else
  153. {
  154. prevToCompositeFrameBuffer = previousFrameBuffer->bind();
  155. }
  156. Game::getInstance()->clear(CLEAR_COLOR, Vector4(0, 0, 0, 1), 1.0f, 0);
  157. compositor->blit(defaultViewport);
  158. drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 1, getFrameRate());
  159. drawTechniqueId(compositor->getTechniqueId());
  160. previousFrameBuffer->bind();
  161. // Draw the pass through compositor at index 0 at quarter of the size and bottom right. dont clear the dest just draw last on top
  162. float quarterWidth = getWidth() / 4;
  163. float quarterHeight = getHeight() / 4;
  164. Rectangle offsetViewport = Rectangle(getWidth() - quarterWidth, 0, quarterWidth, quarterHeight);
  165. Game::getInstance()->setViewport(offsetViewport);
  166. compositor = _compositors[0];
  167. compositor->blit(offsetViewport);
  168. Game::getInstance()->setViewport(defaultViewport);
  169. }
  170. bool PostProcessSample::drawScene(Node* node)
  171. {
  172. // If the node visited contains a model, draw it
  173. Model* model = node->getModel();
  174. if (model)
  175. {
  176. model->draw();
  177. }
  178. return true;
  179. }
  180. void PostProcessSample::drawTechniqueId(const char* techniqueId)
  181. {
  182. char buffer[128];
  183. sprintf(buffer, "%s", techniqueId);
  184. _font->start();
  185. _font->drawText(buffer, Rectangle(0, 10, getWidth(), getHeight()), Vector4::one(), _font->getSize(), Font::ALIGN_TOP_HCENTER);
  186. _font->finish();
  187. }
  188. void PostProcessSample::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  189. {
  190. switch (evt)
  191. {
  192. case Touch::TOUCH_PRESS:
  193. {
  194. _compositorIndex++;
  195. if (_compositorIndex == _compositors.size())
  196. _compositorIndex = 0;
  197. }
  198. break;
  199. default:
  200. break;
  201. };
  202. }