Fixed Multi Texture support in the new batch manager.

This commit is contained in:
Richard Davey 2016-10-25 00:41:45 +01:00
parent 2af81bdfba
commit 4c6691863c
3 changed files with 133 additions and 111 deletions

View file

@ -20,7 +20,7 @@ Phaser.Renderer.WebGL.GameObjects.Image = {
var uvs = frame.uvs; var uvs = frame.uvs;
var verts = src.transform.glVertextData; var verts = src.transform.glVertextData;
var index = src.glTextureIndex; var index = src.frame.source.glTextureIndex;
var tint = src.color._glTint; var tint = src.color._glTint;
var bg = src.color._glBg; var bg = src.color._glBg;

View file

@ -85,7 +85,6 @@ Phaser.Renderer.WebGL.BatchManager = function (renderer, batchSize)
'void main(void) {', 'void main(void) {',
' if (aTextureIndex > 0.0) gl_Position = vec4(0.0);', ' if (aTextureIndex > 0.0) gl_Position = vec4(0.0);',
// ' gl_Position = vec4((aVertexPosition / projectionVector) + center, 0.0, 1.0);',
' gl_Position = vec4(((aVertexPosition + offsetVector) / projectionVector) + center, 0.0, 1.0);', ' gl_Position = vec4(((aVertexPosition + offsetVector) / projectionVector) + center, 0.0, 1.0);',
' vTextureCoord = aTextureCoord;', // pass the texture coordinate to the fragment shader, the GPU will interpolate the points ' vTextureCoord = aTextureCoord;', // pass the texture coordinate to the fragment shader, the GPU will interpolate the points
' vTintColor = vec4(aTintColor.rgb * aTintColor.a, aTintColor.a);', ' vTintColor = vec4(aTintColor.rgb * aTintColor.a, aTintColor.a);',
@ -109,16 +108,15 @@ Phaser.Renderer.WebGL.BatchManager = function (renderer, batchSize)
'uniform sampler2D uSampler;', // our texture 'uniform sampler2D uSampler;', // our texture
'const vec4 PINK = vec4(1.0, 0.0, 1.0, 1.0);',
'void main(void) {', 'void main(void) {',
' vec4 pixel = texture2D(uSampler, vTextureCoord) * vTintColor;', // get the color from the texture ' vec4 pixel = texture2D(uSampler, vTextureCoord) * vTintColor;', // get the color from the texture
' if (pixel.a == 0.0) pixel = vBgColor;', // if texture alpha is zero, use the bg color ' if (pixel.a == 0.0) pixel = vBgColor;', // if texture alpha is zero, use the bg color
// ' if (pixel.a > 0.0) pixel = PINK;', // if texture alpha is zero, use the bg color
' gl_FragColor = pixel;', ' gl_FragColor = pixel;',
'}' '}'
]; ];
this.multiTextureFragmentSrc = null;
// @type {GLint} // @type {GLint}
this.aVertexPosition; this.aVertexPosition;
@ -197,11 +195,6 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.indices[i + 5] = j + 3; // Bottom Left this.indices[i + 5] = j + 3; // Bottom Left
} }
if (this.renderer.enableMultiTextureToggle)
{
// this.initMultitexShader();
}
var gl = this.gl; var gl = this.gl;
// Create indices buffer // Create indices buffer
@ -222,8 +215,51 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
// Set the source of the buffer data (this.vertices array) // Set the source of the buffer data (this.vertices array)
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
// initShader var fragmentSrc = this.fragmentSrc;
var program = this.renderer.compileProgram(this.vertexSrc, this.fragmentSrc);
if (this.renderer.multiTexture && this.renderer.maxTextures > 1)
{
var multiFrag = [
'precision lowp float;',
'varying vec2 vTextureCoord;', // the texture coords passed in from the vertex shader
'varying vec4 vTintColor;', // the color value passed in from the vertex shader (texture color + alpha + tint)
'varying vec4 vBgColor;', // the bg color value passed in from the vertex shader
'varying float vTextureIndex;',
'uniform sampler2D uSamplerArray[' + this.renderer.maxTextures + '];',
'const vec4 PINK = vec4(1.0, 0.0, 1.0, 1.0);',
'void main(void) {',
' vec4 pixel;',
' if (vTextureIndex == 0.0) pixel = texture2D(uSamplerArray[0], vTextureCoord);'
];
for (i = 1; i < this.renderer.maxTextures; i++)
{
multiFrag.push(' else if (vTextureIndex == ' + i + '.0) pixel = texture2D(uSamplerArray[' + i + '], vTextureCoord);');
}
multiFrag = multiFrag.concat([
// ' else pixel = PINK;',
' pixel *= vTintColor;',
// ' if (pixel.a == 0.0) pixel = vBgColor;', // if texture alpha is zero, use the bg color
' gl_FragColor = pixel;',
// ' gl_FragColor = PINK;',
'}'
]);
this.multiTextureFragmentSrc = multiFrag;
fragmentSrc = this.multiTextureFragmentSrc;
console.dir(this.multiTextureFragmentSrc);
}
// Compile the Shaders
var program = this.renderer.compileProgram(this.vertexSrc, fragmentSrc);
// Set Shader // Set Shader
gl.useProgram(program); gl.useProgram(program);
@ -248,7 +284,32 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
// Get and store the uniforms for the shader // Get and store the uniforms for the shader
// this part is different for multi-textures // this part is different for multi-textures
if (this.renderer.multiTexture)
{
// Bind empty multi-textures to avoid WebGL spam
var indices = [];
var tempTexture = this.renderer.createEmptyTexture(1, 1, 0);
for (i = 0; i < this.maxTextures; i++)
{
gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, tempTexture);
indices.push(i);
}
this.uSampler = gl.getUniformLocation(program, 'uSamplerArray[0]');
gl.activeTexture(gl.TEXTURE0);
gl.uniform1iv(this.uSamplerArray, indices);
}
else
{
this.uSampler = gl.getUniformLocation(program, 'uSampler'); this.uSampler = gl.getUniformLocation(program, 'uSampler');
}
// The projection vector (middle of the game world) // The projection vector (middle of the game world)
this.projectionVector = gl.getUniformLocation(program, 'projectionVector'); this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
@ -259,64 +320,6 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.program = program; this.program = program;
}, },
initMultiTextureShader: function ()
{
this.gl = this.renderer.gl;
// var gl = this.gl;
// New Fragment Source ...
/*
if (this.renderer.enableMultiTextureToggle)
{
var dynamicIfs = '\tif (vTextureIndex == 0.0) gl_FragColor = texture2D(uSamplerArray[0], vTextureCoord) * vColor;\n';
for (var index = 1; index < this.MAX_TEXTURES; ++index)
{
dynamicIfs += '\telse if (vTextureIndex == ' +
index + '.0) gl_FragColor = texture2D(uSamplerArray[' +
index + '], vTextureCoord) * vColor;\n';
}
// Does this need the vTextureIndex varying? Doesn't look like it
this.defaultShader = new Phaser.Filter(
this.renderer.game,
undefined,
[
'precision lowp float;',
'varying vec2 vTextureCoord;',
'varying vec4 vColor;',
'varying float vTextureIndex;',
'uniform sampler2D uSamplerArray[' + this.MAX_TEXTURES + '];',
'void main(void) {',
dynamicIfs,
'\telse gl_FragColor = texture2D(uSamplerArray[0], vTextureCoord) * vColor;',
'}'
]);
}
else
{
// Does this need the vTextureIndex varying? Doesn't look like it
this.defaultShader = new Phaser.Filter(
this.renderer.game,
undefined,
[
'precision lowp float;',
'varying vec2 vTextureCoord;',
'varying vec4 vColor;',
'varying float vTextureIndex;',
'uniform sampler2D uSampler;',
'void main(void) {',
' gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor;',
'}'
]);
}
*/
},
begin: function () begin: function ()
{ {
this._i = 0; this._i = 0;
@ -349,27 +352,47 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
setCurrentTexture: function (textureSource) setCurrentTexture: function (textureSource)
{ {
if (this.currentTextureSource === textureSource) var gl = this.gl;
{
return;
}
// if (this.renderer.textureArray[source.glTextureIndex] !== source) if (this.renderer.multiTexture)
{
if (this.renderer.textureArray[textureSource.glTextureIndex] !== textureSource)
{
console.log('setCurrentTexture', this.currentBatchSize);
console.log(textureSource);
if (this.currentBatchSize > 0) if (this.currentBatchSize > 0)
{ {
this.flush(); this.flush();
} }
var gl = this.gl; gl.activeTexture(gl.TEXTURE0 + textureSource.glTextureIndex);
console.log('activeTexture', gl.TEXTURE0 + textureSource.glTextureIndex);
gl.bindTexture(gl.TEXTURE_2D, textureSource.glTexture);
this.renderer.textureArray[textureSource.glTextureIndex] = textureSource;
}
}
else
{
if (this.currentTextureSource === textureSource)
{
return;
}
if (this.currentBatchSize > 0)
{
this.flush();
}
// gl.activeTexture(gl.TEXTURE0 + textureSource.glTextureIndex);
gl.activeTexture(gl.TEXTURE0); gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textureSource.glTexture); gl.bindTexture(gl.TEXTURE_2D, textureSource.glTexture);
this.currentTextureSource = textureSource; this.currentTextureSource = textureSource;
}
// this.renderer.textureArray[textureSource.glTextureIndex] = textureSource;
}, },
// Call 'addVert' x4 after calling this // Call 'addVert' x4 after calling this
@ -424,10 +447,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
} }
// Set texture // Set texture
if (this.currentTextureSource !== gameObject.frame.source)
{
this.setCurrentTexture(gameObject.frame.source); this.setCurrentTexture(gameObject.frame.source);
}
// These are TypedArray Views into the vertices ArrayBuffer // These are TypedArray Views into the vertices ArrayBuffer
var colors = this.colors; var colors = this.colors;
@ -476,7 +496,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.list[this.currentBatchSize++] = gameObject; this.list[this.currentBatchSize++] = gameObject;
}, },
prepShader: function () initShader: function ()
{ {
var gl = this.gl; var gl = this.gl;
@ -525,7 +545,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
// Always dirty the first pass through but subsequent calls may be clean // Always dirty the first pass through but subsequent calls may be clean
if (this.dirty) if (this.dirty)
{ {
this.prepShader(); this.initShader();
} }
var gl = this.gl; var gl = this.gl;
@ -559,7 +579,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.renderer.setBlendMode(sprite.blendMode); this.renderer.setBlendMode(sprite.blendMode);
} }
if (this.currentTextureSource !== sprite.frame.source) if (!this.renderer.multiTexture && this.currentTextureSource !== sprite.frame.source)
{ {
if (currentSize > 0) if (currentSize > 0)
{ {

View file

@ -86,9 +86,7 @@ Phaser.Renderer.WebGL = function (game)
*/ */
this.stencilBufferLimit = 6; this.stencilBufferLimit = 6;
// WebGL specific from here this.multiTexture = true;
this.enableMultiTextureToggle = false;
this.extensions = {}; this.extensions = {};
@ -155,10 +153,10 @@ Phaser.Renderer.WebGL = function (game)
this.gl = null; this.gl = null;
// Add a null entry to avoid an array look-up miss this.textureArray = [];
this.textureArray = [ null, null ];
this.currentBlendMode = 0; this.currentBlendMode = 0;
this.currentTextureSource = null;
this.blendModes = []; this.blendModes = [];
@ -215,6 +213,13 @@ Phaser.Renderer.WebGL.prototype = {
this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
console.log('maxTextures', this.maxTextures);
if (this.maxTextures === 1)
{
this.multiTexture = false;
}
gl.disable(gl.DEPTH_TEST); gl.disable(gl.DEPTH_TEST);
gl.disable(gl.CULL_FACE); gl.disable(gl.CULL_FACE);
gl.enable(gl.BLEND); gl.enable(gl.BLEND);
@ -318,12 +323,6 @@ Phaser.Renderer.WebGL.prototype = {
*/ */
setTexturePriority: function (textureNameCollection) setTexturePriority: function (textureNameCollection)
{ {
if (!this.enableMultiTextureToggle)
{
console.warn('setTexturePriority error: Multi Texture support hasn\'t been enabled in the Phaser Game Config.');
return;
}
var maxTextures = this.maxTextures; var maxTextures = this.maxTextures;
var imageCache = this.game.cache._cache.image; var imageCache = this.game.cache._cache.image;
var imageName = null; var imageName = null;
@ -409,8 +408,7 @@ Phaser.Renderer.WebGL.prototype = {
// gl.clearColor(0, 0, 0, 1); // gl.clearColor(0, 0, 0, 1);
// gl.clear(gl.COLOR_BUFFER_BIT); // gl.clear(gl.COLOR_BUFFER_BIT);
// Normal Blend Mode this.setBlendMode(this.blendModes.NORMAL);
this.setBlendMode(0);
/* /*
if (this.clearBeforeRender) if (this.clearBeforeRender)
@ -476,6 +474,8 @@ Phaser.Renderer.WebGL.prototype = {
// Takes a TextureSource object // Takes a TextureSource object
updateTexture: function (source) updateTexture: function (source)
{ {
console.log('updateTexture', source);
if (source.compressionAlgorithm) if (source.compressionAlgorithm)
{ {
return this.updateCompressedTexture(source); return this.updateCompressedTexture(source);
@ -488,9 +488,7 @@ Phaser.Renderer.WebGL.prototype = {
source.glTexture = gl.createTexture(); source.glTexture = gl.createTexture();
} }
// gl.activeTexture(gl.TEXTURE0 + source.glTextureIndex); gl.activeTexture(gl.TEXTURE0 + source.glTextureIndex);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, source.glTexture); gl.bindTexture(gl.TEXTURE_2D, source.glTexture);
@ -699,11 +697,15 @@ Phaser.Renderer.WebGL.prototype = {
createEmptyTexture: function (width, height, scaleMode) createEmptyTexture: function (width, height, scaleMode)
{ {
console.log('createEmptyTexture');
var gl = this.gl; var gl = this.gl;
var texture = gl.createTexture(); var texture = gl.createTexture();
var glScaleMode = (scaleMode === Phaser.scaleModes.LINEAR) ? gl.LINEAR : gl.NEAREST; var glScaleMode = (scaleMode === Phaser.scaleModes.LINEAR) ? gl.LINEAR : gl.NEAREST;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture); gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 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); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glScaleMode); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glScaleMode);