2016-12-07 02:28:22 +00:00
|
|
|
/**
|
|
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
|
|
* @author Mat Groves (@Doormat23)
|
|
|
|
* @copyright 2016 Photon Storm Ltd.
|
|
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
|
|
*/
|
|
|
|
|
2016-12-07 03:42:41 +00:00
|
|
|
var CONST = require('../../const');
|
2016-12-07 02:28:22 +00:00
|
|
|
var CreateEmptyTexture = require('./utils/CreateEmptyTexture');
|
2017-01-19 23:20:36 +00:00
|
|
|
var CreateTexture2DImage = require('./utils/texture/CreateTexture2DImage');
|
2017-01-19 22:43:41 +00:00
|
|
|
var BlitterBatch = require('./batches/blitter/BlitterBatch');
|
|
|
|
var SpriteBatch = require('./batches/sprite/SpriteBatch');
|
2017-01-20 22:02:12 +00:00
|
|
|
var SpriteBatch32 = require('./batches/sprite/SpriteBatch32');
|
2017-01-23 21:42:47 +00:00
|
|
|
var BlendModes = require('../BlendModes');
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
var WebGLRenderer = function (game)
|
|
|
|
{
|
|
|
|
this.game = game;
|
|
|
|
|
2016-12-07 03:42:41 +00:00
|
|
|
this.type = CONST.WEBGL;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2016-12-07 03:42:41 +00:00
|
|
|
this.width = game.config.width * game.config.resolution;
|
|
|
|
this.height = game.config.height * game.config.resolution;
|
|
|
|
this.resolution = game.config.resolution;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
this.view = game.canvas;
|
|
|
|
|
2017-01-16 15:53:34 +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,
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-01-16 15:53:34 +00:00
|
|
|
WebGLContextOptions: {
|
|
|
|
alpha: true,
|
|
|
|
antialias: true,
|
|
|
|
premultipliedAlpha: true,
|
|
|
|
stencil: true,
|
|
|
|
preserveDrawingBuffer: false
|
|
|
|
}
|
2016-12-07 02:28:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
this.contextLost = false;
|
2017-01-16 15:53:34 +00:00
|
|
|
this.maxTextures = 1;
|
|
|
|
this.multiTexture = false;
|
|
|
|
this.blendModes = [];
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-01-16 15:53:34 +00:00
|
|
|
this.gl = null;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
this.init();
|
2017-01-19 23:20:36 +00:00
|
|
|
|
2017-01-20 22:02:12 +00:00
|
|
|
this.extensions = this.gl.getSupportedExtensions();
|
|
|
|
|
2017-01-19 17:53:20 +00:00
|
|
|
this.blitterBatch = new BlitterBatch(game, this.gl, this);
|
2017-01-20 22:02:12 +00:00
|
|
|
this.spriteBatch = null;
|
|
|
|
if (this.extensions.indexOf('OES_element_index_uint') >= 0)
|
|
|
|
{
|
|
|
|
this.spriteBatch = new SpriteBatch32(game, this.gl, this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.spriteBatch = new SpriteBatch(game, this.gl, this);
|
|
|
|
}
|
2017-01-19 23:20:36 +00:00
|
|
|
|
2017-01-19 17:53:20 +00:00
|
|
|
this.batch = null;
|
|
|
|
this.currentTexture2D = null;
|
2016-12-07 02:28:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
WebGLRenderer.prototype.constructor = WebGLRenderer;
|
|
|
|
|
|
|
|
WebGLRenderer.prototype = {
|
|
|
|
|
|
|
|
init: function ()
|
|
|
|
{
|
2017-01-25 12:02:18 +00:00
|
|
|
console.log('WebGLRenderer.init');
|
|
|
|
|
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-01-16 15:53:34 +00:00
|
|
|
/*
|
|
|
|
// Will need supporting
|
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
|
|
|
|
|
|
if (this.maxTextures === 1)
|
|
|
|
{
|
|
|
|
this.multiTexture = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.createMultiEmptyTextures();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.emptyTexture = CreateEmptyTexture(this.gl, 1, 1, 0, 0);
|
2017-01-16 15:53:34 +00:00
|
|
|
*/
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
gl.disable(gl.DEPTH_TEST);
|
|
|
|
gl.disable(gl.CULL_FACE);
|
|
|
|
gl.enable(gl.BLEND);
|
|
|
|
|
2016-12-07 03:42:41 +00:00
|
|
|
gl.clearColor(1, 0, 0, 1);
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
this.resize(this.width, this.height);
|
|
|
|
|
2017-01-16 15:53:34 +00:00
|
|
|
/*
|
|
|
|
// Will need supporting
|
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
this.extensions.compression = {};
|
|
|
|
|
|
|
|
var etc1 = gl.getExtension('WEBGL_compressed_texture_etc1') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_etc1');
|
|
|
|
var pvrtc = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
|
|
|
|
var s3tc = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
|
|
|
|
|
|
|
|
if (etc1)
|
|
|
|
{
|
|
|
|
this.extensions.compression.ETC1 = etc1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pvrtc)
|
|
|
|
{
|
|
|
|
this.extensions.compression.PVRTC = pvrtc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s3tc)
|
|
|
|
{
|
|
|
|
this.extensions.compression.S3TC = s3tc;
|
|
|
|
}
|
2017-01-16 15:53:34 +00:00
|
|
|
*/
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
// Map Blend Modes
|
|
|
|
|
|
|
|
var add = [ gl.SRC_ALPHA, gl.DST_ALPHA ];
|
2017-01-24 15:21:49 +00:00
|
|
|
var normal = [ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ];
|
2016-12-07 02:28:22 +00:00
|
|
|
var multiply = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ];
|
|
|
|
var screen = [ gl.SRC_ALPHA, gl.ONE ];
|
|
|
|
|
|
|
|
this.blendModes = [
|
|
|
|
normal, add, multiply, screen, normal,
|
|
|
|
normal, normal, normal, normal,
|
|
|
|
normal, normal, normal, normal,
|
|
|
|
normal, normal, normal, normal
|
|
|
|
];
|
2017-01-23 21:42:47 +00:00
|
|
|
|
|
|
|
this.blendMode = -1;
|
2016-12-07 02:28:22 +00:00
|
|
|
},
|
|
|
|
|
2017-01-19 23:20:36 +00:00
|
|
|
createTexture2D: function (source)
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
if (!source.glTexture)
|
|
|
|
{
|
|
|
|
source.glTexture = CreateTexture2DImage(gl, source.image, gl.NEAREST, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.currentTexture2D = source.glTexture;
|
|
|
|
},
|
|
|
|
|
2017-01-19 22:43:41 +00:00
|
|
|
setTexture2D: function (texture2D)
|
2017-01-19 17:53:20 +00:00
|
|
|
{
|
2017-01-20 18:53:53 +00:00
|
|
|
if (this.currentTexture2D !== texture2D)
|
2017-01-20 18:13:24 +00:00
|
|
|
{
|
2017-01-20 18:53:53 +00:00
|
|
|
if (this.batch)
|
2017-01-20 18:51:00 +00:00
|
|
|
{
|
2017-01-20 18:53:53 +00:00
|
|
|
this.batch.flush();
|
2017-01-20 18:51:00 +00:00
|
|
|
}
|
2017-01-20 18:53:53 +00:00
|
|
|
|
|
|
|
var gl = this.gl;
|
|
|
|
|
2017-01-20 18:13:24 +00:00
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture2D);
|
2017-01-20 18:53:53 +00:00
|
|
|
|
2017-01-20 18:13:24 +00:00
|
|
|
this.currentTexture2D = texture2D;
|
|
|
|
}
|
2017-01-19 17:53:20 +00:00
|
|
|
},
|
|
|
|
|
2017-01-20 18:13:24 +00:00
|
|
|
setBatch: function (batch, texture2D)
|
2017-01-19 22:43:41 +00:00
|
|
|
{
|
2017-01-20 18:13:24 +00:00
|
|
|
this.setTexture2D(texture2D);
|
2017-01-20 18:53:53 +00:00
|
|
|
|
|
|
|
if (this.batch !== batch)
|
2017-01-19 22:43:41 +00:00
|
|
|
{
|
|
|
|
if (this.batch)
|
|
|
|
{
|
|
|
|
this.batch.flush();
|
|
|
|
}
|
2017-01-20 18:53:53 +00:00
|
|
|
|
2017-01-19 22:43:41 +00:00
|
|
|
batch.bind();
|
2017-01-20 18:53:53 +00:00
|
|
|
|
2017-01-19 22:43:41 +00:00
|
|
|
this.batch = batch;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
resize: function (width, height)
|
|
|
|
{
|
2016-12-07 03:42:41 +00:00
|
|
|
var res = this.game.config.resolution;
|
|
|
|
|
|
|
|
this.width = width * res;
|
|
|
|
this.height = height * res;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
|
|
|
this.view.width = this.width;
|
|
|
|
this.view.height = this.height;
|
|
|
|
|
|
|
|
if (this.autoResize)
|
|
|
|
{
|
2016-12-07 03:42:41 +00:00
|
|
|
this.view.style.width = (this.width / res) + 'px';
|
|
|
|
this.view.style.height = (this.height / res) + 'px';
|
2016-12-07 02:28:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.gl.viewport(0, 0, this.width, this.height);
|
|
|
|
|
2017-01-16 15:53:34 +00:00
|
|
|
// Needed?
|
|
|
|
// this.clipUnitX = 2 / this.width;
|
|
|
|
// this.clipUnitY = 2 / this.height;
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-01-16 15:53:34 +00:00
|
|
|
// Needed?
|
|
|
|
// this.projection.x = (this.width / 2) / res;
|
|
|
|
// this.projection.y = -(this.height / 2) / res;
|
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
|
|
|
{
|
2016-12-07 03:42:41 +00:00
|
|
|
// console.log('%c render start ', 'color: #ffffff; background: #00ff00;');
|
|
|
|
|
2016-12-07 02:28:22 +00:00
|
|
|
// No point rendering if our context has been blown up!
|
|
|
|
if (this.contextLost)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add Pre-render hook
|
|
|
|
|
|
|
|
var gl = this.gl;
|
|
|
|
|
|
|
|
// clear is needed for the FBO, otherwise corruption ...
|
|
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
|
2017-01-23 21:42:47 +00:00
|
|
|
this.setBlendMode(BlendModes.NORMAL);
|
2017-01-25 17:10:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a single State.
|
|
|
|
*
|
|
|
|
* @method render
|
|
|
|
* @param {Phaser.State} state - The State to be rendered.
|
|
|
|
* @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.
|
|
|
|
*/
|
|
|
|
{
|
2016-12-07 02:28:22 +00:00
|
|
|
// Could move to the State Systems or MainLoop
|
2017-01-31 21:40:29 +00:00
|
|
|
var list = state.sys.children.list;
|
|
|
|
var length = list.length;
|
|
|
|
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-01-19 17:53:20 +00:00
|
|
|
child.renderWebGL(this, child, interpolationPercentage);
|
2017-01-31 20:24:51 +00:00
|
|
|
var batch = this.batch;
|
2017-01-24 13:15:25 +00:00
|
|
|
if (batch && batch.isFull())
|
2017-01-25 17:10:19 +00:00
|
|
|
{
|
2017-01-20 19:43:36 +00:00
|
|
|
batch.flush();
|
2017-01-25 17:10:19 +00:00
|
|
|
}
|
2017-01-19 17:53:20 +00:00
|
|
|
}
|
2017-01-25 17:10:19 +00:00
|
|
|
},
|
2016-12-07 02:28:22 +00:00
|
|
|
|
2017-01-25 17:10:19 +00:00
|
|
|
// Called at the end of the render loop (tidy things up, etc)
|
|
|
|
postRender: function ()
|
|
|
|
{
|
|
|
|
if (this.batch)
|
|
|
|
{
|
|
|
|
this.batch.flush();
|
|
|
|
}
|
2016-12-07 02:28:22 +00:00
|
|
|
|
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;');
|
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function ()
|
|
|
|
{
|
|
|
|
this.gl = null;
|
2017-01-19 17:53:20 +00:00
|
|
|
},
|
2017-01-23 21:42:47 +00:00
|
|
|
|
|
|
|
createFBO: function () {},
|
|
|
|
|
|
|
|
setBlendMode: function (newBlendMode)
|
|
|
|
{
|
|
|
|
var gl = this.gl;
|
|
|
|
var batch = this.batch;
|
|
|
|
var blend = null;
|
|
|
|
|
|
|
|
if (this.blendMode !== newBlendMode)
|
|
|
|
{
|
|
|
|
if (batch)
|
|
|
|
batch.flush();
|
|
|
|
blend = this.blendModes[newBlendMode];
|
|
|
|
gl.enable(gl.BLEND);
|
2017-01-24 15:21:49 +00:00
|
|
|
if (blend.length > 2)
|
|
|
|
{
|
|
|
|
gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl.blendFunc(blend[0], blend[1]);
|
|
|
|
}
|
2017-01-23 21:42:47 +00:00
|
|
|
this.blendMode = newBlendMode;
|
|
|
|
}
|
|
|
|
}
|
2016-12-07 02:28:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = WebGLRenderer;
|