CCRenderTexture.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2009 Jason Booth
  4. Copyright (c) 2008-2010 Ricardo Quesada
  5. Copyright (c) 2011 Zynga Inc.
  6. http://www.cocos2d-x.org
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. ****************************************************************************/
  23. /**
  24. * enum for jpg
  25. * @constant
  26. * @type Number
  27. */
  28. cc.IMAGE_FORMAT_JPEG = 0;
  29. /**
  30. * enum for png
  31. * @constant
  32. * @type Number
  33. */
  34. cc.IMAGE_FORMAT_PNG = 1;
  35. /**
  36. * enum for raw
  37. * @constant
  38. * @type Number
  39. */
  40. cc.IMAGE_FORMAT_RAWDATA = 2;
  41. /**
  42. * @param {Number} x
  43. * @return {Number}
  44. * Constructor
  45. */
  46. cc.NextPOT = function (x) {
  47. x = x - 1;
  48. x = x | (x >> 1);
  49. x = x | (x >> 2);
  50. x = x | (x >> 4);
  51. x = x | (x >> 8);
  52. x = x | (x >> 16);
  53. return x + 1;
  54. };
  55. /**
  56. * cc.RenderTexture is a generic rendering target. To render things into it,<br/>
  57. * simply construct a render target, call begin on it, call visit on any cocos<br/>
  58. * scenes or objects to render them, and call end. For convenience, render texture<br/>
  59. * adds a sprite as it's display child with the results, so you can simply add<br/>
  60. * the render texture to your scene and treat it like any other CocosNode.<br/>
  61. * There are also functions for saving the render texture to disk in PNG or JPG format.
  62. * @class
  63. * @extends cc.Node
  64. */
  65. cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{
  66. /**
  67. * the off-screen canvas for rendering and storing the texture
  68. * @type HTMLCanvasElement
  69. */
  70. _cacheCanvas:null,
  71. /**
  72. * stores a reference to the canvas context object
  73. * @type CanvasRenderingContext2D
  74. */
  75. _cacheContext:null,
  76. _fBO:0,
  77. _depthRenderBuffer:0,
  78. _oldFBO:0,
  79. _texture:null,
  80. _textureCopy:null,
  81. _uITextureImage:null,
  82. _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888,
  83. _sprite:null,
  84. //code for "auto" update
  85. _clearFlags:0,
  86. _clearColor:null,
  87. _clearDepth:0,
  88. _clearStencil:0,
  89. _autoDraw:false,
  90. _clearColorStr:null,
  91. /**
  92. * Constructor
  93. */
  94. ctor: null,
  95. _ctorForCanvas: function () {
  96. cc.Node.prototype.ctor.call(this);
  97. this._clearColor = cc.c4f(1, 1, 1, 1);
  98. this._clearColorStr = "rgba(255,255,255,1)";
  99. this._cacheCanvas = document.createElement('canvas');
  100. this._cacheContext = this._cacheCanvas.getContext('2d');
  101. this.setAnchorPoint(0, 0);
  102. },
  103. _ctorForWebGL: function () {
  104. cc.Node.prototype.ctor.call(this);
  105. this._clearColor = cc.c4f(0, 0, 0, 0);
  106. },
  107. cleanup:null,
  108. _cleanupForCanvas:function () {
  109. cc.Node.prototype.onExit.call(this);
  110. this._cacheContext = null;
  111. this._cacheCanvas = null;
  112. },
  113. _cleanupForWebGL: function () {
  114. cc.Node.prototype.onExit.call(this);
  115. //this._sprite = null;
  116. this._textureCopy = null;
  117. var gl = cc.renderContext;
  118. gl.deleteFramebuffer(this._fBO);
  119. if (this._depthRenderBuffer)
  120. gl.deleteRenderbuffer(this._depthRenderBuffer);
  121. this._uITextureImage = null;
  122. //if (this._texture)
  123. // this._texture.releaseTexture();
  124. },
  125. /**
  126. * The sprite
  127. * @return {cc.Sprite}
  128. */
  129. getSprite:function () {
  130. return this._sprite;
  131. },
  132. /**
  133. * @param {cc.Sprite} sprite
  134. */
  135. setSprite:function (sprite) {
  136. this._sprite = sprite;
  137. },
  138. /**
  139. * @param {Number} width
  140. * @param {Number} height
  141. * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
  142. * @param {Number} depthStencilFormat
  143. * @return {Boolean}
  144. */
  145. initWithWidthAndHeight: null,
  146. _initWithWidthAndHeightForCanvas: function (width, height, format, depthStencilFormat) {
  147. var locCacheCanvas = this._cacheCanvas, locScaleFactor = cc.CONTENT_SCALE_FACTOR();
  148. locCacheCanvas.width = 0 | (width * locScaleFactor);
  149. locCacheCanvas.height = 0 | (height * locScaleFactor);
  150. this._cacheContext.translate(0, locCacheCanvas.height);
  151. var texture = new cc.Texture2D();
  152. texture.initWithElement(locCacheCanvas);
  153. texture.handleLoadedTexture();
  154. this._sprite = cc.Sprite.createWithTexture(texture);
  155. return true;
  156. },
  157. _initWithWidthAndHeightForWebGL: function (width, height, format, depthStencilFormat) {
  158. if(format == cc.TEXTURE_2D_PIXEL_FORMAT_A8)
  159. cc.log( "cc.RenderTexture._initWithWidthAndHeightForWebGL() : only RGB and RGBA formats are valid for a render texture;");
  160. var gl = cc.renderContext, locScaleFactor = cc.CONTENT_SCALE_FACTOR();
  161. width = 0 | (width * locScaleFactor);
  162. height = 0 | (height * locScaleFactor);
  163. this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
  164. // textures must be power of two squared
  165. var powW , powH;
  166. if (cc.Configuration.getInstance().supportsNPOT()) {
  167. powW = width;
  168. powH = height;
  169. } else {
  170. powW = cc.NextPOT(width);
  171. powH = cc.NextPOT(height);
  172. }
  173. //void *data = malloc(powW * powH * 4);
  174. var dataLen = powW * powH * 4;
  175. var data = new Uint8Array(dataLen);
  176. //memset(data, 0, (int)(powW * powH * 4));
  177. for (var i = 0; i < powW * powH * 4; i++)
  178. data[i] = 0;
  179. this._pixelFormat = format;
  180. this._texture = new cc.Texture2D();
  181. if (!this._texture)
  182. return false;
  183. var locTexture = this._texture;
  184. locTexture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
  185. //free( data );
  186. var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING);
  187. if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) {
  188. this._textureCopy = new cc.Texture2D();
  189. if (!this._textureCopy) {
  190. return false;
  191. }
  192. this._textureCopy.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
  193. }
  194. // generate FBO
  195. this._fBO = gl.createFramebuffer();
  196. gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);
  197. // associate texture with FBO
  198. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0);
  199. if (depthStencilFormat != 0) {
  200. //create and attach depth buffer
  201. this._depthRenderBuffer = gl.createRenderbuffer();
  202. gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer);
  203. gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH);
  204. gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
  205. // if depth format is the one with stencil part, bind same render buffer as stencil attachment
  206. //if (depthStencilFormat == gl.DEPTH24_STENCIL8)
  207. // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
  208. }
  209. // check if it worked (probably worth doing :) )
  210. if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE)
  211. cc.log("Could not attach texture to the framebuffer");
  212. locTexture.setAliasTexParameters();
  213. this._sprite = cc.Sprite.createWithTexture(locTexture);
  214. var locSprite = this._sprite;
  215. locSprite.setScaleY(-1);
  216. locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  217. gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO);
  218. gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
  219. // Disabled by default.
  220. this._autoDraw = false;
  221. // add sprite for backward compatibility
  222. this.addChild(locSprite);
  223. return true;
  224. },
  225. /**
  226. * starts grabbing
  227. */
  228. begin: null,
  229. _beginForCanvas: function () {
  230. cc.renderContext = this._cacheContext;
  231. cc.EGLView.getInstance()._setScaleXYForRenderTexture();
  232. /*// Save the current matrix
  233. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  234. cc.kmGLPushMatrix();
  235. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  236. cc.kmGLPushMatrix();*/
  237. },
  238. _beginForWebGL: function () {
  239. // Save the current matrix
  240. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  241. cc.kmGLPushMatrix();
  242. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  243. cc.kmGLPushMatrix();
  244. var director = cc.Director.getInstance();
  245. director.setProjection(director.getProjection());
  246. var texSize = this._texture.getContentSizeInPixels();
  247. // Calculate the adjustment ratios based on the old and new projections
  248. var size = cc.Director.getInstance().getWinSizeInPixels();
  249. var widthRatio = size.width / texSize.width;
  250. var heightRatio = size.height / texSize.height;
  251. var gl = cc.renderContext;
  252. // Adjust the orthographic projection and viewport
  253. gl.viewport(0, 0, texSize.width, texSize.height);
  254. var orthoMatrix = new cc.kmMat4();
  255. cc.kmMat4OrthographicProjection(orthoMatrix, -1.0 / widthRatio, 1.0 / widthRatio,
  256. -1.0 / heightRatio, 1.0 / heightRatio, -1, 1);
  257. cc.kmGLMultMatrix(orthoMatrix);
  258. this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
  259. gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);//Will direct drawing to the frame buffer created above
  260. /* Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture.
  261. * The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture.
  262. * Create a temporary texture to overcome this. At the end of CCRenderTexture::begin(), switch the attached texture to the second one, call glClear,
  263. * and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
  264. */
  265. if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) {
  266. // -- bind a temporary texture so we can clear the render buffer without losing our texture
  267. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._textureCopy._webTextureObj, 0);
  268. //cc.CHECK_GL_ERROR_DEBUG();
  269. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  270. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0);
  271. }
  272. },
  273. /**
  274. * starts rendering to the texture while clearing the texture first.<br/>
  275. * This is more efficient then calling -clear first and then -begin
  276. * @param {Number} r red 0-1
  277. * @param {Number} g green 0-1
  278. * @param {Number} b blue 0-1
  279. * @param {Number} a alpha 0-1 0 is transparent
  280. * @param {Number} [depthValue=]
  281. * @param {Number} [stencilValue=]
  282. */
  283. beginWithClear:function (r, g, b, a, depthValue, stencilValue) {
  284. var gl = cc.renderContext;
  285. depthValue = depthValue || gl.COLOR_BUFFER_BIT;
  286. stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  287. this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
  288. },
  289. _beginWithClear: null,
  290. _beginWithClearForCanvas: function (r, g, b, a, depthValue, stencilValue, flags) {
  291. this.begin();
  292. r = r || 0;
  293. g = g || 0;
  294. b = b || 0;
  295. a = isNaN(a) ? 1 : a;
  296. //var context = cc.renderContext;
  297. var context = this._cacheContext;
  298. var locCanvas = this._cacheCanvas;
  299. context.save();
  300. context.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")";
  301. context.clearRect(0, 0, locCanvas.width, -locCanvas.height);
  302. context.fillRect(0, 0, locCanvas.width, -locCanvas.height);
  303. context.restore();
  304. },
  305. _beginWithClearForWebGL: function (r, g, b, a, depthValue, stencilValue, flags) {
  306. this.begin();
  307. var gl = cc.renderContext;
  308. // save clear color
  309. var clearColor = [0.0, 0.0, 0.0, 0.0];
  310. var depthClearValue = 0.0;
  311. var stencilClearValue = 0;
  312. if (flags & gl.COLOR_BUFFER_BIT) {
  313. clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
  314. gl.clearColor(r, g, b, a);
  315. }
  316. if (flags & gl.DEPTH_BUFFER_BIT) {
  317. depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
  318. gl.clearDepth(depthValue);
  319. }
  320. if (flags & gl.STENCIL_BUFFER_BIT) {
  321. stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
  322. gl.clearStencil(stencilValue);
  323. }
  324. gl.clear(flags);
  325. // restore
  326. if (flags & gl.COLOR_BUFFER_BIT)
  327. gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
  328. if (flags & gl.DEPTH_BUFFER_BIT)
  329. gl.clearDepth(depthClearValue);
  330. if (flags & gl.STENCIL_BUFFER_BIT)
  331. gl.clearStencil(stencilClearValue);
  332. },
  333. /**
  334. * ends grabbing
  335. */
  336. end: null,
  337. _endForCanvas: function () {
  338. cc.renderContext = cc.mainRenderContextBackup;
  339. cc.EGLView.getInstance()._resetScale();
  340. //TODO
  341. /*//restore viewport
  342. director.setViewport();
  343. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  344. cc.kmGLPopMatrix();
  345. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  346. cc.kmGLPopMatrix();*/
  347. },
  348. _endForWebGL: function () {
  349. var gl = cc.renderContext;
  350. var director = cc.Director.getInstance();
  351. gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
  352. //restore viewport
  353. director.setViewport();
  354. cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
  355. cc.kmGLPopMatrix();
  356. cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
  357. cc.kmGLPopMatrix();
  358. /* var size = director.getWinSizeInPixels();
  359. // restore viewport
  360. gl.viewport(0, 0, size.width * cc.CONTENT_SCALE_FACTOR(), size.height * cc.CONTENT_SCALE_FACTOR());
  361. // special viewport for 3d projection + retina display
  362. if (director.getProjection() == cc.DIRECTOR_PROJECTION_3D && cc.CONTENT_SCALE_FACTOR() != 1) {
  363. gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.CONTENT_SCALE_FACTOR()), (size.height * cc.CONTENT_SCALE_FACTOR()));
  364. }
  365. director.setProjection(director.getProjection());*/
  366. },
  367. /**
  368. * clears the texture with a color
  369. * @param {Number|cc.Rect} r red 0-1
  370. * @param {Number} g green 0-1
  371. * @param {Number} b blue 0-1
  372. * @param {Number} a alpha 0-1
  373. */
  374. clear:function (r, g, b, a) {
  375. this.beginWithClear(r, g, b, a);
  376. this.end();
  377. },
  378. clearRect:null,
  379. _clearRectForCanvas:function(x, y, width, height){
  380. this._cacheContext.clearRect(x, y, width, -height);
  381. },
  382. _clearRectForWebGL:function(x, y, width, height){
  383. //TODO need to implement
  384. },
  385. /**
  386. * clears the texture with a specified depth value
  387. * @param {Number} depthValue
  388. */
  389. clearDepth:null,
  390. _clearDepthForCanvas:function (depthValue) {
  391. cc.log("clearDepth isn't supported on Cocos2d-Html5");
  392. },
  393. _clearDepthForWebGL:function (depthValue) {
  394. this.begin();
  395. var gl = cc.renderContext;
  396. //! save old depth value
  397. var depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
  398. gl.clearDepth(depthValue);
  399. gl.clear(gl.DEPTH_BUFFER_BIT);
  400. // restore clear color
  401. gl.clearDepth(depthClearValue);
  402. this.end();
  403. },
  404. /**
  405. * clears the texture with a specified stencil value
  406. * @param {Number} stencilValue
  407. */
  408. clearStencil:null,
  409. _clearStencilForCanvas:function (stencilValue) {
  410. cc.log("clearDepth isn't supported on Cocos2d-Html5");
  411. },
  412. _clearStencilForWebGL:function (stencilValue) {
  413. var gl = cc.renderContext;
  414. // save old stencil value
  415. var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
  416. gl.clearStencil(stencilValue);
  417. gl.clear(gl.STENCIL_BUFFER_BIT);
  418. // restore clear color
  419. gl.clearStencil(stencilClearValue);
  420. },
  421. visit:null,
  422. _visitForCanvas:function (ctx) {
  423. // override visit.
  424. // Don't call visit on its children
  425. if (!this._visible)
  426. return;
  427. ctx = ctx || cc.renderContext;
  428. ctx.save();
  429. this.draw(ctx); // update children of RenderTexture before
  430. this.transform(ctx);
  431. this._sprite.visit(); // draw the RenderTexture
  432. ctx.restore();
  433. this._orderOfArrival = 0;
  434. },
  435. _visitForWebGL:function (ctx) {
  436. // override visit.
  437. // Don't call visit on its children
  438. if (!this._visible)
  439. return;
  440. cc.kmGLPushMatrix();
  441. var locGrid = this._grid;
  442. if (locGrid && locGrid.isActive()) {
  443. locGrid.beforeDraw();
  444. this.transformAncestors();
  445. }
  446. this.transform(ctx);
  447. this._sprite.visit();
  448. this.draw(ctx);
  449. if (locGrid && locGrid.isActive())
  450. locGrid.afterDraw(this);
  451. cc.kmGLPopMatrix();
  452. this._orderOfArrival = 0;
  453. },
  454. draw:null,
  455. _drawForCanvas: function (ctx) {
  456. ctx = ctx || cc.renderContext;
  457. if (this._autoDraw) {
  458. this.begin();
  459. if (this._clearFlags) {
  460. var locCanvas = this._cacheCanvas;
  461. ctx.save();
  462. ctx.fillStyle = this._clearColorStr;
  463. ctx.clearRect(0, 0, locCanvas.width, -locCanvas.height);
  464. ctx.fillRect(0, 0, locCanvas.width, -locCanvas.height);
  465. ctx.restore();
  466. }
  467. //! make sure all children are drawn
  468. this.sortAllChildren();
  469. var locChildren = this._children;
  470. var childrenLen = locChildren.length;
  471. var selfSprite = this._sprite;
  472. for (var i = 0; i < childrenLen; i++) {
  473. var getChild = locChildren[i];
  474. if (getChild != selfSprite)
  475. getChild.visit();
  476. }
  477. this.end();
  478. }
  479. },
  480. _drawForWebGL: function (ctx) {
  481. var gl = cc.renderContext;
  482. if (this._autoDraw) {
  483. this.begin();
  484. var locClearFlags = this._clearFlags;
  485. if (locClearFlags) {
  486. var oldClearColor = [0.0, 0.0, 0.0, 0.0];
  487. var oldDepthClearValue = 0.0;
  488. var oldStencilClearValue = 0;
  489. // backup and set
  490. if (locClearFlags & gl.COLOR_BUFFER_BIT) {
  491. oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
  492. gl.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a);
  493. }
  494. if (locClearFlags & gl.DEPTH_BUFFER_BIT) {
  495. oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
  496. gl.clearDepth(this._clearDepth);
  497. }
  498. if (locClearFlags & gl.STENCIL_BUFFER_BIT) {
  499. oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
  500. gl.clearStencil(this._clearStencil);
  501. }
  502. // clear
  503. gl.clear(locClearFlags);
  504. // restore
  505. if (locClearFlags & gl.COLOR_BUFFER_BIT)
  506. gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
  507. if (locClearFlags & gl.DEPTH_BUFFER_BIT)
  508. gl.clearDepth(oldDepthClearValue);
  509. if (locClearFlags & gl.STENCIL_BUFFER_BIT)
  510. gl.clearStencil(oldStencilClearValue);
  511. }
  512. //! make sure all children are drawn
  513. this.sortAllChildren();
  514. var locChildren = this._children;
  515. for (var i = 0; i < locChildren.length; i++) {
  516. var getChild = locChildren[i];
  517. if (getChild != this._sprite)
  518. getChild.visit();
  519. }
  520. this.end();
  521. }
  522. },
  523. /**
  524. * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete.
  525. * @return {cc.Image}
  526. */
  527. newCCImage:null,
  528. _newCCImageForCanvas:function (flipImage) {
  529. cc.log("saveToFile isn't supported on Cocos2d-Html5");
  530. return null;
  531. },
  532. _newCCImageForWebGL:function (flipImage) {
  533. cc.log("saveToFile isn't supported on Cocos2d-Html5");
  534. if(flipImage === null)
  535. flipImage = true;
  536. cc.Assert(this._pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, "only RGBA8888 can be saved as image");
  537. if (!this._texture)
  538. return null;
  539. var size = this._texture.getContentSizeInPixels();
  540. // to get the image size to save
  541. // if the saving image domain exeeds the buffer texture domain,
  542. // it should be cut
  543. var nSavedBufferWidth = size.width;
  544. var nSavedBufferHeight = size.height;
  545. var pImage = new cc.Image();
  546. var gl = cc.renderContext;
  547. var pBuffer = new Uint8Array(nSavedBufferWidth * nSavedBufferHeight * 4);
  548. if (!(pBuffer))
  549. return pImage;
  550. var pTempData = new Uint8Array(nSavedBufferWidth * nSavedBufferHeight * 4);
  551. if (!(pTempData))
  552. return null;
  553. this.begin();
  554. gl.pixelStorei(gl.PACK_ALIGNMENT, 1);
  555. gl.readPixels(0, 0, nSavedBufferWidth, nSavedBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pTempData);
  556. this.end();
  557. // to get the actual texture data
  558. // #640 the image read from rendertexture is upseted
  559. for (var i = 0; i < nSavedBufferHeight; ++i) {
  560. this._memcpy(pBuffer, i * nSavedBufferWidth * 4,
  561. pTempData, (nSavedBufferHeight - i - 1) * nSavedBufferWidth * 4,
  562. nSavedBufferWidth * 4);
  563. }
  564. pImage.initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, cc.FMT_RAWDATA, nSavedBufferWidth, nSavedBufferHeight, 8);
  565. pBuffer = null;
  566. pTempData = null;
  567. return pImage;
  568. },
  569. _memcpy:function (destArr, destIndex, srcArr, srcIndex, size) {
  570. for (var i = 0; i < size; i++) {
  571. destArr[destIndex + i] = srcArr[srcIndex + i];
  572. }
  573. },
  574. /**
  575. * saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
  576. * Returns YES if the operation is successful.
  577. * (doesn't support in HTML5)
  578. * @param {Number} filePath
  579. * @param {Number} format
  580. */
  581. saveToFile:function (filePath, format) {
  582. cc.log("saveToFile isn't supported on Cocos2d-Html5");
  583. },
  584. /**
  585. * Listen "come to background" message, and save render texture. It only has effect on Android.
  586. * @param {cc.Class} obj
  587. */
  588. listenToBackground:function (obj) {
  589. cc.log("listenToBackground isn't supported on Cocos2d-Html5");
  590. },
  591. /**
  592. * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android.
  593. * @param {cc.Class} obj
  594. */
  595. listenToForeground:function (obj) {
  596. cc.log("listenToForeground isn't supported on Cocos2d-Html5");
  597. },
  598. /**
  599. * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES.
  600. * @return {Number}
  601. */
  602. getClearFlags:function () {
  603. return this._clearFlags;
  604. },
  605. setClearFlags:function (clearFlags) {
  606. this._clearFlags = clearFlags;
  607. },
  608. /**
  609. * Clear color value. Valid only when "autoDraw" is true.
  610. * @return {cc.Color4F}
  611. */
  612. getClearColor:function () {
  613. return this._clearColor;
  614. },
  615. setClearColor:null,
  616. _setClearColorForCanvas:function (clearColor) {
  617. var locClearColor = this._clearColor;
  618. locClearColor.r = clearColor.r;
  619. locClearColor.g = clearColor.g;
  620. locClearColor.b = clearColor.b;
  621. locClearColor.a = clearColor.a;
  622. this._clearColorStr = "rgba(" + (0 | (clearColor.r * 255)) + "," + (0 | (clearColor.g * 255)) + "," + (0 | (clearColor.b * 255)) + "," + clearColor.a + ")";
  623. },
  624. _setClearColorForWebGL:function (clearColor) {
  625. var locClearColor = this._clearColor;
  626. locClearColor.r = clearColor.r;
  627. locClearColor.g = clearColor.g;
  628. locClearColor.b = clearColor.b;
  629. locClearColor.a = clearColor.a;
  630. },
  631. /**
  632. * Value for clearDepth. Valid only when autoDraw is true.
  633. * @return {Number}
  634. */
  635. getClearDepth:function () {
  636. return this._clearDepth;
  637. },
  638. setClearDepth:function (clearDepth) {
  639. this._clearDepth = clearDepth;
  640. },
  641. /**
  642. * Value for clear Stencil. Valid only when autoDraw is true
  643. * @return {Number}
  644. */
  645. getClearStencil:function () {
  646. return this._clearStencil;
  647. },
  648. setClearStencil:function (clearStencil) {
  649. this._clearStencil = clearStencil;
  650. },
  651. /**
  652. * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons. <br/>
  653. * Will be enabled in the future.
  654. * @return {Boolean}
  655. */
  656. isAutoDraw:function () {
  657. return this._autoDraw;
  658. },
  659. setAutoDraw:function (autoDraw) {
  660. this._autoDraw = autoDraw;
  661. }
  662. });
  663. if(cc.Browser.supportWebGL){
  664. cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForWebGL;
  665. cc.RenderTexture.prototype.cleanup = cc.RenderTexture.prototype._cleanupForWebGL;
  666. cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForWebGL;
  667. cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForWebGL;
  668. cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForWebGL;
  669. cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForWebGL;
  670. cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForWebGL;
  671. cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForWebGL;
  672. cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForWebGL;
  673. cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForWebGL;
  674. cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForWebGL;
  675. cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForWebGL;
  676. cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForWebGL;
  677. } else {
  678. cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForCanvas;
  679. cc.RenderTexture.prototype.cleanup = cc.RenderTexture.prototype._cleanupForCanvas;
  680. cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForCanvas;
  681. cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForCanvas;
  682. cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForCanvas;
  683. cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForCanvas;
  684. cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForCanvas;
  685. cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForCanvas;
  686. cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForCanvas;
  687. cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForCanvas;
  688. cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForCanvas;
  689. cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForCanvas;
  690. cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForCanvas;
  691. }
  692. /**
  693. * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
  694. * @param {Number} width
  695. * @param {Number} height
  696. * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
  697. * @param {Number} depthStencilFormat
  698. * @return {cc.RenderTexture}
  699. * @example
  700. * // Example
  701. * var rt = cc.RenderTexture.create()
  702. */
  703. cc.RenderTexture.create = function (width, height, format, depthStencilFormat) {
  704. format = format || cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888;
  705. depthStencilFormat = depthStencilFormat || 0;
  706. var ret = new cc.RenderTexture();
  707. if (ret && ret.initWithWidthAndHeight(width, height, format, depthStencilFormat))
  708. return ret;
  709. return null;
  710. };