PostProcess.cpp 13 KB

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