RenderTarget.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. import { EventDispatcher } from './EventDispatcher.js';
  2. import { Texture } from '../textures/Texture.js';
  3. import { LinearFilter } from '../constants.js';
  4. import { Vector4 } from '../math/Vector4.js';
  5. import { Source } from '../textures/Source.js';
  6. /**
  7. * A render target is a buffer where the video card draws pixels for a scene
  8. * that is being rendered in the background. It is used in different effects,
  9. * such as applying postprocessing to a rendered image before displaying it
  10. * on the screen.
  11. *
  12. * @augments EventDispatcher
  13. */
  14. class RenderTarget extends EventDispatcher {
  15. /**
  16. * Render target options.
  17. *
  18. * @typedef {Object} RenderTarget~Options
  19. * @property {boolean} [generateMipmaps=false] - Whether to generate mipmaps or not.
  20. * @property {number} [magFilter=LinearFilter] - The mag filter.
  21. * @property {number} [minFilter=LinearFilter] - The min filter.
  22. * @property {number} [format=RGBAFormat] - The texture format.
  23. * @property {number} [type=UnsignedByteType] - The texture type.
  24. * @property {?string} [internalFormat=null] - The texture's internal format.
  25. * @property {number} [wrapS=ClampToEdgeWrapping] - The texture's uv wrapping mode.
  26. * @property {number} [wrapT=ClampToEdgeWrapping] - The texture's uv wrapping mode.
  27. * @property {number} [anisotropy=1] - The texture's anisotropy value.
  28. * @property {string} [colorSpace=NoColorSpace] - The texture's color space.
  29. * @property {boolean} [depthBuffer=true] - Whether to allocate a depth buffer or not.
  30. * @property {boolean} [stencilBuffer=false] - Whether to allocate a stencil buffer or not.
  31. * @property {boolean} [resolveDepthBuffer=true] - Whether to resolve the depth buffer or not.
  32. * @property {boolean} [resolveStencilBuffer=true] - Whether to resolve the stencil buffer or not.
  33. * @property {?Texture} [depthTexture=null] - Reference to a depth texture.
  34. * @property {number} [samples=0] - The MSAA samples count.
  35. * @property {number} [count=1] - Defines the number of color attachments . Must be at least `1`.
  36. * @property {number} [depth=1] - The texture depth.
  37. * @property {boolean} [multiview=false] - Whether this target is used for multiview rendering.
  38. */
  39. /**
  40. * Constructs a new render target.
  41. *
  42. * @param {number} [width=1] - The width of the render target.
  43. * @param {number} [height=1] - The height of the render target.
  44. * @param {RenderTarget~Options} [options] - The configuration object.
  45. */
  46. constructor( width = 1, height = 1, options = {} ) {
  47. super();
  48. options = Object.assign( {
  49. generateMipmaps: false,
  50. internalFormat: null,
  51. minFilter: LinearFilter,
  52. depthBuffer: true,
  53. stencilBuffer: false,
  54. resolveDepthBuffer: true,
  55. resolveStencilBuffer: true,
  56. depthTexture: null,
  57. samples: 0,
  58. count: 1,
  59. depth: 1,
  60. multiview: false
  61. }, options );
  62. /**
  63. * This flag can be used for type testing.
  64. *
  65. * @type {boolean}
  66. * @readonly
  67. * @default true
  68. */
  69. this.isRenderTarget = true;
  70. /**
  71. * The width of the render target.
  72. *
  73. * @type {number}
  74. * @default 1
  75. */
  76. this.width = width;
  77. /**
  78. * The height of the render target.
  79. *
  80. * @type {number}
  81. * @default 1
  82. */
  83. this.height = height;
  84. /**
  85. * The depth of the render target.
  86. *
  87. * @type {number}
  88. * @default 1
  89. */
  90. this.depth = options.depth;
  91. /**
  92. * A rectangular area inside the render target's viewport. Fragments that are
  93. * outside the area will be discarded.
  94. *
  95. * @type {Vector4}
  96. * @default (0,0,width,height)
  97. */
  98. this.scissor = new Vector4( 0, 0, width, height );
  99. /**
  100. * Indicates whether the scissor test should be enabled when rendering into
  101. * this render target or not.
  102. *
  103. * @type {boolean}
  104. * @default false
  105. */
  106. this.scissorTest = false;
  107. /**
  108. * A rectangular area representing the render target's viewport.
  109. *
  110. * @type {Vector4}
  111. * @default (0,0,width,height)
  112. */
  113. this.viewport = new Vector4( 0, 0, width, height );
  114. const image = { width: width, height: height, depth: options.depth };
  115. const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
  116. texture.flipY = false;
  117. texture.generateMipmaps = options.generateMipmaps;
  118. texture.internalFormat = options.internalFormat;
  119. /**
  120. * An array of textures. Each color attachment is represented as a separate texture.
  121. * Has at least a single entry for the default color attachment.
  122. *
  123. * @type {Array<Texture>}
  124. */
  125. this.textures = [];
  126. const count = options.count;
  127. for ( let i = 0; i < count; i ++ ) {
  128. this.textures[ i ] = texture.clone();
  129. this.textures[ i ].isRenderTargetTexture = true;
  130. this.textures[ i ].renderTarget = this;
  131. }
  132. /**
  133. * Whether to allocate a depth buffer or not.
  134. *
  135. * @type {boolean}
  136. * @default true
  137. */
  138. this.depthBuffer = options.depthBuffer;
  139. /**
  140. * Whether to allocate a stencil buffer or not.
  141. *
  142. * @type {boolean}
  143. * @default false
  144. */
  145. this.stencilBuffer = options.stencilBuffer;
  146. /**
  147. * Whether to resolve the depth buffer or not.
  148. *
  149. * @type {boolean}
  150. * @default true
  151. */
  152. this.resolveDepthBuffer = options.resolveDepthBuffer;
  153. /**
  154. * Whether to resolve the stencil buffer or not.
  155. *
  156. * @type {boolean}
  157. * @default true
  158. */
  159. this.resolveStencilBuffer = options.resolveStencilBuffer;
  160. this._depthTexture = null;
  161. this.depthTexture = options.depthTexture;
  162. /**
  163. * The number of MSAA samples.
  164. *
  165. * A value of `0` disables MSAA.
  166. *
  167. * @type {number}
  168. * @default 0
  169. */
  170. this.samples = options.samples;
  171. /**
  172. * Whether to this target is used in multiview rendering.
  173. *
  174. * @type {boolean}
  175. * @default false
  176. */
  177. this.multiview = options.multiview;
  178. }
  179. /**
  180. * The texture representing the default color attachment.
  181. *
  182. * @type {Texture}
  183. */
  184. get texture() {
  185. return this.textures[ 0 ];
  186. }
  187. set texture( value ) {
  188. this.textures[ 0 ] = value;
  189. }
  190. set depthTexture( current ) {
  191. if ( this._depthTexture !== null ) this._depthTexture.renderTarget = null;
  192. if ( current !== null ) current.renderTarget = this;
  193. this._depthTexture = current;
  194. }
  195. /**
  196. * Instead of saving the depth in a renderbuffer, a texture
  197. * can be used instead which is useful for further processing
  198. * e.g. in context of post-processing.
  199. *
  200. * @type {?DepthTexture}
  201. * @default null
  202. */
  203. get depthTexture() {
  204. return this._depthTexture;
  205. }
  206. /**
  207. * Sets the size of this render target.
  208. *
  209. * @param {number} width - The width.
  210. * @param {number} height - The height.
  211. * @param {number} [depth=1] - The depth.
  212. */
  213. setSize( width, height, depth = 1 ) {
  214. if ( this.width !== width || this.height !== height || this.depth !== depth ) {
  215. this.width = width;
  216. this.height = height;
  217. this.depth = depth;
  218. for ( let i = 0, il = this.textures.length; i < il; i ++ ) {
  219. this.textures[ i ].image.width = width;
  220. this.textures[ i ].image.height = height;
  221. this.textures[ i ].image.depth = depth;
  222. if ( this.textures[ i ].image.depth > 1 ) {
  223. this.textures[ i ].isArrayTexture = true;
  224. }
  225. }
  226. this.dispose();
  227. }
  228. this.viewport.set( 0, 0, width, height );
  229. this.scissor.set( 0, 0, width, height );
  230. }
  231. /**
  232. * Returns a new render target with copied values from this instance.
  233. *
  234. * @return {RenderTarget} A clone of this instance.
  235. */
  236. clone() {
  237. return new this.constructor().copy( this );
  238. }
  239. /**
  240. * Copies the settings of the given render target. This is a structural copy so
  241. * no resources are shared between render targets after the copy. That includes
  242. * all MRT textures and the depth texture.
  243. *
  244. * @param {RenderTarget} source - The render target to copy.
  245. * @return {RenderTarget} A reference to this instance.
  246. */
  247. copy( source ) {
  248. this.width = source.width;
  249. this.height = source.height;
  250. this.depth = source.depth;
  251. this.scissor.copy( source.scissor );
  252. this.scissorTest = source.scissorTest;
  253. this.viewport.copy( source.viewport );
  254. this.textures.length = 0;
  255. for ( let i = 0, il = source.textures.length; i < il; i ++ ) {
  256. this.textures[ i ] = source.textures[ i ].clone();
  257. this.textures[ i ].isRenderTargetTexture = true;
  258. this.textures[ i ].renderTarget = this;
  259. // ensure image object is not shared, see #20328
  260. const image = Object.assign( {}, source.textures[ i ].image );
  261. this.textures[ i ].source = new Source( image );
  262. }
  263. this.depthBuffer = source.depthBuffer;
  264. this.stencilBuffer = source.stencilBuffer;
  265. this.resolveDepthBuffer = source.resolveDepthBuffer;
  266. this.resolveStencilBuffer = source.resolveStencilBuffer;
  267. if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
  268. this.samples = source.samples;
  269. return this;
  270. }
  271. /**
  272. * Frees the GPU-related resources allocated by this instance. Call this
  273. * method whenever this instance is no longer used in your app.
  274. *
  275. * @fires RenderTarget#dispose
  276. */
  277. dispose() {
  278. this.dispatchEvent( { type: 'dispose' } );
  279. }
  280. }
  281. export { RenderTarget };
粤ICP备19079148号