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 verts = src.transform.glVertextData;
var index = src.glTextureIndex;
var index = src.frame.source.glTextureIndex;
var tint = src.color._glTint;
var bg = src.color._glBg;

View file

@ -85,7 +85,6 @@ Phaser.Renderer.WebGL.BatchManager = function (renderer, batchSize)
'void main(void) {',
' 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);',
' vTextureCoord = aTextureCoord;', // pass the texture coordinate to the fragment shader, the GPU will interpolate the points
' vTintColor = vec4(aTintColor.rgb * aTintColor.a, aTintColor.a);',
@ -109,16 +108,15 @@ Phaser.Renderer.WebGL.BatchManager = function (renderer, batchSize)
'uniform sampler2D uSampler;', // our texture
'const vec4 PINK = vec4(1.0, 0.0, 1.0, 1.0);',
'void main(void) {',
' 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 = PINK;', // if texture alpha is zero, use the bg color
' gl_FragColor = pixel;',
'}'
];
this.multiTextureFragmentSrc = null;
// @type {GLint}
this.aVertexPosition;
@ -197,11 +195,6 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.indices[i + 5] = j + 3; // Bottom Left
}
if (this.renderer.enableMultiTextureToggle)
{
// this.initMultitexShader();
}
var gl = this.gl;
// Create indices buffer
@ -222,8 +215,51 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
// Set the source of the buffer data (this.vertices array)
gl.bufferData(gl.ARRAY_BUFFER, this.vertices, gl.DYNAMIC_DRAW);
// initShader
var program = this.renderer.compileProgram(this.vertexSrc, this.fragmentSrc);
var fragmentSrc = 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
gl.useProgram(program);
@ -248,7 +284,32 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
// Get and store the uniforms for the shader
// 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');
}
// The projection vector (middle of the game world)
this.projectionVector = gl.getUniformLocation(program, 'projectionVector');
@ -259,64 +320,6 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
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 ()
{
this._i = 0;
@ -349,27 +352,47 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
setCurrentTexture: function (textureSource)
{
if (this.currentTextureSource === textureSource)
{
return;
}
var gl = this.gl;
// 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)
{
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.bindTexture(gl.TEXTURE_2D, textureSource.glTexture);
this.currentTextureSource = textureSource;
// this.renderer.textureArray[textureSource.glTextureIndex] = textureSource;
}
},
// Call 'addVert' x4 after calling this
@ -424,10 +447,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
}
// Set texture
if (this.currentTextureSource !== gameObject.frame.source)
{
this.setCurrentTexture(gameObject.frame.source);
}
// These are TypedArray Views into the vertices ArrayBuffer
var colors = this.colors;
@ -476,7 +496,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.list[this.currentBatchSize++] = gameObject;
},
prepShader: function ()
initShader: function ()
{
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
if (this.dirty)
{
this.prepShader();
this.initShader();
}
var gl = this.gl;
@ -559,7 +579,7 @@ Phaser.Renderer.WebGL.BatchManager.prototype = {
this.renderer.setBlendMode(sprite.blendMode);
}
if (this.currentTextureSource !== sprite.frame.source)
if (!this.renderer.multiTexture && this.currentTextureSource !== sprite.frame.source)
{
if (currentSize > 0)
{

View file

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