2
0

PostProcess.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. #include "PostProcess.h"
  2. #include "Actor.h"
  3. #include "core/gl/VertexDeclarationGL.h"
  4. #include "core/gl/ShaderProgramGL.h"
  5. #include "core/oxygine.h"
  6. #include "RenderState.h"
  7. #include "STDMaterial.h"
  8. #include "core/file.h"
  9. #include "core/system_data.h"
  10. #include "core/ZipFileSystem.h"
  11. namespace oxygine
  12. {
  13. ShaderProgram* PostProcess::shaderBlurV = 0;
  14. ShaderProgram* PostProcess::shaderBlurH = 0;
  15. ShaderProgram* PostProcess::shaderBlit = 0;
  16. void PostProcess::initShaders()
  17. {
  18. if (PostProcess::shaderBlurH)
  19. return;
  20. file::Zips zp;
  21. zp.add(system_data, system_size);
  22. const VertexDeclarationGL* decl = static_cast<const VertexDeclarationGL*>(IVideoDriver::instance->getVertexDeclaration(vertexPCT2::FORMAT));
  23. file::buffer vs_h;
  24. file::buffer vs_v;
  25. file::buffer fs_blur;
  26. zp.read("system/pp_hblur_vs.glsl", vs_h);
  27. zp.read("system/pp_vblur_vs.glsl", vs_v);
  28. zp.read("system/pp_rast_fs.glsl", fs_blur);
  29. vs_h.push_back(0);
  30. vs_v.push_back(0);
  31. fs_blur.push_back(0);
  32. unsigned int h = ShaderProgramGL::createShader(GL_VERTEX_SHADER, (const char*)&vs_h.front(), "", "");
  33. unsigned int v = ShaderProgramGL::createShader(GL_VERTEX_SHADER, (const char*)&vs_v.front(), "", "");
  34. unsigned int ps = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, (const char*)&fs_blur.front(), "", "");
  35. IVideoDriver* driver = IVideoDriver::instance;
  36. shaderBlurV = new ShaderProgramGL(ShaderProgramGL::createProgram(v, ps, decl));
  37. driver->setShaderProgram(shaderBlurV);
  38. driver->setUniformInt("s_texture", 0);
  39. shaderBlurH = new ShaderProgramGL(ShaderProgramGL::createProgram(h, ps, decl));
  40. driver->setShaderProgram(shaderBlurH);
  41. driver->setUniformInt("s_texture", 0);
  42. file::buffer vs_blit;
  43. file::buffer fs_blit;
  44. zp.read("system/pp_blit_vs.glsl", vs_blit);
  45. zp.read("system/pp_blit_fs.glsl", fs_blit);
  46. vs_blit.push_back(0);
  47. fs_blit.push_back(0);
  48. unsigned int vs = ShaderProgramGL::createShader(GL_VERTEX_SHADER, (const char*)&vs_blit.front(), "", "");
  49. unsigned int fs = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, (const char*)&fs_blit.front(), "", "");
  50. shaderBlit = new ShaderProgramGL(ShaderProgramGL::createProgram(vs, fs, decl));
  51. driver->setShaderProgram(shaderBlit);
  52. driver->setUniformInt("s_texture", 0);
  53. }
  54. void PostProcess::freeShaders()
  55. {
  56. delete shaderBlit;
  57. shaderBlit = 0;
  58. delete shaderBlurH;
  59. shaderBlurH = 0;
  60. delete shaderBlurV;
  61. shaderBlurV = 0;
  62. }
  63. const int ALIGN_SIZE = 256;
  64. const int TEXTURE_LIVE = 3000;
  65. const int MAX_FREE_TEXTURES = 3;
  66. using namespace std;
  67. DECLARE_SMART(TweenPostProcess, spTweenPostProcess);
  68. vector<spTweenPostProcess> postProcessItems;
  69. int alignTextureSize(int v)
  70. {
  71. int n = (v - 1) / ALIGN_SIZE;
  72. return (n + 1) * ALIGN_SIZE;
  73. }
  74. class NTP
  75. {
  76. public:
  77. int _w;
  78. int _h;
  79. TextureFormat _tf;
  80. NTP(int w, int h, TextureFormat tf) : _w(w), _h(h), _tf(tf) {}
  81. bool operator()(const spNativeTexture& t1, const spNativeTexture& t2) const
  82. {
  83. if (t1->getFormat() < _tf)
  84. return true;
  85. if (t1->getWidth() < _w)
  86. return true;
  87. return t1->getHeight() < _h;
  88. }
  89. static bool cmp(const spNativeTexture& t2, const spNativeTexture& t1)
  90. {
  91. if (t1->getFormat() > t2->getFormat())
  92. return true;
  93. if (t1->getWidth() > t2->getWidth())
  94. return true;
  95. return t1->getHeight() > t2->getHeight();
  96. }
  97. };
  98. RenderTargetsManager::RenderTargetsManager()
  99. {
  100. //get(10, 15, TF_R8G8B8A8);
  101. //get(10, 15, TF_R8G8B8A8);
  102. }
  103. void RenderTargetsManager::print()
  104. {
  105. log::messageln("print");
  106. for (size_t i = 0, sz = _free.size(); i < sz; ++i)
  107. {
  108. spNativeTexture t = _free[i];
  109. log::messageln("texture %d %d", t->getWidth(), t->getHeight());
  110. }
  111. }
  112. bool RenderTargetsManager::isGood(const spNativeTexture& t, int w, int h, TextureFormat tf) const
  113. {
  114. if (!t)
  115. return false;
  116. if (!t->getHandle())
  117. return false;
  118. if (t->getFormat() == tf &&
  119. t->getWidth() >= w && t->getHeight() >= h &&
  120. t->getWidth() <= (w + ALIGN_SIZE) && t->getHeight() <= (h + ALIGN_SIZE))
  121. return true;
  122. return false;
  123. }
  124. spNativeTexture RenderTargetsManager::get(spNativeTexture current, int w, int h, TextureFormat tf)
  125. {
  126. w = alignTextureSize(w);
  127. h = alignTextureSize(h);
  128. if (isGood(current, w, h, tf))
  129. {
  130. current->setUserData((void*)(size_t)getTimeMS());
  131. return current;
  132. }
  133. spNativeTexture result;
  134. free::iterator it = lower_bound(_free.begin(), _free.end(), result, NTP(w, h, tf));
  135. if (it != _free.end())
  136. {
  137. spNativeTexture& t = *it;
  138. if (isGood(t, w, h, tf))
  139. {
  140. result = t;
  141. _free.erase(it);
  142. }
  143. }
  144. if (!result)
  145. {
  146. //if texture wasn't found create it
  147. result = IVideoDriver::instance->createTexture();
  148. result->init(w, h, tf, true);
  149. }
  150. result->setUserData((void*)(size_t)getTimeMS());
  151. _rts.push_back(result);
  152. //print();
  153. return result;
  154. }
  155. void RenderTargetsManager::update()
  156. {
  157. timeMS tm = getTimeMS();
  158. for (size_t i = 0, sz = _rts.size(); i < sz; ++i)
  159. {
  160. spNativeTexture& texture = _rts[i];
  161. if (texture->_ref_counter == 1)
  162. {
  163. free::iterator it = lower_bound(_free.begin(), _free.end(), texture, NTP::cmp);
  164. _free.insert(it, texture);
  165. _rts.erase(_rts.begin() + i);
  166. --i;
  167. --sz;
  168. continue;
  169. }
  170. }
  171. for (size_t i = 0, sz = _free.size(); i < sz; ++i)
  172. {
  173. spNativeTexture& t = _free[i];
  174. timeMS createTime = (timeMS)(size_t)t->getUserData();
  175. if (createTime + TEXTURE_LIVE > tm)
  176. continue;
  177. _free.erase(_free.begin() + i);
  178. --i;
  179. --sz;
  180. }
  181. if (_free.size() > MAX_FREE_TEXTURES)
  182. {
  183. _free.erase(_free.begin(), _free.begin() + _free.size() - MAX_FREE_TEXTURES);
  184. }
  185. }
  186. void RenderTargetsManager::reset()
  187. {
  188. _free.clear();
  189. _rts.clear();
  190. }
  191. RenderTargetsManager _rtm;
  192. RenderTargetsManager& getRTManager()
  193. {
  194. return _rtm;
  195. }
  196. void updatePortProcessItems()
  197. {
  198. if (!postProcessItems.empty())
  199. {
  200. Material::setCurrent(0);
  201. IVideoDriver* driver = IVideoDriver::instance;
  202. driver->setState(IVideoDriver::STATE_BLEND, 0);
  203. spNativeTexture prevRT = driver->getRenderTarget();
  204. for (size_t i = 0; i < postProcessItems.size(); ++i)
  205. {
  206. spTweenPostProcess p = postProcessItems[i];
  207. p->renderPP();
  208. p->getActor()->releaseRef();
  209. }
  210. postProcessItems.clear();
  211. driver->setRenderTarget(prevRT);
  212. }
  213. _rtm.update();
  214. }
  215. void clearPostProcessItems()
  216. {
  217. postProcessItems.clear();
  218. _rtm.reset();
  219. }
  220. void pass(spNativeTexture srcTexture, const Rect& srcRect, spNativeTexture destTexture, const Rect& destRect, const Color& color)
  221. {
  222. IVideoDriver* driver = IVideoDriver::instance;
  223. const VertexDeclarationGL* decl = static_cast<const VertexDeclarationGL*>(driver->getVertexDeclaration(vertexPCT2::FORMAT));
  224. driver->setRenderTarget(destTexture);
  225. driver->clear(0);
  226. driver->setViewport(destRect);
  227. driver->setTexture(0, srcTexture);
  228. vertexPCT2 v[4];
  229. RectF dst = srcRect.cast<RectF>() / Vector2((float)srcTexture->getWidth(), (float)srcTexture->getHeight());
  230. fillQuadT(v,
  231. dst,
  232. RectF(-1, -1, 2, 2),
  233. AffineTransform::getIdentity(), color.rgba());
  234. driver->draw(IVideoDriver::PT_TRIANGLE_STRIP, decl, v, sizeof(v));
  235. driver->setTexture(0, 0);
  236. }
  237. PostProcess::PostProcess(const PostProcessOptions& opt) : _options(opt), _format(TF_R4G4B4A4), _extend(2, 2)
  238. {
  239. }
  240. PostProcess::~PostProcess()
  241. {
  242. }
  243. void PostProcess::free()
  244. {
  245. _rt = 0;
  246. }
  247. Rect PostProcess::getScreenRect(const Actor& actor) const
  248. {
  249. Rect screen;
  250. Rect display(Point(0, 0), core::getDisplaySize());
  251. if (_options._flags & PostProcessOptions::flag_fullscreen)
  252. return display;
  253. screen = actor.computeBounds(actor.computeGlobalTransform()).cast<Rect>();
  254. screen.size += Point(1, 1);
  255. screen.expand(_extend, _extend);
  256. if (!(_options._flags & PostProcessOptions::flag_singleR2T))
  257. screen.clip(display);
  258. return screen.cast<Rect>();
  259. }
  260. void PostProcess::update(Actor* actor)
  261. {
  262. _screen = getScreenRect(*actor);
  263. // OX_ASSERT(actor->_getStage());
  264. _rt = getRTManager().get(_rt, _screen.getWidth(), _screen.getHeight(), _format);
  265. _transform = actor->computeGlobalTransform().inverted();
  266. Material::setCurrent(0);
  267. IVideoDriver* driver = IVideoDriver::instance;
  268. driver->setRenderTarget(_rt);
  269. Rect vp = _screen;
  270. vp.pos = Point(0, 0);
  271. driver->setViewport(vp);
  272. driver->clear(0);
  273. RenderState rs;
  274. STDMaterial* mat = STDMaterial::instance;
  275. STDRenderer* renderer = mat->getRenderer();
  276. rs.material = mat;
  277. RectF clip = vp.cast<RectF>();
  278. rs.clip = &clip;
  279. renderer->initCoordinateSystem(vp.getWidth(), vp.getHeight(), true);
  280. rs.transform = actor->getParent()->computeGlobalTransform();
  281. if (!(_options._flags & PostProcessOptions::flag_fullscreen))
  282. {
  283. AffineTransform offset;
  284. offset.identity();
  285. offset.translate(-_screen.pos);
  286. rs.transform = rs.transform * offset;
  287. }
  288. mat->Material::render(actor, rs);
  289. mat->finish();
  290. }
  291. TweenPostProcess::TweenPostProcess(const PostProcessOptions& opt) : _pp(opt), _prevMaterial(0), _actor(0)
  292. {
  293. }
  294. TweenPostProcess::~TweenPostProcess()
  295. {
  296. if (_actor && _actor->getMaterial())
  297. _actor->setMaterial(_prevMaterial);
  298. }
  299. void TweenPostProcess::renderPP()
  300. {
  301. if (_pp._options._flags & PostProcessOptions::flag_singleR2T && _pp._rt)
  302. return;
  303. _pp.update(_actor);
  304. _renderPP();
  305. }
  306. void TweenPostProcess::init(Actor& actor)
  307. {
  308. _actor = &actor;
  309. _prevMaterial = _actor->getMaterial();
  310. _actor->setMaterial(this);
  311. }
  312. void TweenPostProcess::update(Actor& actor, float p, const UpdateState& us)
  313. {
  314. _progress = p;
  315. if (find(postProcessItems.begin(), postProcessItems.end(), this) == postProcessItems.end())
  316. {
  317. _actor->addRef();
  318. postProcessItems.push_back(this);
  319. }
  320. }
  321. void TweenPostProcess::done(Actor& actor)
  322. {
  323. if (_actor->getMaterial())
  324. _actor->setMaterial(_prevMaterial);
  325. }
  326. }