2016-12-07 02:28:22 +00:00
|
|
|
/**
|
2017-02-13 12:01:19 +00:00
|
|
|
* @author Richard Davey (@photonstorm)
|
|
|
|
* @author Felipe Alfonso (@bitnenfer)
|
|
|
|
* @copyright 2017 Photon Storm Ltd.
|
2016-12-07 02:28:22 +00:00
|
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
|
|
*/
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
var BlendModes = require('../BlendModes');
|
2017-04-06 17:40:43 +00:00
|
|
|
var BlitterBatch = require('./renderers/blitterbatch/BlitterBatch');
|
2017-07-04 13:48:18 +00:00
|
|
|
var Class = require('../../utils/Class');
|
|
|
|
var CONST = require('../../const');
|
|
|
|
var EffectRenderer = require('./renderers/effectrenderer/EffectRenderer');
|
|
|
|
var IsSizePowerOfTwo = require('../../math/pow2/IsSizePowerOfTwo');
|
2017-04-06 17:40:43 +00:00
|
|
|
var QuadBatch = require('./renderers/quadbatch/QuadBatch');
|
2017-09-17 20:13:40 +00:00
|
|
|
var ParticleRenderer = require('./renderers/particlerenderer/ParticleRenderer');
|
2017-07-04 13:48:18 +00:00
|
|
|
var ResourceManager = require('./ResourceManager');
|
|
|
|
var Resources = require('./resources');
|
|
|
|
var ScaleModes = require('../ScaleModes');
|
|
|
|
var ShapeBatch = require('./renderers/shapebatch/ShapeBatch');
|
2017-04-06 17:40:43 +00:00
|
|
|
var SpriteBatch = require('./renderers/spritebatch/SpriteBatch');
|
2017-04-25 22:09:13 +00:00
|
|
|
var TileBatch = require('./renderers/tilebatch/TileBatch');
|
2017-06-01 21:05:50 +00:00
|
|
|
var TilemapRenderer = require('./renderers/tilemaprenderer/TilemapRenderer');
|
2017-07-04 12:10:26 +00:00
|
|
|
var WebGLSnapshot = require('../snapshot/WebGLSnapshot');
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
var WebGLRenderer = new Class({
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
initialize:
|
|
|
|
|
|
|
|
function WebGLRenderer (game)
|
2016-12-07 02:28:22 +00:00
|
|
|
{
|
2017-09-13 19:11:40 +00:00
|
|
|
var _this = this;
|
2017-07-04 13:48:18 +00:00
|
|
|
this.game = game;
|
2017-09-13 19:43:34 +00:00
|
|
|
this.onContextLostCallbacks = [];
|
|
|
|
this.onContextRestoredCallbacks = [];
|
2017-07-04 13:48:18 +00:00
|
|
|
this.type = CONST.WEBGL;
|
|
|
|
this.width = game.config.width * game.config.resolution;
|
|
|
|
this.height = game.config.height * game.config.resolution;
|
|
|
|
this.resolution = game.config.resolution;
|
|
|
|
this.view = game.canvas;
|
2017-09-13 19:11:40 +00:00
|
|
|
this.view.addEventListener('webglcontextlost', function (evt) {
|
2017-09-13 19:43:34 +00:00
|
|
|
var callbacks = _this.onContextLostCallbacks;
|
2017-09-13 19:11:40 +00:00
|
|
|
var renderers = _this.rendererArray;
|
|
|
|
for (var index = 0; index < renderers.length; ++index)
|
|
|
|
{
|
|
|
|
renderers[index].destroy();
|
|
|
|
}
|
|
|
|
_this.contextLost = true;
|
2017-09-13 19:43:34 +00:00
|
|
|
for (var index = 0; index < callbacks.length; ++index)
|
|
|
|
{
|
|
|
|
callbacks[index](_this);
|
|
|
|
}
|
2017-09-13 19:11:40 +00:00
|
|
|
evt.preventDefault();
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
this.view.addEventListener('webglcontextrestored', function (evt) {
|
2017-09-13 19:43:34 +00:00
|
|
|
var callbacks = _this.onContextRestoredCallbacks;
|
2017-09-13 19:11:40 +00:00
|
|
|
_this.rendererArray.length = 0;
|
|
|
|
_this.resourceManager.shaderCache = {};
|
|
|
|
_this.resourceManager.shaderCount = 0;
|
|
|
|
_this.contextLost = false;
|
|
|
|
_this.init();
|
2017-09-13 20:54:32 +00:00
|
|
|
_this.game.textures.each(function (texture) {
|
|
|
|
for (var i = 0; i < texture.source.length; ++i)
|
|
|
|
{
|
|
|
|
texture.source[i].init(_this.game);
|
|
|
|
}
|
|
|
|
}, null);
|
2017-09-13 19:43:34 +00:00
|
|
|
for (var index = 0; index < callbacks.length; ++index)
|
|
|
|
{
|
|
|
|
callbacks[index](_this);
|
|
|
|
}
|
2017-09-13 19:11:40 +00:00
|
|
|
}, false);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
|
|
|
// All of these settings will be able to be controlled via the Game Config
|
|
|
|
this.config = {
|
|
|
|
clearBeforeRender: true,
|
|
|
|
transparent: false,
|
|
|
|
autoResize: false,
|
|
|
|
preserveDrawingBuffer: false,
|
|
|
|
|
|
|
|
WebGLContextOptions: {
|
|
|
|
alpha: true,
|
|
|
|
antialias: true,
|
|
|
|
premultipliedAlpha: true,
|
|
|
|
stencil: true,
|
|
|
|
preserveDrawingBuffer: false
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.contextLost = false;
|
|
|
|
this.maxTextures = 1;
|
|
|
|
this.multiTexture = false;
|
|
|
|
this.blendModes = [];
|
|
|
|
this.gl = null;
|
|
|
|
this.extensions = null;
|
2017-08-10 04:17:58 +00:00
|
|
|
this.extensionList = {};
|
2017-07-04 13:48:18 +00:00
|
|
|
this.rendererArray = [];
|
|
|
|
this.blitterBatch = null;
|
|
|
|
this.aaQuadBatch = null;
|
|
|
|
this.spriteBatch = null;
|
|
|
|
this.shapeBatch = null;
|
|
|
|
this.effectRenderer = null;
|
|
|
|
this.currentRenderer = null;
|
2017-08-03 20:02:57 +00:00
|
|
|
this.currentTexture = [];
|
2017-07-04 13:48:18 +00:00
|
|
|
this.shaderCache = {};
|
|
|
|
this.currentShader = null;
|
|
|
|
this.resourceManager = null;
|
|
|
|
this.currentRenderTarget = null;
|
|
|
|
this.snapshotCallback = null;
|
|
|
|
|
|
|
|
this.scissor = {
|
|
|
|
enabled: false,
|
|
|
|
x: 0,
|
|
|
|
y: 0,
|
|
|
|
width: 0,
|
|
|
|
height: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
this.init();
|
|
|
|
},
|
2017-01-25 12:02:18 +00:00
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
init: function ()
|
|
|
|
{
|
2017-01-16 15:53:34 +00:00
|
|
|
this.gl = this.view.getContext('webgl', this.config.WebGLContextOptions) || this.view.getContext('experimental-webgl', this.config.WebGLContextOptions);
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
if (!this.gl)
|
|
|
|
{
|
|
|
|
this.contextLost = true;
|
|
|
|
throw new Error('This browser does not support WebGL. Try using the Canvas renderer.');
|
|
|
|
}
|
|
|
|
var gl = this.gl;
|
2017-09-13 19:11:40 +00:00
|
|
|
|
|
|
|
this.lostContext = this.getExtension('WEBGL_lose_context');
|
|
|
|
|
2017-02-13 15:27:32 +00:00
|
|
|
var color = this.game.config.backgroundColor;
|
2017-04-05 22:01:44 +00:00
|
|
|
|
|
|
|
this.resourceManager = new ResourceManager(gl);
|
2017-02-13 15:27:32 +00:00
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
gl.disable(gl.DEPTH_TEST);
|
|
|
|
gl.disable(gl.CULL_FACE);
|
|
|
|
gl.enable(gl.BLEND);
|
2017-02-11 20:25:12 +00:00
|
|
|
gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
// Map Blend Modes
|
|
|
|
|
2017-08-03 01:09:59 +00:00
|
|
|
this.blendModes = [];
|
|
|
|
|
|
|
|
for (var i = 0; i <= 16; i++)
|
|
|
|
{
|
|
|
|
this.blendModes.push({ func: [ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ], equation: gl.FUNC_ADD });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add
|
|
|
|
this.blendModes[1].func = [ gl.SRC_ALPHA, gl.DST_ALPHA ];
|
|
|
|
|
|
|
|
// Multiply
|
|
|
|
this.blendModes[2].func = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ];
|
|
|
|
|
|
|
|
// Screen
|
|
|
|
this.blendModes[3].func = [ gl.SRC_ALPHA, gl.ONE ];
|
2017-01-23 21:42:47 +00:00
|
|
|
|
|
|
|
this.blendMode = -1;
|
2017-02-13 15:27:32 +00:00
|
|
|
this.extensions = gl.getSupportedExtensions();
|
2017-04-06 17:40:43 +00:00
|
|
|
this.blitterBatch = this.addRenderer(new BlitterBatch(this.game, gl, this));
|
|
|
|
this.quadBatch = this.addRenderer(new QuadBatch(this.game, gl, this));
|
|
|
|
this.spriteBatch = this.addRenderer(new SpriteBatch(this.game, gl, this));
|
|
|
|
this.shapeBatch = this.addRenderer(new ShapeBatch(this.game, gl, this));
|
2017-04-07 01:49:15 +00:00
|
|
|
this.effectRenderer = this.addRenderer(new EffectRenderer(this.game, gl, this));
|
2017-04-25 22:09:13 +00:00
|
|
|
this.tileBatch = this.addRenderer(new TileBatch(this.game, gl, this));
|
2017-06-01 21:05:50 +00:00
|
|
|
this.tilemapRenderer = this.addRenderer(new TilemapRenderer(this.game, gl, this));
|
2017-09-17 20:13:40 +00:00
|
|
|
this.particleRenderer = this.addRenderer(new ParticleRenderer(this.game, gl, this));
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer = this.spriteBatch;
|
2017-08-15 19:42:04 +00:00
|
|
|
this.currentVertexBuffer = null;
|
2017-04-20 18:06:57 +00:00
|
|
|
this.setBlendMode(0);
|
2017-05-17 15:09:06 +00:00
|
|
|
this.resize(this.width, this.height);
|
2016-12-07 02:28:22 +00:00
|
|
|
},
|
|
|
|
|
2017-08-03 01:09:59 +00:00
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFunc
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendFuncSeparate
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendEquation
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendEquationSeparate
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendColor
|
|
|
|
addBlendMode: function (func, equation)
|
|
|
|
{
|
|
|
|
var index = this.blendModes.push({ func: func, equation: equation });
|
|
|
|
|
|
|
|
return index - 1;
|
|
|
|
},
|
|
|
|
|
|
|
|
updateBlendMode: function (index, func, equation)
|
|
|
|
{
|
|
|
|
if (this.blendModes[index])
|
|
|
|
{
|
|
|
|
this.blendModes[index].func = func;
|
|
|
|
|
|
|
|
if (equation)
|
|
|
|
{
|
|
|
|
this.blendModes[index].equation = equation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
removeBlendMode: function (index)
|
|
|
|
{
|
|
|
|
if (index > 16 && this.blendModes[index])
|
|
|
|
{
|
|
|
|
this.blendModes.splice(index, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2017-08-10 04:17:58 +00:00
|
|
|
getExtension: function (name)
|
|
|
|
{
|
|
|
|
if (!(name in this.extensionList))
|
|
|
|
{
|
|
|
|
this.extensionList[name] = this.gl.getExtension(name);
|
|
|
|
}
|
|
|
|
return this.extensionList[name];
|
|
|
|
},
|
|
|
|
|
2017-09-13 19:43:34 +00:00
|
|
|
addContextLostCallback: function (callback)
|
|
|
|
{
|
|
|
|
if (this.onContextLostCallbacks.indexOf(callback) === -1)
|
|
|
|
{
|
|
|
|
this.onContextLostCallbacks.push(callback);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
addContextRestoredCallback: function (callback)
|
|
|
|
{
|
|
|
|
if (this.onContextRestoredCallbacks.indexOf(callback) === -1)
|
|
|
|
{
|
|
|
|
this.onContextRestoredCallbacks.push(callback);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-05-11 00:24:57 +00:00
|
|
|
createTexture: function (source, width, height)
|
2017-01-19 23:20:36 +00:00
|
|
|
{
|
2017-05-22 14:44:05 +00:00
|
|
|
width = source ? source.width : width;
|
|
|
|
height = source ? source.height : height;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-01-19 23:20:36 +00:00
|
|
|
var gl = this.gl;
|
2017-04-05 22:01:44 +00:00
|
|
|
var filter = gl.NEAREST;
|
2017-07-04 13:48:18 +00:00
|
|
|
var wrap = IsSizePowerOfTwo(width, height) ? gl.REPEAT : gl.CLAMP_TO_EDGE;
|
2017-01-19 23:20:36 +00:00
|
|
|
|
|
|
|
if (!source.glTexture)
|
|
|
|
{
|
2017-04-05 22:01:44 +00:00
|
|
|
if (source.scaleMode === ScaleModes.LINEAR)
|
|
|
|
{
|
|
|
|
filter = gl.LINEAR;
|
|
|
|
}
|
2017-06-07 23:13:34 +00:00
|
|
|
else if (source.scaleMode === ScaleModes.NEAREST || this.game.config.pixelArt)
|
2017-04-05 22:01:44 +00:00
|
|
|
{
|
|
|
|
filter = gl.NEAREST;
|
|
|
|
}
|
|
|
|
|
2017-05-22 14:44:05 +00:00
|
|
|
if (!source && typeof width === 'number' && typeof height === 'number')
|
2017-05-11 00:24:57 +00:00
|
|
|
{
|
|
|
|
source.glTexture = this.resourceManager.createTexture(
|
|
|
|
0,
|
|
|
|
filter,
|
|
|
|
filter,
|
2017-05-20 01:16:45 +00:00
|
|
|
wrap,
|
|
|
|
wrap,
|
2017-05-11 00:24:57 +00:00
|
|
|
gl.RGBA,
|
|
|
|
null,
|
|
|
|
width, height
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
source.glTexture = this.resourceManager.createTexture(
|
2017-04-05 22:01:44 +00:00
|
|
|
0,
|
|
|
|
filter,
|
|
|
|
filter,
|
2017-05-20 01:16:45 +00:00
|
|
|
wrap,
|
|
|
|
wrap,
|
2017-04-05 22:01:44 +00:00
|
|
|
gl.RGBA,
|
|
|
|
source.image
|
|
|
|
);
|
2017-05-11 00:24:57 +00:00
|
|
|
}
|
2017-01-19 23:20:36 +00:00
|
|
|
}
|
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
this.currentTexture[0] = null;
|
2017-01-19 23:20:36 +00:00
|
|
|
},
|
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
setTexture: function (texture, unit)
|
2017-01-19 17:53:20 +00:00
|
|
|
{
|
2017-08-03 20:02:57 +00:00
|
|
|
unit = unit || 0;
|
|
|
|
if (this.currentTexture[unit] !== texture)
|
2017-01-20 18:13:24 +00:00
|
|
|
{
|
2017-01-20 18:53:53 +00:00
|
|
|
var gl = this.gl;
|
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer.flush();
|
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
2017-05-17 15:09:06 +00:00
|
|
|
|
2017-04-05 22:01:44 +00:00
|
|
|
if (texture !== null)
|
|
|
|
{
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture.texture);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
|
|
}
|
2017-01-20 18:53:53 +00:00
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
this.currentTexture[unit] = texture;
|
2017-01-20 18:13:24 +00:00
|
|
|
}
|
2017-01-19 17:53:20 +00:00
|
|
|
},
|
|
|
|
|
2017-04-13 15:45:01 +00:00
|
|
|
setRenderer: function (renderer, texture, renderTarget)
|
2017-01-19 22:43:41 +00:00
|
|
|
{
|
2017-04-05 22:01:44 +00:00
|
|
|
this.setTexture(texture);
|
2017-04-07 01:49:15 +00:00
|
|
|
this.setRenderTarget(renderTarget);
|
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
if (this.currentRenderer !== renderer || this.currentRenderer.shouldFlush())
|
2017-04-07 01:49:15 +00:00
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer.flush();
|
2017-04-07 01:49:15 +00:00
|
|
|
this.currentRenderer = renderer;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
setRenderTarget: function (renderTarget)
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
if (this.currentRenderTarget !== renderTarget)
|
2017-01-19 22:43:41 +00:00
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer.flush();
|
2017-01-20 18:53:53 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
if (renderTarget !== null)
|
|
|
|
{
|
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, renderTarget.framebufferObject);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
if (renderTarget.shouldClear)
|
|
|
|
{
|
2017-06-28 09:22:48 +00:00
|
|
|
gl.clearColor(0, 0, 0, renderTarget.clearAlpha);
|
2017-04-07 01:49:15 +00:00
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
renderTarget.shouldClear = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
|
|
gl.viewport(0, 0, this.width, this.height);
|
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
this.currentRenderTarget = renderTarget;
|
2017-01-19 22:43:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
resize: function (width, height)
|
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
var resolution = this.game.config.resolution;
|
2016-12-07 03:42:41 +00:00
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
this.width = width * resolution;
|
|
|
|
this.height = height * resolution;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
this.view.width = this.width;
|
|
|
|
this.view.height = this.height;
|
|
|
|
|
|
|
|
if (this.autoResize)
|
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
this.view.style.width = (this.width / resolution) + 'px';
|
|
|
|
this.view.style.height = (this.height / resolution) + 'px';
|
2016-12-07 02:28:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.gl.viewport(0, 0, this.width, this.height);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
for (var i = 0, l = this.rendererArray.length; i < l; ++i)
|
2017-02-13 15:27:32 +00:00
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
this.rendererArray[i].bind();
|
|
|
|
this.rendererArray[i].resize(width, height, resolution);
|
2017-02-13 15:27:32 +00:00
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer.bind();
|
2016-12-07 02:28:22 +00:00
|
|
|
},
|
|
|
|
|
2017-01-25 17:10:19 +00:00
|
|
|
// Call at the start of the render loop
|
|
|
|
preRender: function ()
|
2016-12-07 02:28:22 +00:00
|
|
|
{
|
|
|
|
// No point rendering if our context has been blown up!
|
|
|
|
if (this.contextLost)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-13 19:11:40 +00:00
|
|
|
this.setRenderTarget(null);
|
2016-12-07 02:28:22 +00:00
|
|
|
// Add Pre-render hook
|
|
|
|
|
|
|
|
var gl = this.gl;
|
2017-02-11 20:25:12 +00:00
|
|
|
var color = this.game.config.backgroundColor;
|
|
|
|
|
|
|
|
gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-02-13 15:27:32 +00:00
|
|
|
// Some drivers require to call glClear
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
this.setBlendMode(BlendModes.NORMAL);
|
2017-01-25 17:10:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2017-07-14 13:30:20 +00:00
|
|
|
* Renders a single Scene.
|
2017-01-25 17:10:19 +00:00
|
|
|
*
|
|
|
|
* @method render
|
2017-07-14 13:30:20 +00:00
|
|
|
* @param {Phaser.Scene} scene - The Scene to be rendered.
|
2017-01-25 17:10:19 +00:00
|
|
|
* @param {number} interpolationPercentage - The cumulative amount of time that hasn't been simulated yet, divided
|
|
|
|
* by the amount of time that will be simulated the next time update()
|
|
|
|
* runs. Useful for interpolating frames.
|
|
|
|
*/
|
2017-07-14 13:30:20 +00:00
|
|
|
render: function (scene, children, interpolationPercentage, camera)
|
2017-01-25 17:10:19 +00:00
|
|
|
{
|
2017-09-13 19:11:40 +00:00
|
|
|
if (this.contextLost) return;
|
2017-01-31 23:06:13 +00:00
|
|
|
var gl = this.gl;
|
2017-07-04 13:48:18 +00:00
|
|
|
var quadBatch = this.quadBatch;
|
2017-06-08 16:15:02 +00:00
|
|
|
|
|
|
|
this.scissor.enabled = (camera.x !== 0 || camera.y !== 0 || camera.width !== gl.canvas.width || camera.height !== gl.canvas.height);
|
2017-02-07 16:12:20 +00:00
|
|
|
|
2017-04-07 05:06:55 +00:00
|
|
|
this.setRenderTarget(null);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
|
|
|
if (this.scissor.enabled)
|
2017-02-07 19:30:50 +00:00
|
|
|
{
|
|
|
|
gl.enable(gl.SCISSOR_TEST);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
|
|
|
this.scissor.x = camera.x;
|
|
|
|
this.scissor.y = gl.drawingBufferHeight - camera.y - camera.height;
|
|
|
|
this.scissor.width = camera.width;
|
|
|
|
this.scissor.height = camera.height;
|
|
|
|
|
|
|
|
gl.scissor(this.scissor.x, this.scissor.y, this.scissor.width, this.scissor.height);
|
2017-02-07 19:30:50 +00:00
|
|
|
}
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-06-28 00:51:04 +00:00
|
|
|
if (camera.backgroundColor.alphaGL > 0)
|
|
|
|
{
|
|
|
|
var color = camera.backgroundColor;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-06-28 16:47:24 +00:00
|
|
|
quadBatch.bind();
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-06-28 16:47:24 +00:00
|
|
|
quadBatch.add(
|
2017-07-04 13:48:18 +00:00
|
|
|
camera.x, camera.y, camera.width, camera.height,
|
2017-06-28 16:47:24 +00:00
|
|
|
color.redGL, color.greenGL, color.blueGL, color.alphaGL
|
|
|
|
);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-06-28 16:47:24 +00:00
|
|
|
quadBatch.flush();
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-06-28 16:47:24 +00:00
|
|
|
this.currentRenderer.bind();
|
2017-06-28 00:51:04 +00:00
|
|
|
}
|
2017-02-07 16:12:20 +00:00
|
|
|
|
2017-02-21 20:05:18 +00:00
|
|
|
var list = children.list;
|
2017-01-31 21:40:29 +00:00
|
|
|
var length = list.length;
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-01-31 21:40:29 +00:00
|
|
|
for (var index = 0; index < length; ++index)
|
2017-01-19 17:53:20 +00:00
|
|
|
{
|
2017-01-31 21:40:29 +00:00
|
|
|
var child = list[index];
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-10-17 03:17:28 +00:00
|
|
|
if (child.blendMode !== this.blendMode)
|
2017-01-31 23:06:13 +00:00
|
|
|
{
|
2017-10-17 03:17:28 +00:00
|
|
|
this.setBlendMode(child.blendMode);
|
2017-01-31 23:06:13 +00:00
|
|
|
}
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-01-31 23:06:13 +00:00
|
|
|
// drawing child
|
2017-02-21 00:38:22 +00:00
|
|
|
child.renderWebGL(this, child, interpolationPercentage, camera);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-07 01:49:15 +00:00
|
|
|
renderer = this.currentRenderer;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
if (renderer.isFull() || renderer.shouldFlush())
|
2017-01-25 17:10:19 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
renderer.flush();
|
2017-01-25 17:10:19 +00:00
|
|
|
}
|
2017-01-19 17:53:20 +00:00
|
|
|
}
|
2017-05-17 15:09:06 +00:00
|
|
|
|
|
|
|
this.currentRenderer.flush();
|
|
|
|
|
2017-02-10 00:48:32 +00:00
|
|
|
if (camera._fadeAlpha > 0 || camera._flashAlpha > 0)
|
|
|
|
{
|
2017-04-10 19:15:18 +00:00
|
|
|
this.setRenderTarget(null);
|
2017-09-29 01:16:10 +00:00
|
|
|
this.setBlendMode(BlendModes.NORMAL);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-02-10 00:48:32 +00:00
|
|
|
// fade rendering
|
2017-04-06 17:40:43 +00:00
|
|
|
quadBatch.add(
|
2017-07-04 13:48:18 +00:00
|
|
|
camera.x, camera.y, camera.width, camera.height,
|
|
|
|
camera._fadeRed,
|
|
|
|
camera._fadeGreen,
|
|
|
|
camera._fadeBlue,
|
2017-02-10 00:48:32 +00:00
|
|
|
camera._fadeAlpha
|
|
|
|
);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-02-10 00:48:32 +00:00
|
|
|
// flash rendering
|
2017-04-06 17:40:43 +00:00
|
|
|
quadBatch.add(
|
2017-07-04 13:48:18 +00:00
|
|
|
camera.x, camera.y, camera.width, camera.height,
|
|
|
|
camera._flashRed,
|
|
|
|
camera._flashGreen,
|
|
|
|
camera._flashBlue,
|
2017-02-10 00:48:32 +00:00
|
|
|
camera._flashAlpha
|
|
|
|
);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-06 17:40:43 +00:00
|
|
|
quadBatch.flush();
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-04-06 17:40:43 +00:00
|
|
|
this.currentRenderer.bind();
|
2017-02-10 00:48:32 +00:00
|
|
|
}
|
2017-06-08 16:15:02 +00:00
|
|
|
|
|
|
|
if (this.scissor.enabled)
|
2017-02-07 19:30:50 +00:00
|
|
|
{
|
|
|
|
gl.disable(gl.SCISSOR_TEST);
|
|
|
|
}
|
|
|
|
},
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-02-07 19:30:50 +00:00
|
|
|
// Called at the end of the render loop (tidy things up, etc)
|
|
|
|
postRender: function ()
|
|
|
|
{
|
2017-09-13 19:11:40 +00:00
|
|
|
if (this.contextLost) return;
|
|
|
|
|
2017-05-17 15:09:06 +00:00
|
|
|
this.currentRenderer.flush();
|
2017-05-16 19:15:01 +00:00
|
|
|
|
|
|
|
if (this.snapshotCallback)
|
|
|
|
{
|
2017-07-04 12:10:26 +00:00
|
|
|
this.snapshotCallback(WebGLSnapshot(this.view));
|
2017-05-16 19:15:01 +00:00
|
|
|
this.snapshotCallback = null;
|
|
|
|
}
|
|
|
|
|
2017-01-25 17:10:19 +00:00
|
|
|
// Add Post-render hook
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
// console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
|
|
|
|
},
|
|
|
|
|
2017-07-04 12:10:26 +00:00
|
|
|
snapshot: function (callback)
|
2017-05-16 19:15:01 +00:00
|
|
|
{
|
|
|
|
this.snapshotCallback = callback;
|
|
|
|
},
|
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
createFBO: function () {},
|
|
|
|
|
|
|
|
setBlendMode: function (newBlendMode)
|
|
|
|
{
|
2017-10-17 03:17:28 +00:00
|
|
|
if (newBlendMode === BlendModes.SKIP_CHECK)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
var gl = this.gl;
|
2017-04-07 01:49:15 +00:00
|
|
|
var renderer = this.currentRenderer;
|
2017-01-23 21:42:47 +00:00
|
|
|
|
|
|
|
if (this.blendMode !== newBlendMode)
|
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
if (renderer)
|
2017-06-08 16:15:02 +00:00
|
|
|
{
|
2017-04-07 01:49:15 +00:00
|
|
|
renderer.flush();
|
2017-06-08 16:15:02 +00:00
|
|
|
}
|
|
|
|
|
2017-08-03 01:09:59 +00:00
|
|
|
var blend = this.blendModes[newBlendMode].func;
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
gl.enable(gl.BLEND);
|
2017-08-03 01:09:59 +00:00
|
|
|
gl.blendEquation(this.blendModes[newBlendMode].equation);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-01-24 15:21:49 +00:00
|
|
|
if (blend.length > 2)
|
|
|
|
{
|
|
|
|
gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-04 13:48:18 +00:00
|
|
|
gl.blendFunc(blend[0], blend[1]);
|
2017-01-24 15:21:49 +00:00
|
|
|
}
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
this.blendMode = newBlendMode;
|
|
|
|
}
|
2017-02-13 15:27:32 +00:00
|
|
|
},
|
|
|
|
|
2017-04-06 17:40:43 +00:00
|
|
|
addRenderer: function (rendererInstance)
|
2017-02-13 15:27:32 +00:00
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
var index = this.rendererArray.indexOf(rendererInstance);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
|
|
|
if (index < 0)
|
2017-02-13 15:27:32 +00:00
|
|
|
{
|
2017-05-17 15:09:06 +00:00
|
|
|
this.rendererArray.push(rendererInstance);
|
2017-04-06 17:40:43 +00:00
|
|
|
return rendererInstance;
|
2017-02-13 15:27:32 +00:00
|
|
|
}
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-02-13 15:27:32 +00:00
|
|
|
return null;
|
2017-03-21 20:45:57 +00:00
|
|
|
},
|
|
|
|
|
2017-05-20 01:16:45 +00:00
|
|
|
setTextureFilterMode: function (texture, filterMode)
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
2017-06-08 16:15:02 +00:00
|
|
|
var glFilter = [ gl.LINEAR, gl.NEAREST ][filterMode];
|
2017-05-20 01:16:45 +00:00
|
|
|
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture.texture);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter);
|
2017-06-08 16:15:02 +00:00
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
if (this.currentTexture[0] !== null)
|
2017-06-08 16:15:02 +00:00
|
|
|
{
|
2017-08-03 20:02:57 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, this.currentTexture[0].texture);
|
2017-06-08 16:15:02 +00:00
|
|
|
}
|
2017-05-20 01:16:45 +00:00
|
|
|
else
|
2017-06-08 16:15:02 +00:00
|
|
|
{
|
2017-05-20 01:16:45 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
2017-06-08 16:15:02 +00:00
|
|
|
}
|
2017-05-20 01:16:45 +00:00
|
|
|
|
|
|
|
return texture;
|
|
|
|
},
|
|
|
|
|
2017-07-27 19:26:12 +00:00
|
|
|
uploadCanvasToGPU: function (srcCanvas, dstTexture, shouldReallocate)
|
2017-03-21 20:45:57 +00:00
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
if (!dstTexture)
|
|
|
|
{
|
2017-04-06 17:40:43 +00:00
|
|
|
dstTexture = new Resources.Texture(null, 0, 0);
|
2017-07-04 13:48:18 +00:00
|
|
|
|
|
|
|
// Only call this once
|
2017-04-06 17:40:43 +00:00
|
|
|
dstTexture.texture = gl.createTexture();
|
2017-03-21 20:45:57 +00:00
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
if (dstTexture != this.currentTexture[0])
|
2017-07-12 20:55:57 +00:00
|
|
|
{
|
|
|
|
this.currentRenderer.flush();
|
|
|
|
}
|
|
|
|
|
2017-08-03 20:02:57 +00:00
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
|
|
|
2017-07-27 19:26:12 +00:00
|
|
|
if (!shouldReallocate)
|
2017-03-21 20:45:57 +00:00
|
|
|
{
|
2017-07-04 13:48:18 +00:00
|
|
|
// Update resource
|
2017-04-06 17:40:43 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
|
2017-03-21 20:45:57 +00:00
|
|
|
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-04 13:48:18 +00:00
|
|
|
// Allocate or Reallocate resource
|
2017-04-06 17:40:43 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
|
2017-03-21 20:45:57 +00:00
|
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
2017-07-27 19:26:12 +00:00
|
|
|
dstTexture.width = srcCanvas.width;
|
|
|
|
dstTexture.height = srcCanvas.height;
|
2017-03-21 20:45:57 +00:00
|
|
|
}
|
|
|
|
|
2017-07-04 13:48:18 +00:00
|
|
|
// We must rebind old texture
|
2017-08-18 15:31:39 +00:00
|
|
|
if (this.currentTexture.length > 0 && dstTexture != this.currentTexture[0] && this.currentTexture[0] !== null)
|
2017-07-12 20:55:57 +00:00
|
|
|
{
|
2017-08-03 20:02:57 +00:00
|
|
|
gl.bindTexture(gl.TEXTURE_2D, this.currentTexture[0].texture);
|
2017-07-12 20:55:57 +00:00
|
|
|
}
|
2017-03-21 20:45:57 +00:00
|
|
|
|
|
|
|
return dstTexture;
|
2017-07-04 13:48:18 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function ()
|
|
|
|
{
|
2017-09-13 19:11:40 +00:00
|
|
|
if (this.lostContext)
|
|
|
|
{
|
|
|
|
this.lostContext.loseContext();
|
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
this.gl = null;
|
2017-01-23 21:42:47 +00:00
|
|
|
}
|
2017-07-04 13:48:18 +00:00
|
|
|
|
|
|
|
});
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
module.exports = WebGLRenderer;
|