Source: core/renderers/webgl/utils/RenderTarget.js

core/renderers/webgl/utils/RenderTarget.js

  1. import { Rectangle, Matrix } from '../../../math';
  2. import { SCALE_MODES } from '../../../const';
  3. import settings from '../../../settings';
  4. // 修改依赖库应对小程序环境
  5. import { GLFramebuffer } from '../../../../dependencies/pixi-gl-core/';
  6. // import { GLFramebuffer } from 'pixi-gl-core';
  7. /**
  8. * @class
  9. * @memberof PIXI
  10. */
  11. export default class RenderTarget
  12. {
  13. /**
  14. * @param {WebGLRenderingContext} gl - The current WebGL drawing context
  15. * @param {number} [width=0] - the horizontal range of the filter
  16. * @param {number} [height=0] - the vertical range of the filter
  17. * @param {number} [scaleMode=PIXI.settings.SCALE_MODE] - See {@link PIXI.SCALE_MODES} for possible values
  18. * @param {number} [resolution=1] - The current resolution / device pixel ratio
  19. * @param {boolean} [root=false] - Whether this object is the root element or not
  20. */
  21. constructor(gl, width, height, scaleMode, resolution, root)
  22. {
  23. // TODO Resolution could go here ( eg low res blurs )
  24. /**
  25. * The current WebGL drawing context.
  26. *
  27. * @member {WebGLRenderingContext}
  28. */
  29. this.gl = gl;
  30. // next time to create a frame buffer and texture
  31. /**
  32. * A frame buffer
  33. *
  34. * @member {PIXI.glCore.GLFramebuffer}
  35. */
  36. this.frameBuffer = null;
  37. /**
  38. * The texture
  39. *
  40. * @member {PIXI.glCore.GLTexture}
  41. */
  42. this.texture = null;
  43. /**
  44. * The background colour of this render target, as an array of [r,g,b,a] values
  45. *
  46. * @member {number[]}
  47. */
  48. this.clearColor = [0, 0, 0, 0];
  49. /**
  50. * The size of the object as a rectangle
  51. *
  52. * @member {PIXI.Rectangle}
  53. */
  54. this.size = new Rectangle(0, 0, 1, 1);
  55. /**
  56. * The current resolution / device pixel ratio
  57. *
  58. * @member {number}
  59. * @default 1
  60. */
  61. this.resolution = resolution || settings.RESOLUTION;
  62. /**
  63. * The projection matrix
  64. *
  65. * @member {PIXI.Matrix}
  66. */
  67. this.projectionMatrix = new Matrix();
  68. /**
  69. * The object's transform
  70. *
  71. * @member {PIXI.Matrix}
  72. */
  73. this.transform = null;
  74. /**
  75. * The frame.
  76. *
  77. * @member {PIXI.Rectangle}
  78. */
  79. this.frame = null;
  80. /**
  81. * The stencil buffer stores masking data for the render target
  82. *
  83. * @member {glCore.GLBuffer}
  84. */
  85. this.defaultFrame = new Rectangle();
  86. this.destinationFrame = null;
  87. this.sourceFrame = null;
  88. /**
  89. * The stencil buffer stores masking data for the render target
  90. *
  91. * @member {glCore.GLBuffer}
  92. */
  93. this.stencilBuffer = null;
  94. /**
  95. * The data structure for the stencil masks
  96. *
  97. * @member {PIXI.Graphics[]}
  98. */
  99. this.stencilMaskStack = [];
  100. /**
  101. * Stores filter data for the render target
  102. *
  103. * @member {object[]}
  104. */
  105. this.filterData = null;
  106. /**
  107. * The key for pooled texture of FilterSystem
  108. * @private
  109. * @member {string}
  110. */
  111. this.filterPoolKey = '';
  112. /**
  113. * The scale mode.
  114. *
  115. * @member {number}
  116. * @default PIXI.settings.SCALE_MODE
  117. * @see PIXI.SCALE_MODES
  118. */
  119. this.scaleMode = scaleMode !== undefined ? scaleMode : settings.SCALE_MODE;
  120. /**
  121. * Whether this object is the root element or not
  122. *
  123. * @member {boolean}
  124. * @default false
  125. */
  126. this.root = root || false;
  127. if (!this.root)
  128. {
  129. this.frameBuffer = GLFramebuffer.createRGBA(gl, 100, 100);
  130. if (this.scaleMode === SCALE_MODES.NEAREST)
  131. {
  132. this.frameBuffer.texture.enableNearestScaling();
  133. }
  134. else
  135. {
  136. this.frameBuffer.texture.enableLinearScaling();
  137. }
  138. /*
  139. A frame buffer needs a target to render to..
  140. create a texture and bind it attach it to the framebuffer..
  141. */
  142. // this is used by the base texture
  143. this.texture = this.frameBuffer.texture;
  144. }
  145. else
  146. {
  147. // make it a null framebuffer..
  148. this.frameBuffer = new GLFramebuffer(gl, 100, 100);
  149. this.frameBuffer.framebuffer = null;
  150. }
  151. this.setFrame();
  152. this.resize(width, height);
  153. }
  154. /**
  155. * Clears the filter texture.
  156. *
  157. * @param {number[]} [clearColor=this.clearColor] - Array of [r,g,b,a] to clear the framebuffer
  158. */
  159. clear(clearColor)
  160. {
  161. const cc = clearColor || this.clearColor;
  162. this.frameBuffer.clear(cc[0], cc[1], cc[2], cc[3]);// r,g,b,a);
  163. }
  164. /**
  165. * Binds the stencil buffer.
  166. *
  167. */
  168. attachStencilBuffer()
  169. {
  170. // TODO check if stencil is done?
  171. /**
  172. * The stencil buffer is used for masking in pixi
  173. * lets create one and then add attach it to the framebuffer..
  174. */
  175. if (!this.root)
  176. {
  177. this.frameBuffer.enableStencil();
  178. }
  179. }
  180. /**
  181. * Sets the frame of the render target.
  182. *
  183. * @param {Rectangle} destinationFrame - The destination frame.
  184. * @param {Rectangle} sourceFrame - The source frame.
  185. */
  186. setFrame(destinationFrame, sourceFrame)
  187. {
  188. this.destinationFrame = destinationFrame || this.destinationFrame || this.defaultFrame;
  189. this.sourceFrame = sourceFrame || this.sourceFrame || this.destinationFrame;
  190. }
  191. /**
  192. * Binds the buffers and initialises the viewport.
  193. *
  194. */
  195. activate()
  196. {
  197. // TODO refactor usage of frame..
  198. const gl = this.gl;
  199. // make sure the texture is unbound!
  200. this.frameBuffer.bind();
  201. this.calculateProjection(this.destinationFrame, this.sourceFrame);
  202. if (this.transform)
  203. {
  204. this.projectionMatrix.append(this.transform);
  205. }
  206. // TODO add a check as them may be the same!
  207. if (this.destinationFrame !== this.sourceFrame)
  208. {
  209. gl.enable(gl.SCISSOR_TEST);
  210. gl.scissor(
  211. this.destinationFrame.x | 0,
  212. this.destinationFrame.y | 0,
  213. (this.destinationFrame.width * this.resolution) | 0,
  214. (this.destinationFrame.height * this.resolution) | 0
  215. );
  216. }
  217. else
  218. {
  219. gl.disable(gl.SCISSOR_TEST);
  220. }
  221. // TODO - does not need to be updated all the time??
  222. gl.viewport(
  223. this.destinationFrame.x | 0,
  224. this.destinationFrame.y | 0,
  225. (this.destinationFrame.width * this.resolution) | 0,
  226. (this.destinationFrame.height * this.resolution) | 0
  227. );
  228. }
  229. /**
  230. * Updates the projection matrix based on a projection frame (which is a rectangle)
  231. *
  232. * @param {Rectangle} destinationFrame - The destination frame.
  233. * @param {Rectangle} sourceFrame - The source frame.
  234. */
  235. calculateProjection(destinationFrame, sourceFrame)
  236. {
  237. const pm = this.projectionMatrix;
  238. sourceFrame = sourceFrame || destinationFrame;
  239. pm.identity();
  240. // TODO: make dest scale source
  241. if (!this.root)
  242. {
  243. pm.a = 1 / destinationFrame.width * 2;
  244. pm.d = 1 / destinationFrame.height * 2;
  245. pm.tx = -1 - (sourceFrame.x * pm.a);
  246. pm.ty = -1 - (sourceFrame.y * pm.d);
  247. }
  248. else
  249. {
  250. pm.a = 1 / destinationFrame.width * 2;
  251. pm.d = -1 / destinationFrame.height * 2;
  252. pm.tx = -1 - (sourceFrame.x * pm.a);
  253. pm.ty = 1 - (sourceFrame.y * pm.d);
  254. }
  255. }
  256. /**
  257. * Resizes the texture to the specified width and height
  258. *
  259. * @param {number} width - the new width of the texture
  260. * @param {number} height - the new height of the texture
  261. */
  262. resize(width, height)
  263. {
  264. width = width | 0;
  265. height = height | 0;
  266. if (this.size.width === width && this.size.height === height)
  267. {
  268. return;
  269. }
  270. this.size.width = width;
  271. this.size.height = height;
  272. this.defaultFrame.width = width;
  273. this.defaultFrame.height = height;
  274. this.frameBuffer.resize(width * this.resolution, height * this.resolution);
  275. const projectionFrame = this.frame || this.size;
  276. this.calculateProjection(projectionFrame);
  277. }
  278. /**
  279. * Destroys the render target.
  280. *
  281. */
  282. destroy()
  283. {
  284. if (this.frameBuffer.stencil)
  285. {
  286. this.gl.deleteRenderbuffer(this.frameBuffer.stencil);
  287. }
  288. this.frameBuffer.destroy();
  289. this.frameBuffer = null;
  290. this.texture = null;
  291. }
  292. }