@@ -300,12 +300,135 @@ var Shader = new Class({
300300 */
301301 this . _textureCount = 0 ;
302302
303+ /**
304+ * A reference to the GL Frame Buffer this Shader is drawing to.
305+ * This property is only set if you have called `Shader.setRenderToTexture`.
306+ *
307+ * @name Phaser.GameObjects.Shader#framebuffer
308+ * @type {?WebGLFramebuffer }
309+ * @since 3.19.0
310+ */
311+ this . framebuffer = null ;
312+
313+ /**
314+ * A reference to the WebGLTexture this Shader is rendering to.
315+ * This property is only set if you have called `Shader.setRenderToTexture`.
316+ *
317+ * @name Phaser.GameObjects.Shader#glTexture
318+ * @type {?WebGLTexture }
319+ * @since 3.19.0
320+ */
321+ this . glTexture = null ;
322+
323+ /**
324+ * A flag that indicates if this Shader has been set to render to a texture instead of the display list.
325+ *
326+ * This property is `true` if you have called `Shader.setRenderToTexture`, otherwise it's `false`.
327+ *
328+ * A Shader that is rendering to a texture _does not_ appear on the display list.
329+ *
330+ * @name Phaser.GameObjects.Shader#renderToTexture
331+ * @type {boolean }
332+ * @readonly
333+ * @since 3.19.0
334+ */
335+ this . renderToTexture = false ;
336+
337+ /**
338+ * A reference to the Phaser.Textures.Texture that has been stored in the Texture Manager for this Shader.
339+ *
340+ * This property is only set if you have called `Shader.setRenderToTexture`, otherwise it is `null`.
341+ *
342+ * @name Phaser.GameObjects.Shader#texture
343+ * @type {Phaser.Textures.Texture }
344+ * @since 3.19.0
345+ */
346+ this . texture = null ;
347+
348+ /**
349+ * Internal saved texture key.
350+ *
351+ * @name Phaser.GameObjects.Shader#_savedKey
352+ * @type {boolean }
353+ * @private
354+ * @since 3.19.0
355+ */
356+ this . _savedKey = '' ;
357+
303358 this . setPosition ( x , y ) ;
304359 this . setSize ( width , height ) ;
305360 this . setOrigin ( 0.5 , 0.5 ) ;
306361 this . setShader ( key , textures ) ;
307362 } ,
308363
364+ /**
365+ * Changes this Shader so instead of rendering to the display list it renders to a
366+ * WebGL Framebuffer and WebGL Texture instead. This allows you to use the output
367+ * of this shader as an input for another shader, by mapping a sampler2D uniform
368+ * to it.
369+ *
370+ * After calling this method the `Shader.framebuffer` and `Shader.glTexture` properties
371+ * are populated.
372+ *
373+ * Additionally, you can provide a key to this method. Doing so will create a Phaser Texture
374+ * from this Shader and save it into the Texture Manager, allowing you to then use it for
375+ * any texture-based Game Object, such as a Sprite or Image:
376+ *
377+ * ```javascript
378+ * var shader = this.add.shader('myShader', x, y, width, height);
379+ *
380+ * shader.setRenderToTexture('doodle');
381+ *
382+ * this.add.image(400, 300, 'doodle');
383+ * ```
384+ *
385+ * Note that it stores an active reference to this Shader. That means as this shader updates,
386+ * so does the texture and any object using it to render with. Also, if you destroy this
387+ * shader, be sure to clear any objects that may have been using it as a texture too.
388+ *
389+ * You can access the Phaser Texture that is created via the `Shader.texture` property.
390+ *
391+ * By default it will create a single base texture. You can add frames to the texture
392+ * by using the `Texture.add` method. After doing this, you can then allow Game Objects
393+ * to use a specific frame from a Render Texture.
394+ *
395+ * @method Phaser.GameObjects.Shader#setRenderToTexture
396+ * @since 3.19.0
397+ *
398+ * @param {string } [key] - The unique key to store the texture as within the global Texture Manager.
399+ *
400+ * @return {this } This Shader instance.
401+ */
402+ setRenderToTexture : function ( key )
403+ {
404+ if ( ! this . renderToTexture )
405+ {
406+ var width = this . width ;
407+ var height = this . height ;
408+ var renderer = this . renderer ;
409+
410+ this . glTexture = renderer . createTextureFromSource ( null , width , height , 0 ) ;
411+
412+ this . framebuffer = renderer . createFramebuffer ( width , height , this . glTexture , false ) ;
413+
414+ this . _rendererWidth = width ;
415+ this . _rendererHeight = height ;
416+
417+ this . renderToTexture = true ;
418+
419+ this . projOrtho ( 0 , this . width , this . height , 0 ) ;
420+
421+ if ( key )
422+ {
423+ this . _savedKey = key ;
424+
425+ this . texture = this . scene . sys . textures . addGLTexture ( key , this . glTexture , width , height ) ;
426+ }
427+ }
428+
429+ return this ;
430+ } ,
431+
309432 /**
310433 * Sets the fragment and, optionally, the vertex shader source code that this Shader will use.
311434 * This will immediately delete the active shader program, if set, and then create a new one
@@ -391,7 +514,7 @@ var Shader = new Class({
391514
392515 this . initUniforms ( ) ;
393516
394- this . projOrtho ( 0 , renderer . width , renderer . height , 0 ) ;
517+ this . projOrtho ( 0 , this . _rendererWidth , this . _rendererHeight , 0 ) ;
395518
396519 return this ;
397520 } ,
@@ -809,7 +932,7 @@ var Shader = new Class({
809932 * @method Phaser.GameObjects.Shader#load
810933 * @since 3.17.0
811934 *
812- * @param {Phaser.GameObjects.Components.TransformMatrix } matrix2D - The transform matrix to use during rendering.
935+ * @param {Phaser.GameObjects.Components.TransformMatrix } [ matrix2D] - The transform matrix to use during rendering.
813936 */
814937 load : function ( matrix2D )
815938 {
@@ -820,19 +943,22 @@ var Shader = new Class({
820943 var renderer = this . renderer ;
821944 var program = this . program ;
822945
823- var x = - this . _displayOriginX ;
824- var y = - this . _displayOriginY ;
825-
826- var vm = this . viewMatrix ;
827-
828- vm [ 0 ] = matrix2D [ 0 ] ;
829- vm [ 1 ] = matrix2D [ 1 ] ;
830- vm [ 4 ] = matrix2D [ 2 ] ;
831- vm [ 5 ] = matrix2D [ 3 ] ;
832- vm [ 8 ] = matrix2D [ 4 ] ;
833- vm [ 9 ] = matrix2D [ 5 ] ;
834- vm [ 12 ] = vm [ 0 ] * x + vm [ 4 ] * y ;
835- vm [ 13 ] = vm [ 1 ] * x + vm [ 5 ] * y ;
946+ if ( ! this . renderToTexture )
947+ {
948+ var x = - this . _displayOriginX ;
949+ var y = - this . _displayOriginY ;
950+
951+ var vm = this . viewMatrix ;
952+
953+ vm [ 0 ] = matrix2D [ 0 ] ;
954+ vm [ 1 ] = matrix2D [ 1 ] ;
955+ vm [ 4 ] = matrix2D [ 2 ] ;
956+ vm [ 5 ] = matrix2D [ 3 ] ;
957+ vm [ 8 ] = matrix2D [ 4 ] ;
958+ vm [ 9 ] = matrix2D [ 5 ] ;
959+ vm [ 12 ] = vm [ 0 ] * x + vm [ 4 ] * y ;
960+ vm [ 13 ] = vm [ 1 ] * x + vm [ 5 ] * y ;
961+ }
836962
837963 // Update vertex shader uniforms
838964
@@ -886,6 +1012,11 @@ var Shader = new Class({
8861012 var renderer = this . renderer ;
8871013 var vertexSize = Float32Array . BYTES_PER_ELEMENT * 2 ;
8881014
1015+ if ( this . renderToTexture )
1016+ {
1017+ renderer . setFramebuffer ( this . framebuffer ) ;
1018+ }
1019+
8891020 renderer . setProgram ( program ) ;
8901021 renderer . setVertexBuffer ( vertexBuffer ) ;
8911022
@@ -916,6 +1047,11 @@ var Shader = new Class({
9161047 gl . bufferSubData ( gl . ARRAY_BUFFER , 0 , this . bytes . subarray ( 0 , vertexCount * vertexSize ) ) ;
9171048
9181049 gl . drawArrays ( gl . TRIANGLES , 0 , vertexCount ) ;
1050+
1051+ if ( this . renderToTexture )
1052+ {
1053+ renderer . setFramebuffer ( null , false ) ;
1054+ }
9191055 } ,
9201056
9211057 /**
@@ -955,6 +1091,17 @@ var Shader = new Class({
9551091
9561092 gl . deleteProgram ( this . program ) ;
9571093 gl . deleteBuffer ( this . vertexBuffer ) ;
1094+
1095+ if ( this . renderToTexture )
1096+ {
1097+ this . renderer . deleteFramebuffer ( this . framebuffer ) ;
1098+
1099+ this . texture . destroy ( ) ;
1100+
1101+ this . framebuffer = null ;
1102+ this . glTexture = null ;
1103+ this . texture = null ;
1104+ }
9581105 }
9591106
9601107} ) ;
0 commit comments