2
0

PostProcessSample.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. // Initialize box model
  69. _modelNode = _scene->findNode("duck");
  70. Model* model = _modelNode->getModel();
  71. Material* material = model->setMaterial("res/common/duck.material");
  72. // Get light node
  73. Node* lightNode = _scene->findNode("directionalLight1");
  74. Light* light = lightNode->getLight();
  75. material->getParameter("u_directionalLightColor[0]")->setValue(light->getColor());
  76. material->getParameter("u_directionalLightDirection[0]")->setValue(lightNode->getForwardVectorView());
  77. // Create one frame buffer for the full screen compositerss.
  78. _frameBuffer = FrameBuffer::create("PostProcessSample", FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
  79. DepthStencilTarget* dst = DepthStencilTarget::create("PostProcessSample", DepthStencilTarget::DEPTH_STENCIL, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
  80. _frameBuffer->setDepthStencilTarget(dst);
  81. SAFE_RELEASE(dst);
  82. // Create our compositors that all output to the default framebuffer.
  83. Compositor* compositor = NULL;
  84. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Passthrough");
  85. _compositors.push_back(compositor);
  86. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Grayscale");
  87. _compositors.push_back(compositor);
  88. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Sepia");
  89. _compositors.push_back(compositor);
  90. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Pixelate");
  91. _compositors.push_back(compositor);
  92. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Sobel Edge");
  93. _compositors.push_back(compositor);
  94. compositor->getMaterial()->getParameter("u_width")->setValue((float)FRAMEBUFFER_WIDTH / 2.0f);
  95. compositor->getMaterial()->getParameter("u_height")->setValue((float)FRAMEBUFFER_HEIGHT / 2.0f);
  96. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Gaussian Blur");
  97. _compositors.push_back(compositor);
  98. compositor->getMaterial()->getParameter("u_length")->setValue(1.0f / ((float)FRAMEBUFFER_WIDTH / 2.0f));
  99. compositor = Compositor::create(_frameBuffer, NULL, "res/common/postprocess/postprocess.material", "Old Film");
  100. _compositors.push_back(compositor);
  101. compositor->getMaterial()->getParameter("u_sepiaValue")->setValue(0.8f);
  102. compositor->getMaterial()->getParameter("u_noiseValue")->setValue(0.4f);
  103. compositor->getMaterial()->getParameter("u_scratchValue")->setValue(0.4f);
  104. compositor->getMaterial()->getParameter("u_innerVignetting")->setValue(0.9f);
  105. compositor->getMaterial()->getParameter("u_outerVignetting")->setValue(0.9f);
  106. }
  107. void PostProcessSample::finalize()
  108. {
  109. SAFE_RELEASE(_font);
  110. SAFE_RELEASE(_scene);
  111. for (std::vector<Compositor*>::iterator it = _compositors.begin(); it != _compositors.end(); ++it)
  112. {
  113. delete *it;
  114. }
  115. _compositors.clear();
  116. SAFE_RELEASE(_quadModel);
  117. SAFE_RELEASE(_frameBuffer);
  118. }
  119. void PostProcessSample::update(float elapsedTime)
  120. {
  121. _modelNode->rotateY(elapsedTime * MATH_DEG_TO_RAD(0.25f));
  122. // Only the last sample will check live updating of material parameters
  123. if (_compositorIndex == _compositors.size() - 1)
  124. {
  125. Compositor* compositor = _compositors[_compositorIndex];
  126. MaterialParameter* elapsedParam = compositor->getMaterial()->getParameter("u_elapsedTime");
  127. if (elapsedParam)
  128. elapsedParam->setValue(elapsedTime);
  129. MaterialParameter* randomParam = compositor->getMaterial()->getParameter("u_random");
  130. if (randomParam)
  131. randomParam->setValue(MATH_RANDOM_0_1());
  132. }
  133. }
  134. void PostProcessSample::render(float elapsedTime)
  135. {
  136. Rectangle defaultViewport = Game::getInstance()->getViewport();
  137. // Draw into the framebuffer
  138. Game::getInstance()->setViewport(Rectangle(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT));
  139. FrameBuffer* previousFrameBuffer = _frameBuffer->bind();
  140. clear(CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0f, 0);
  141. _scene->visit(this, &PostProcessSample::drawScene);
  142. // Bind the current compositor
  143. Game::getInstance()->setViewport(defaultViewport);
  144. Compositor* compositor = _compositors[_compositorIndex];
  145. FrameBuffer* compositorDstFrameBuffer = compositor->getDstFrameBuffer();
  146. FrameBuffer* prevToCompositeFrameBuffer = NULL;
  147. if (compositorDstFrameBuffer)
  148. {
  149. prevToCompositeFrameBuffer = compositorDstFrameBuffer->bind();
  150. }
  151. else
  152. {
  153. prevToCompositeFrameBuffer = previousFrameBuffer->bind();
  154. }
  155. Game::getInstance()->clear(CLEAR_COLOR, Vector4(0, 0, 0, 1), 1.0f, 0);
  156. compositor->blit(defaultViewport);
  157. drawFrameRate(_font, Vector4(0, 0.5f, 1, 1), 5, 1, getFrameRate());
  158. drawTechniqueId(compositor->getTechniqueId());
  159. previousFrameBuffer->bind();
  160. // 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
  161. float quarterWidth = getWidth() / 4;
  162. float quarterHeight = getHeight() / 4;
  163. Rectangle offsetViewport = Rectangle(getWidth() - quarterWidth, 0, quarterWidth, quarterHeight);
  164. Game::getInstance()->setViewport(offsetViewport);
  165. compositor = _compositors[0];
  166. compositor->blit(offsetViewport);
  167. Game::getInstance()->setViewport(defaultViewport);
  168. }
  169. bool PostProcessSample::drawScene(Node* node)
  170. {
  171. // If the node visited contains a model, draw it
  172. Model* model = node->getModel();
  173. if (model)
  174. {
  175. model->draw();
  176. }
  177. return true;
  178. }
  179. void PostProcessSample::drawTechniqueId(const char* techniqueId)
  180. {
  181. char buffer[128];
  182. sprintf(buffer, "%s", techniqueId);
  183. _font->start();
  184. _font->drawText(buffer, Rectangle(0, 10, getWidth(), getHeight()), Vector4::one(), _font->getSize(), Font::ALIGN_TOP_HCENTER);
  185. _font->finish();
  186. }
  187. void PostProcessSample::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  188. {
  189. switch (evt)
  190. {
  191. case Touch::TOUCH_PRESS:
  192. {
  193. _compositorIndex++;
  194. if (_compositorIndex == _compositors.size())
  195. _compositorIndex = 0;
  196. }
  197. break;
  198. default:
  199. break;
  200. };
  201. }