Heavily optimised PixiShader.

This commit is contained in:
photonstorm 2013-11-26 05:13:56 +00:00
parent 86584a636c
commit 141337bed9
11 changed files with 222 additions and 301 deletions

View file

@ -46,12 +46,12 @@ Version 1.1.3 - in build
* New: Added a new in-built texture. Sprites now use __default if no texture was provided (a 32x32 transparent PNG) or __missing if one was given but not found (a 32x32 black box with a green cross through it)
* New: Added Phaser.Filter. A new way to use the new WebGL shaders/filters that the new version of Pixi supports.
* New: The object returned by Math.sinCosGenerator now contains a length property.
* New: Phaser.BitmapData object. Can be used as a texture for a Sprite or Tiling Sprite. See the new examples and docs for details.
* New: Phaser.BitmapData object. A Canvas you can freely draw to with lots of functions. Can be used as a texture for Sprites. See the new examples and docs for details.
* New: RenderTexture.render now takes a Phaser.Group. Also added renderXY for when you don't want to make a new Point object.
* New: Implementing PluginManager.remove, added PluginManager.removeAll (thanks crazysam)
* New: Added scrollFactorX/scrollFactorY to TilemapLayers (thanks jcd-as)
* New: PluginManager.remove, added PluginManager.removeAll (thanks crazysam)
* New: scrollFactorX/scrollFactorY have been added to TilemapLayers (thanks jcd-as)
* New: Phaser.Game parent can now be an HTMLElement or a string (thanks beeglebug)
* New: Updated to use the latest version of Pixi.js - which means you can now use all the sexy new WebGL filters they added :)
* New: Now using the latest version of Pixi.js. Which means you can use all the sexy new WebGL filters :)
* New: Sprite.animations.getAnimation will return an animation instance which was added by name.
* New: Added Mouse.button which is set to the button that was pressed: Phaser.Mouse.LEFT_BUTTON, MIDDLE_BUTTON or RIGHT_BUTTON (thanks wKLV)
* New: Added Mouse.pointerLock signal which you can listen to whenever the browser enters or leaves pointer lock mode.
@ -64,6 +64,8 @@ Version 1.1.3 - in build
* New: Device.littleEndian boolean added. Only safe to use if the browser supports TypedArrays (which IE9 doesn't, but nearly all others do)
* New: You can now call game.sound.play() and simply pass it a key. The sound will play if the audio system is unlocked and optionally destroy itself on complete.
* New: Mouse.capture is a boolean. If set to true then DOM mouse events will have event.preventDefault() applied, if false they will propogate fully.
* New: Added Sound.externalNode which allows you to connect a Sound to an external node input rather than the SoundManager gain node.
* New: Added SoundManager.connectToMaster boolean. Used in conjunction with Sound.externalNode you can easily configure audio nodes to connect together for special effects.
* Fixed: Lots of fixes to the TypeScript definitions file (many thanks gltovar)
* Fixed: Tilemap commands use specified layer when one given (thanks Izzimach)
@ -77,6 +79,8 @@ Version 1.1.3 - in build
* Fixed: Fixes to Math and Loader (thanks theJare)
* Fixed: Tween - isRunning not reset when non-looped tween completes (thanks crazysam + kevinthompson)
* Fixed: Math.normalizeAngle and Math.wrapAngle (thanks theJare)
* Fixed: Device.isTouch modified to test maxTouchPointers instead of MSPointer.
* Fixed: InputHandler.checkPointerOver now checks the visible status of the Sprite Group before processing.
* Updated: ArcadePhysics.updateMotion applies the dt to the velocity calculations as well as position now (thanks jcs)
* Updated: RequestAnimationFrame now retains the callbackID which is passed to cancelRequestAnimationFrame.

View file

@ -28,23 +28,7 @@
<script src="$path/src/pixi/extras/Rope.js"></script>
<script src="$path/src/pixi/extras/TilingSprite.js"></script>
<script src="$path/src/pixi/filters/AbstractFilter.js"></script>
<script src="$path/src/pixi/filters/BlurFilter.js"></script>
<script src="$path/src/pixi/filters/BlurXFilter.js"></script>
<script src="$path/src/pixi/filters/BlurYFilter.js"></script>
<script src="$path/src/pixi/filters/ColorMatrixFilter.js"></script>
<script src="$path/src/pixi/filters/CrossHatchFilter.js"></script>
<script src="$path/src/pixi/filters/DisplacementFilter.js"></script>
<script src="$path/src/pixi/filters/DotScreenFilter.js"></script>
<script src="$path/src/pixi/filters/FilterBlock.js"></script>
<script src="$path/src/pixi/filters/GrayFilter.js"></script>
<script src="$path/src/pixi/filters/InvertFilter.js"></script>
<script src="$path/src/pixi/filters/PixelateFilter.js"></script>
<script src="$path/src/pixi/filters/RGBSplitFilter.js"></script>
<script src="$path/src/pixi/filters/SepiaFilter.js"></script>
<script src="$path/src/pixi/filters/SmartBlurFilter.js"></script>
<script src="$path/src/pixi/filters/TwistFilter.js"></script>
<script src="$path/src/pixi/primitives/Graphics.js"></script>
<script src="$path/src/pixi/renderers/canvas/CanvasGraphics.js"></script>

View file

@ -8,7 +8,7 @@ Phaser.Filter.Tunnel = function (game) {
this.uniforms.alpha = { type: '1f', value: 1 }
this.uniforms.origin = { type: '1f', value: 2.0 }
this.uniforms.iChannel0 = { type: 'sampler2D', value: null, wrap: 'repeat' }
this.uniforms.iChannel0 = { type: 'sampler2D', value: null, repeat: true }
this.fragmentSrc = [

View file

@ -1190,15 +1190,25 @@ Phaser.Group.prototype = {
*
* @method Phaser.Group#remove
* @param {Any} child - The child to remove.
* @return {boolean} true if the child was removed from this Group, otherwise false.
*/
remove: function (child) {
if (child.group !== this)
{
return false;
}
if (child.events)
{
child.events.onRemovedFromGroup.dispatch(child, this);
}
this._container.removeChild(child);
// Check it's actually in the container
if (child.parent === this._container)
{
this._container.removeChild(child);
}
if (this.cursor == child)
{
@ -1214,6 +1224,8 @@ Phaser.Group.prototype = {
child.group = null;
return true;
},
/**

View file

@ -104,13 +104,14 @@ Phaser.GameObjectFactory.prototype = {
*
* @method Phaser.GameObjectFactory#audio
* @param {string} key - The Game.cache key of the sound that this object will use.
* @param {number} volume - The volume at which the sound will be played.
* @param {boolean} loop - Whether or not the sound will loop.
* @param {number} [volume=1] - The volume at which the sound will be played.
* @param {boolean} [loop=false] - Whether or not the sound will loop.
* @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
* @return {Phaser.Sound} The newly created text object.
*/
audio: function (key, volume, loop) {
audio: function (key, volume, loop, connect) {
return this.game.sound.add(key, volume, loop);
return this.game.sound.add(key, volume, loop, connect);
},

View file

@ -510,24 +510,24 @@ Phaser.InputHandler.prototype = {
*/
checkPointerOver: function (pointer) {
if (this.enabled && this.sprite.visible)
if (this.enabled === false || this.sprite.visible === false || (this.sprite.group && this.sprite.group.visible === false))
{
this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y);
if (this._tempPoint.x >= 0 && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= 0 && this._tempPoint.y <= this.sprite.currentFrame.height)
{
if (this.pixelPerfect)
{
return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
}
else
{
return true;
}
}
return false;
}
return false;
this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y);
if (this._tempPoint.x >= 0 && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= 0 && this._tempPoint.y <= this.sprite.currentFrame.height)
{
if (this.pixelPerfect)
{
return this.checkPixel(this._tempPoint.x, this._tempPoint.y);
}
else
{
return true;
}
}
},

View file

@ -31,8 +31,10 @@ PIXI.PixiShader = function()
* @property {number} textureCount - A local texture counter for multi-texture shaders.
*/
this.textureCount = 0;
// this.dirty = true;
}
};
/**
* @method PIXI.PixiShader#init
@ -49,7 +51,7 @@ PIXI.PixiShader.prototype.init = function()
this.uSampler = gl.getUniformLocation(program, "uSampler");
this.projectionVector = gl.getUniformLocation(program, "projectionVector");
this.offsetVector = gl.getUniformLocation(program, "offsetVector");
// this.dimensions = gl.getUniformLocation(program, "dimensions");
this.dimensions = gl.getUniformLocation(program, "dimensions");
// get and store the attributes
this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
@ -62,189 +64,80 @@ PIXI.PixiShader.prototype.init = function()
// get the uniform locations..
this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key);
}
this.initUniforms();
this.program = program;
}
};
/**
* Updates the shader uniform values.
* Initialises the shader uniform values.
* Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/
* http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf
*
* @method PIXI.PixiShader#syncUniforms
* @method PIXI.PixiShader#initUniforms
*/
PIXI.PixiShader.prototype.syncUniforms = function()
PIXI.PixiShader.prototype.initUniforms = function()
{
this.textureCount = 1;
var gl = PIXI.gl;
var uniform;
for (var key in this.uniforms)
{
var type = this.uniforms[key].type;
var transpose = false;
var uniform = this.uniforms[key];
var type = uniform.type;
if (this.uniforms[key].transpose)
if (type == 'sampler2D')
{
transpose = this.uniforms[key].transpose;
}
if (type == "1f")
{
// void uniform1f(WebGLUniformLocation? location, GLfloat x);
gl.uniform1f(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "1fv")
{
// void uniform1fv(WebGLUniformLocation? location, Float32Array v);
// void uniform1fv(WebGLUniformLocation? location, sequence<GLfloat> v);
gl.uniform1fv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "1i")
{
// void uniform1i(WebGLUniformLocation? location, GLint x);
gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "1iv")
{
// void uniform1iv(WebGLUniformLocation? location, Int32Array v);
// void uniform1iv(WebGLUniformLocation? location, sequence<long> v);
gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "2f")
{
// void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y);
gl.uniform2f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y);
}
else if (type == "2fv")
{
// void uniform2fv(WebGLUniformLocation? location, Float32Array v);
// void uniform2fv(WebGLUniformLocation? location, sequence<GLfloat> v);
gl.uniform2fv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "2i")
{
// void uniform2i(WebGLUniformLocation? location, GLint x, GLint y);
gl.uniform2i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y);
}
else if (type == "2iv")
{
// void uniform2iv(WebGLUniformLocation? location, Int32Array v);
// void uniform2iv(WebGLUniformLocation? location, sequence<long> v);
gl.uniform2iv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "3f")
{
// void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z);
gl.uniform3f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z);
}
else if (type == "3fv")
{
// void uniform3fv(WebGLUniformLocation? location, Float32Array v);
// void uniform3fv(WebGLUniformLocation? location, sequence<GLfloat> v);
gl.uniform3fv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "3i")
{
// void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z);
gl.uniform3i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z);
}
else if (type == "3iv")
{
// void uniform3iv(WebGLUniformLocation? location, Int32Array v);
// void uniform3iv(WebGLUniformLocation? location, sequence<long> v);
gl.uniform3iv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "4f")
{
// void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
gl.uniform4f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w);
}
else if (type == "4fv")
{
// void uniform4fv(WebGLUniformLocation? location, Float32Array v);
// void uniform4fv(WebGLUniformLocation? location, sequence<GLfloat> v);
gl.uniform4fv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "4i")
{
// void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w);
gl.uniform4i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w);
}
else if (type == "4iv")
{
// void uniform4iv(WebGLUniformLocation? location, Int32Array v);
// void uniform4iv(WebGLUniformLocation? location, sequence<long> v);
gl.uniform4iv(this.uniforms[key].uniformLocation, this.uniforms[key].value);
}
else if (type == "mat2")
{
// void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value);
// void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, sequence<GLfloat> value);
gl.uniformMatrix2fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value);
}
else if (type == "mat3")
{
// void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value);
// void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, sequence<GLfloat> value);
gl.uniformMatrix3fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value);
}
else if (type == "mat4")
{
// void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value);
// void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, sequence<GLfloat> value);
gl.uniformMatrix4fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value);
}
else if (type == "sampler2D")
{
if (this.uniforms[key].value && this.uniforms[key].value.baseTexture.hasLoaded)
if (uniform.value && uniform.value.baseTexture.hasLoaded)
{
var texture = this.uniforms[key].value.baseTexture._glTexture;
var image = this.uniforms[key].value.baseTexture.source;
var format = gl.RGBA;
this.initSampler2D(uniform);
}
else
{
uniform._init = false;
}
}
else if (type == 'mat2' || type == 'mat3' || type == 'mat4')
{
// These require special handling
uniform.glMatrix = true;
uniform.glValueLength = 1;
if (this.uniforms[key].format && this.uniforms[key].format == 'luminance')
{
format = gl.LUMINANCE;
}
if (type == 'mat2')
{
uniform.glFunc = PIXI.gl.uniformMatrix2fv;
}
else if (type == 'mat3')
{
uniform.glFunc = PIXI.gl.uniformMatrix3fv;
}
else if (type == 'mat4')
{
uniform.glFunc = PIXI.gl.uniformMatrix4fv;
}
}
else
{
// GL function reference
uniform.glFunc = PIXI.gl['uniform' + type];
gl.activeTexture(gl['TEXTURE' + this.textureCount]);
if (this.uniforms[key].wrap)
{
if (this.uniforms[key].wrap == 'no-repeat' || this.uniforms[key].wrap === false)
{
this.createGLTextureLinear(gl, image, texture);
}
else if (this.uniforms[key].wrap == 'repeat' || this.uniforms[key].wrap === true)
{
this.createGLTexture(gl, image, format, texture);
}
else if (this.uniforms[key].wrap == 'nearest-repeat')
{
this.createGLTextureNearestRepeat(gl, image, texture);
}
else if (this.uniforms[key].wrap == 'nearest')
{
this.createGLTextureNearest(gl, image, texture);
}
else if (this.uniforms[key].wrap == 'audio')
{
this.createAudioTexture(gl, texture);
}
else if (this.uniforms[key].wrap == 'keyboard')
{
this.createKeyboardTexture(gl, texture);
}
}
else
{
this.createGLTextureLinear(gl, image, texture);
}
gl.uniform1i(this.uniforms[key].uniformLocation, this.textureCount);
this.textureCount++;
if (type == '2f' || type == '2i')
{
uniform.glValueLength = 2;
}
else if (type == '3f' || type == '3i')
{
uniform.glValueLength = 3;
}
else if (type == '4f' || type == '4i')
{
uniform.glValueLength = 4;
}
else
{
uniform.glValueLength = 1;
}
}
}
@ -252,99 +145,100 @@ PIXI.PixiShader.prototype.syncUniforms = function()
};
/**
* Binds the given texture and image data. The texture is set to REPEAT.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createGLTexture
* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture is has loaded)
*
* @method PIXI.PixiShader#initSampler2D
*/
PIXI.PixiShader.prototype.createGLTexture = function(gl, image, format, texture)
PIXI.PixiShader.prototype.initSampler2D = function(uniform)
{
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.generateMipmap(gl.TEXTURE_2D);
}
if (uniform.value && uniform.value.baseTexture.hasLoaded)
{
// GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D);
// GLTextureLinear = mag/min linear, wrap clamp
// GLTextureNearestRepeat = mag/min NEAREST, wrap repeat
// GLTextureNearest = mag/min nearest, wrap clamp
// AudioTexture = whatever + luminance
// magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST
// wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT
var magFilter = (uniform.magFilter) ? uniform.magFilter : PIXI.gl.LINEAR;
var minFilter = (uniform.minFilter) ? uniform.minFilter : PIXI.gl.LINEAR;
var wrapS = (uniform.wrapS) ? uniform.wrapS : PIXI.gl.CLAMP_TO_EDGE;
var wrapT = (uniform.wrapT) ? uniform.wrapT : PIXI.gl.CLAMP_TO_EDGE;
var format = (uniform.luminance) ? PIXI.gl.LUMINANCE : PIXI.gl.RGBA;
if (uniform.repeat)
{
wrapS = PIXI.gl.REPEAT;
wrapT = PIXI.gl.REPEAT;
}
PIXI.gl.activeTexture(PIXI.gl['TEXTURE' + this.textureCount]);
PIXI.gl.bindTexture(PIXI.gl.TEXTURE_2D, uniform.value.baseTexture._glTexture);
PIXI.gl.pixelStorei(PIXI.gl.UNPACK_FLIP_Y_WEBGL, false);
PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, format, PIXI.gl.RGBA, PIXI.gl.UNSIGNED_BYTE, uniform.value.baseTexture.source);
// PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, PIXI.gl.LUMINANCE, 512, 2, 0, PIXI.gl.LUMINANCE, PIXI.gl.UNSIGNED_BYTE, null);
// PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, PIXI.gl.LUMINANCE, 256, 2, 0, PIXI.gl.LUMINANCE, PIXI.gl.UNSIGNED_BYTE, null);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MAG_FILTER, magFilter);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MIN_FILTER, minFilter);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_S, wrapS);
PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_T, wrapT);
PIXI.gl.uniform1i(uniform.uniformLocation, this.textureCount);
uniform._init = true;
this.textureCount++;
}
};
/**
* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createGLTextureLinear
* Updates the shader uniform values.
*
* @method PIXI.PixiShader#syncUniforms
*/
PIXI.PixiShader.prototype.createGLTextureLinear = function(gl, image, texture)
PIXI.PixiShader.prototype.syncUniforms = function()
{
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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);
}
var uniform;
/**
* Binds the given texture and image data. The texture is set to REPEAT with NEAREST.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createGLTextureNearestRepeat
*/
PIXI.PixiShader.prototype.createGLTextureNearestRepeat = function(gl, image, texture)
{
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
}
// This would probably be faster in an array and it would guarantee key order
for (var key in this.uniforms)
{
uniform = this.uniforms[key];
/**
* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE with NEAREST.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createGLTextureNearest
*/
PIXI.PixiShader.prototype.createGLTextureNearest = function(gl, image, texture)
{
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
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);
}
/**
* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with real-time audio data.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createAudioTexture
*/
PIXI.PixiShader.prototype.createAudioTexture = function(gl, texture)
{
gl.bindTexture(gl.TEXTURE_2D, texture );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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) ;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 512, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null);
}
/**
* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with keyboard input data.
* Code based on Effects.js from ShaderToy.com
* @method PIXI.PixiShader#createKeyboardTexture
*/
PIXI.PixiShader.prototype.createKeyboardTexture = function(gl, texture)
{
gl.bindTexture(gl.TEXTURE_2D, texture );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
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.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 256, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null);
}
if (uniform.glValueLength == 1)
{
if (uniform.glMatrix === true)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.transpose, uniform.value);
}
else
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value);
}
}
else if (uniform.glValueLength == 2)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y);
}
else if (uniform.glValueLength == 3)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z);
}
else if (uniform.glValueLength == 4)
{
uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w);
}
else if (uniform.type == 'sampler2D' && uniform._init == false && uniform.value && uniform.value.baseTexture.hasLoaded === false)
{
this.initSampler2D(uniform);
}
}
};
PIXI.PixiShader.defaultVertexSrc = [

View file

@ -15,10 +15,11 @@
* @param {number} [volume=1] - Default value for the volume, between 0 and 1.
* @param {boolean} [loop=false] - Whether or not the sound will loop.
*/
Phaser.Sound = function (game, key, volume, loop) {
Phaser.Sound = function (game, key, volume, loop, connect) {
if (typeof volume == 'undefined') { volume = 1; }
if (typeof loop == 'undefined') { loop = false; }
if (typeof connect === 'undefined') { connect = game.sound.connectToMaster; }
/**
* A reference to the currently running Game.
@ -152,6 +153,11 @@ Phaser.Sound = function (game, key, volume, loop) {
*/
this.usingAudioTag = this.game.sound.usingAudioTag;
/**
* @property {object} externalNode - If defined this Sound won't connect to the SoundManager master gain node, but will instead connect to externalNode.input.
*/
this.externalNode = null;
if (this.usingWebAudio)
{
this.context = this.game.sound.context;
@ -167,7 +173,11 @@ Phaser.Sound = function (game, key, volume, loop) {
}
this.gainNode.gain.value = volume * this.game.sound.volume;
this.gainNode.connect(this.masterGainNode);
if (connect)
{
this.gainNode.connect(this.masterGainNode);
}
}
else
{
@ -477,7 +487,16 @@ Phaser.Sound.prototype = {
this._sound = this.context.createBufferSource();
this._sound.buffer = this._buffer;
this._sound.connect(this.gainNode);
if (this.externalNode)
{
this._sound.connect(this.externalNode.input);
}
else
{
this._sound.connect(this.gainNode);
}
this.totalDuration = this._sound.buffer.duration;
if (this.duration === 0)

View file

@ -78,6 +78,12 @@ Phaser.SoundManager = function (game) {
*/
this.noAudio = false;
/**
* @property {boolean} connectToMaster - Used in conjunction with Sound.externalNode this allows you to stop a Sound node being connected to the SoundManager master gain node.
* @default
*/
this.connectToMaster = true;
/**
* @property {boolean} touchLocked - true if the audio system is currently locked awaiting a touch event.
* @default
@ -174,7 +180,6 @@ Phaser.SoundManager.prototype = {
this.masterGain.connect(this.context.destination);
}
},
/**
@ -324,14 +329,16 @@ Phaser.SoundManager.prototype = {
* @param {string} key - Asset key for the sound.
* @param {number} [volume=1] - Default value for the volume.
* @param {boolean} [loop=false] - Whether or not the sound will loop.
* @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio.
* @return {Phaser.Sound} The new sound instance.
*/
add: function (key, volume, loop) {
add: function (key, volume, loop, connect) {
if (typeof volume === 'undefined') { volume = 1; }
if (typeof loop === 'undefined') { loop = false; }
if (typeof connect === 'undefined') { connect = this.connectToMaster; }
var sound = new Phaser.Sound(this.game, key, volume, loop);
var sound = new Phaser.Sound(this.game, key, volume, loop, connect);
this._sounds.push(sound);

View file

@ -354,11 +354,11 @@ Phaser.Device.prototype = {
this.worker = !!window['Worker'];
if ('ontouchstart' in document.documentElement || window.navigator.msPointerEnabled) {
if ('ontouchstart' in document.documentElement || (window.navigator.maxTouchPoints && window.navigator.maxTouchPoints > 1)) {
this.touch = true;
}
if (window.navigator.msPointerEnabled) {
if (window.navigator.msPointerEnabled || window.navigator.pointerEnabled) {
this.mspointer = true;
}

View file

@ -307,7 +307,7 @@ Phaser.Utils.Debug.prototype = {
/**
* Renders the Pointer.circle object onto the stage in green if down or red if up along with debug text.
* @method Phaser.Utils.Debug#renderDebug
* @method Phaser.Utils.Debug#renderPointer
* @param {Phaser.Pointer} pointer - Description.
* @param {boolean} [hideIfUp=false] - Doesn't render the circle if the pointer is up.
* @param {string} [downColor='rgba(0,255,0,0.5)'] - The color the circle is rendered in if down.