Skip to content

Commit ba280c7

Browse files
committed
BitmapMask and GeometryMask are rendering correctly
1 parent 77e0422 commit ba280c7

7 files changed

Lines changed: 186 additions & 119 deletions

File tree

src/display/mask/BitmapMask.js

Lines changed: 26 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -15,135 +15,51 @@ var BitmapMask = new Class({
1515
this.mainTexture = null;
1616
this.dirty = true;
1717

18-
if (resourceManager !== undefined)
18+
if (renderer.gl)
1919
{
2020
var width = renderer.width;
2121
var height = renderer.height;
2222
var pot = ((width & (width - 1)) == 0 && (height & (height - 1)) == 0);
2323
var gl = renderer.gl;
2424
var wrap = pot ? gl.REPEAT : gl.CLAMP_TO_EDGE;
25+
var filter = gl.LINEAR;
26+
27+
this.mainTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
28+
this.maskTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
29+
this.mainFramebuffer = renderer.createFramebuffer(width, height, this.mainTexture, false);
30+
this.maskFramebuffer = renderer.createFramebuffer(width, height, this.maskTexture, false);
31+
32+
renderer.onContextRestored(function (renderer) {
33+
var width = renderer.width;
34+
var height = renderer.height;
35+
var pot = ((width & (width - 1)) == 0 && (height & (height - 1)) == 0);
36+
var gl = renderer.gl;
37+
var wrap = pot ? gl.REPEAT : gl.CLAMP_TO_EDGE;
38+
var filter = gl.LINEAR;
39+
40+
this.mainTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
41+
this.maskTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
42+
this.mainFramebuffer = renderer.createFramebuffer(width, height, this.mainTexture, false);
43+
this.maskFramebuffer = renderer.createFramebuffer(width, height, this.maskTexture, false);
44+
45+
}, this);
2546

26-
this.maskTexture = resourceManager.createTexture(
27-
0,
28-
gl.LINEAR, gl.LINEAR,
29-
wrap, wrap,
30-
gl.RGBA,
31-
null, width, height
32-
);
33-
34-
this.mainTexture = resourceManager.createTexture(
35-
0,
36-
gl.LINEAR, gl.LINEAR,
37-
wrap, wrap,
38-
gl.RGBA,
39-
null, width, height
40-
);
41-
42-
this.maskRenderTarget = resourceManager.createRenderTarget(
43-
width, height,
44-
this.maskTexture,
45-
null
46-
);
47-
this.mainRenderTarget = resourceManager.createRenderTarget(
48-
width, height,
49-
this.mainTexture,
50-
null
51-
);
52-
53-
scene.sys.game.renderer.currentTexture[0] = null;
5447
}
55-
56-
var _this = this;
57-
58-
renderer.addContextRestoredCallback(function (renderer) {
59-
var resourceManager = renderer.resourceManager;
60-
var gl = renderer.gl;
61-
var wrap = pot ? gl.REPEAT : gl.CLAMP_TO_EDGE;
62-
63-
_this.maskTexture = resourceManager.createTexture(
64-
0,
65-
gl.LINEAR, gl.LINEAR,
66-
wrap, wrap,
67-
gl.RGBA,
68-
null, width, height
69-
);
70-
_this.mainTexture = resourceManager.createTexture(
71-
0,
72-
gl.LINEAR, gl.LINEAR,
73-
wrap, wrap,
74-
gl.RGBA,
75-
null, width, height
76-
);
77-
78-
_this.maskRenderTarget = resourceManager.createRenderTarget(
79-
width, height,
80-
_this.maskTexture,
81-
null
82-
);
83-
_this.mainRenderTarget = resourceManager.createRenderTarget(
84-
width, height,
85-
_this.mainTexture,
86-
null
87-
);
88-
89-
// force rebinding of prev texture
90-
scene.sys.game.renderer.currentTexture[0] = null;
91-
});
9248
},
9349

9450
setBitmap: function (renderable)
9551
{
9652
this.bitmapMask = renderable;
9753
},
9854

99-
preRenderWebGL: function (renderer, gameObject, camera)
55+
preRenderWebGL: function (renderer, maskedObject, camera)
10056
{
101-
var bitmapMask = this.bitmapMask;
102-
var maskRenderTarget = this.maskRenderTarget;
103-
var mainRenderTarget = this.mainRenderTarget;
104-
var prevRenderTarget = null;
105-
var visible = bitmapMask.visible;
106-
107-
if (bitmapMask)
108-
{
109-
/* Clear render targets first */
110-
var gl = renderer.gl;
111-
112-
gl.clearColor(0.0, 0.0, 0.0, 0.0);
113-
gl.bindFramebuffer(gl.FRAMEBUFFER, maskRenderTarget.framebufferObject);
114-
gl.clear(gl.COLOR_BUFFER_BIT);
115-
gl.bindFramebuffer(gl.FRAMEBUFFER, mainRenderTarget.framebufferObject);
116-
gl.clear(gl.COLOR_BUFFER_BIT);
117-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
118-
119-
// Inject mask render target & reset it after rendering.
120-
prevRenderTarget = bitmapMask.renderTarget;
121-
bitmapMask.renderTarget = maskRenderTarget;
122-
bitmapMask.visible = true;
123-
bitmapMask.renderWebGL(renderer, bitmapMask, 0.0, camera);
124-
renderer.currentRenderer.flush(null, maskRenderTarget);
125-
bitmapMask.renderTarget = prevRenderTarget;
126-
bitmapMask.visible = visible;
127-
128-
// Inject main render target & reset it at post rendering.
129-
gameObject.renderTarget = this.mainRenderTarget;
130-
renderer.setBlendMode(0);
131-
}
132-
57+
renderer.pipelines.BitmapMaskPipeline.beginMask(this, maskedObject, camera);
13358
},
13459

135-
postRenderWebGL: function (renderer, gameObject)
60+
postRenderWebGL: function (renderer)
13661
{
137-
var maskRenderer = renderer.maskRenderer;
138-
var gl = renderer.gl;
139-
var prevRenderTarget = gameObject.renderTarget;
140-
141-
// flush and reset
142-
renderer.currentRenderer.flush(null, this.mainRenderTarget);
143-
gameObject.renderTarget = prevRenderTarget;
144-
145-
// Apply alpha masking using mask renderer
146-
maskRenderer.draw(null, null, this.mainTexture, this.maskTexture);
62+
renderer.pipelines.BitmapMaskPipeline.endMask(this);
14763
},
14864

14965
preRenderCanvas: function (renderer, mask, camera)

src/display/mask/GeometryMask.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var GeometryMask = new Class({
2020
var geometryMask = this.geometryMask;
2121

2222
// Force flushing before drawing to stencil buffer
23-
renderer.currentRenderer.flush();
23+
renderer.flush();
2424

2525
// Enable and setup GL state to write to stencil buffer
2626
gl.enable(gl.STENCIL_TEST);
@@ -31,7 +31,7 @@ var GeometryMask = new Class({
3131

3232
// Write stencil buffer
3333
geometryMask.renderWebGL(renderer, geometryMask, 0.0, camera);
34-
renderer.currentRenderer.flush();
34+
renderer.flush();
3535

3636
// Use stencil buffer to affect next rendering object
3737
gl.colorMask(true, true, true, true);
@@ -44,7 +44,7 @@ var GeometryMask = new Class({
4444
var gl = renderer.gl;
4545

4646
// Force flush before disabling stencil test
47-
renderer.currentRenderer.flush();
47+
renderer.flush();
4848
gl.disable(gl.STENCIL_TEST);
4949
},
5050

src/renderer/webgl/WebGLPipeline.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ var WebGLPipeline = new Class({
1717
this.vertexCount = 0;
1818
this.vertexCapacity = config.vertexCapacity;
1919
this.renderer = config.renderer;
20-
this.vertexData = new ArrayBuffer(config.vertexCapacity * config.vertexSize);
21-
this.vertexBuffer = this.renderer.createVertexBuffer(this.vertexData.byteLength, this.gl.STREAM_DRAW);
20+
this.vertexData = (config.vertices ? config.vertices : new ArrayBuffer(config.vertexCapacity * config.vertexSize));
21+
this.vertexBuffer = this.renderer.createVertexBuffer((config.vertices ? config.vertices : this.vertexData.byteLength), this.gl.STREAM_DRAW);
2222
this.program = this.renderer.createProgram(config.vertShader, config.fragShader);
2323
this.attributes = config.attributes;
2424
this.vertexSize = config.vertexSize;

src/renderer/webgl/WebGLRenderer.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var Utils = require('./Utils');
77
// Default Pipelines
88
var TextureTintPipeline = require('./pipelines/TextureTintPipeline');
99
var FlatTintPipeline = require('./pipelines/FlatTintPipeline');
10+
var BitmapMaskPipeline = require('./pipelines/BitmapMaskPipeline');
1011

1112
var WebGLRenderer = new Class({
1213

@@ -131,7 +132,8 @@ var WebGLRenderer = new Class({
131132

132133
this.addPipeline('TextureTintPipeline', new TextureTintPipeline(this.game, gl, this));
133134
this.addPipeline('FlatTintPipeline', new FlatTintPipeline(this.game, gl, this));
134-
135+
this.addPipeline('BitmapMaskPipeline', new BitmapMaskPipeline(this.game, gl, this));
136+
135137
this.setBlendMode(CONST.BlendModes.NORMAL);
136138
this.resize(this.width, this.height, this.game.config.resolution);
137139

@@ -546,11 +548,11 @@ var WebGLRenderer = new Class({
546548

547549
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS))
548550
{
549-
return new Error('Failed to compile Vertex Shader:\n' + gl.getShaderInfoLog(vs));
551+
throw new Error('Failed to compile Vertex Shader:\n' + gl.getShaderInfoLog(vs));
550552
}
551553
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS))
552554
{
553-
return new Error('Failed to compile Fragment Shader:\n' + gl.getShaderInfoLog(fs));
555+
throw new Error('Failed to compile Fragment Shader:\n' + gl.getShaderInfoLog(fs));
554556
}
555557

556558
gl.attachShader(program, vs);
@@ -559,7 +561,7 @@ var WebGLRenderer = new Class({
559561

560562
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
561563
{
562-
return new Error('Failed to link program:\n' + gl.getProgramInfoLog(program));
564+
throw new Error('Failed to link program:\n' + gl.getProgramInfoLog(program));
563565
}
564566

565567
return program;
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
var Class = require('../../../utils/Class');
2+
var WebGLPipeline = require('../WebGLPipeline');
3+
var Utils = require('../Utils');
4+
var ShaderSourceVS = require('../shaders/BitmapMask.vert');
5+
var ShaderSourceFS = require('../shaders/BitmapMask.frag');
6+
7+
var BitmapMaskPipeline = new Class({
8+
9+
Extends: WebGLPipeline,
10+
11+
initialize:
12+
13+
function BitmapMaskPipeline(game, gl, renderer)
14+
{
15+
WebGLPipeline.call(this, {
16+
name: 'BitmapMaskPipeline',
17+
game: game,
18+
gl: gl,
19+
renderer: renderer,
20+
topology: gl.TRIANGLES,
21+
vertShader: ShaderSourceVS,
22+
fragShader: ShaderSourceFS,
23+
vertexCapacity: 3,
24+
25+
vertexSize:
26+
Float32Array.BYTES_PER_ELEMENT * 2,
27+
28+
vertices: new Float32Array([
29+
-1, +1, -1, -7, +7, +1
30+
]).buffer,
31+
32+
attributes: [
33+
{
34+
name: 'inPosition',
35+
size: 2,
36+
type: gl.FLOAT,
37+
normalized: false,
38+
offset: 0
39+
}
40+
]
41+
});
42+
43+
this.vertexViewF32 = new Float32Array(this.vertexData);
44+
this.maxQuads = 1;
45+
this.resolutionDirty = true;
46+
},
47+
48+
onBind: function ()
49+
{
50+
WebGLPipeline.prototype.onBind.call(this);
51+
52+
var renderer = this.renderer;
53+
var program = this.currentProgram;
54+
55+
if (this.resolutionDirty || (this.currentProgram !== this.program))
56+
{
57+
renderer.setFloat2(program, 'uResolution', this.width, this.height);
58+
renderer.setInt1(program, 'uMainSampler', 0);
59+
renderer.setInt1(program, 'uMaskSampler', 1);
60+
this.resolutionDirty = false;
61+
}
62+
63+
return this;
64+
},
65+
66+
resize: function (width, height, resolution)
67+
{
68+
WebGLPipeline.prototype.resize.call(this, width, height, resolution);
69+
this.resolutionDirty = true;
70+
return this;
71+
},
72+
73+
beginMask: function (mask, maskedObject, camera)
74+
{
75+
var bitmapMask = mask.bitmapMask;
76+
var renderer = this.renderer;
77+
var gl = this.gl;
78+
var visible = bitmapMask.visible;
79+
80+
if (bitmapMask && gl)
81+
{
82+
// First we clear the mask framebuffer
83+
renderer.setFramebuffer(mask.maskFramebuffer);
84+
gl.clearColor(0, 0, 0, 0);
85+
gl.clear(gl.COLOR_BUFFER_BIT);
86+
87+
// We render out mask source
88+
bitmapMask.visible = true;
89+
bitmapMask.renderWebGL(renderer, bitmapMask, 0.0, camera);
90+
bitmapMask.visible = visible;
91+
renderer.flush();
92+
93+
// Bind and clear our main source (masked object)
94+
renderer.setFramebuffer(mask.mainFramebuffer);
95+
gl.clearColor(0, 0, 0, 0);
96+
gl.clear(gl.COLOR_BUFFER_BIT);
97+
}
98+
},
99+
100+
endMask: function (mask)
101+
{
102+
var bitmapMask = mask.bitmapMask;
103+
var renderer = this.renderer;
104+
var gl = this.gl;
105+
106+
if (bitmapMask)
107+
{
108+
// Return to default framebuffer
109+
renderer.setFramebuffer(null);
110+
111+
// Bind bitmap mask pipeline and draw
112+
renderer.setPipeline(this);
113+
renderer.setTexture2D(mask.mainTexture, 0);
114+
renderer.setTexture2D(mask.maskTexture, 1);
115+
116+
// Finally draw a triangle filling the whole screen
117+
gl.drawArrays(this.topology, 0, 3);
118+
}
119+
}
120+
121+
});
122+
123+
module.exports = BitmapMaskPipeline;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#define SHADER_NAME PHASER_BITMAP_MASK_FS
2+
3+
precision mediump float;
4+
5+
uniform vec2 uResolution;
6+
uniform sampler2D uMainSampler;
7+
uniform sampler2D uMaskSampler;
8+
9+
void main()
10+
{
11+
vec2 uv = gl_FragCoord.xy / uResolution;
12+
vec4 mainColor = texture2D(uMainSampler, uv);
13+
vec4 maskColor = texture2D(uMaskSampler, uv);
14+
float alpha = maskColor.a * mainColor.a;
15+
gl_FragColor = vec4(mainColor.rgb * alpha, alpha);
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#define SHADER_NAME PHASER_BITMAP_MASK_VS
2+
3+
precision mediump float;
4+
5+
attribute vec2 inPosition;
6+
7+
void main()
8+
{
9+
gl_Position = vec4(inPosition, 0.0, 1.0);
10+
}

0 commit comments

Comments
 (0)