Skip to content

Commit 22b107b

Browse files
committed
Added setRenderToTexture method and supporting properties
1 parent 9a6fe49 commit 22b107b

1 file changed

Lines changed: 162 additions & 15 deletions

File tree

src/gameobjects/shader/Shader.js

Lines changed: 162 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)