New Filter Structure
Base Filters now working for graphics and sprite Filters now nestable
This commit is contained in:
parent
e50a6716d8
commit
46ae15a6ce
13 changed files with 684 additions and 63 deletions
|
@ -39,6 +39,8 @@ module.exports = function(grunt) {
|
|||
'<%= dirs.src %>/renderers/webgl/WebGLRenderer.js',
|
||||
'<%= dirs.src %>/renderers/webgl/WebGLBatch.js',
|
||||
'<%= dirs.src %>/renderers/webgl/WebGLRenderGroup.js',
|
||||
'<%= dirs.src %>/renderers/webgl/filters/FilterManager.js',
|
||||
'<%= dirs.src %>/renderers/webgl/filters/Filter.js',
|
||||
'<%= dirs.src %>/renderers/canvas/CanvasRenderer.js',
|
||||
'<%= dirs.src %>/renderers/canvas/CanvasGraphics.js',
|
||||
'<%= dirs.src %>/primitives/Graphics.js',
|
||||
|
|
|
@ -164,6 +164,9 @@ PIXI.DisplayObject = function()
|
|||
this._sr = 0;
|
||||
this._cr = 1;
|
||||
|
||||
|
||||
this.filterArea = new PIXI.Rectangle(0,0,1,1);
|
||||
|
||||
/*
|
||||
* MOUSE Callbacks
|
||||
*/
|
||||
|
@ -353,6 +356,7 @@ PIXI.DisplayObject.prototype.addFilter = function(data)
|
|||
{
|
||||
//if(this.filter)return;
|
||||
//this.filter = true;
|
||||
// data[0].target = this;
|
||||
|
||||
// insert a filter block..
|
||||
// TODO Onject pool thease bad boys..
|
||||
|
@ -370,6 +374,8 @@ PIXI.DisplayObject.prototype.addFilter = function(data)
|
|||
|
||||
start.open = true;
|
||||
|
||||
start.target = this;
|
||||
|
||||
/*
|
||||
* insert start
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,7 @@ PIXI.DisplacementFilter = function(texture)
|
|||
"uniform sampler2D uSampler;",
|
||||
"uniform vec2 scale;",
|
||||
"uniform vec2 mapDimensions;",// = vec2(256.0, 256.0);",
|
||||
"const vec2 textureDimensions = vec2(245.0, 263.0);",
|
||||
"const vec2 textureDimensions = vec2(800.0, 600.0);",
|
||||
|
||||
"void main(void) {",
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ PIXI.InvertFilter = function()
|
|||
{
|
||||
// set the uniforms
|
||||
this.uniforms = {
|
||||
invert: {type: 'f', value: 0.5},
|
||||
invert: {type: 'f', value: 0},
|
||||
};
|
||||
|
||||
this.fragmentSrc = [
|
||||
|
|
|
@ -221,6 +221,81 @@ PIXI.Graphics.prototype.clear = function()
|
|||
this.dirty = true;
|
||||
this.clearDirty = true;
|
||||
this.graphicsData = [];
|
||||
|
||||
this.bounds = null//new PIXI.Rectangle();
|
||||
}
|
||||
|
||||
|
||||
PIXI.Graphics.prototype.updateFilterBounds = function()
|
||||
{
|
||||
if(!this.bounds)
|
||||
{
|
||||
var minX = Infinity;
|
||||
var maxX = -Infinity;
|
||||
|
||||
var minY = Infinity;
|
||||
var maxY = -Infinity;
|
||||
|
||||
var points, x, y;
|
||||
|
||||
for (var i = 0; i < this.graphicsData.length; i++) {
|
||||
|
||||
|
||||
var data = this.graphicsData[i];
|
||||
var type = data.type;
|
||||
var lineWidth = data.lineWidth;
|
||||
|
||||
points = data.points;
|
||||
|
||||
if(type === PIXI.Graphics.RECT)
|
||||
{
|
||||
x = points.x - lineWidth/2;
|
||||
y = points.y - lineWidth/2;
|
||||
var width = points.width + lineWidth;
|
||||
var height = points.height + lineWidth;
|
||||
|
||||
minX = x < minX ? x : minX;
|
||||
maxX = x + width > maxX ? x + width : maxX;
|
||||
|
||||
minY = y < minY ? x : minY;
|
||||
maxY = y + height > maxY ? y + height : maxY;
|
||||
}
|
||||
else if(type === PIXI.Graphics.CIRC || type === PIXI.Graphics.ELIP)
|
||||
{
|
||||
x = points.x;
|
||||
y = points.y;
|
||||
var radius = points.radius + lineWidth/2;
|
||||
|
||||
minX = x - radius < minX ? x - radius : minX;
|
||||
maxX = x + radius > maxX ? x + radius : maxX;
|
||||
|
||||
minY = y - radius < minY ? y - radius : minY;
|
||||
maxY = y + radius > maxY ? y + radius : maxY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// POLY
|
||||
for (var j = 0; j < points.length; j+=2)
|
||||
{
|
||||
|
||||
x = points[j];
|
||||
y = points[j+1];
|
||||
|
||||
minX = x-lineWidth < minX ? x-lineWidth : minX;
|
||||
maxX = x+lineWidth > maxX ? x+lineWidth : maxX;
|
||||
|
||||
minY = y-lineWidth < minY ? y-lineWidth : minY;
|
||||
maxY = y+lineWidth > maxY ? y+lineWidth : maxY;
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.bounds = new PIXI.Rectangle(minX, minY, maxX - minX, maxY - minY);
|
||||
|
||||
}
|
||||
|
||||
// console.log(this.bounds);
|
||||
}
|
||||
|
||||
// SOME TYPES:
|
||||
|
|
|
@ -28,6 +28,16 @@ PIXI.PixiShader.prototype.init = function()
|
|||
|
||||
gl.useProgram(program);
|
||||
|
||||
// get and store the uniforms for the shader
|
||||
this.uSampler = gl.getUniformLocation(program, "uSampler");
|
||||
this.projectionVector = gl.getUniformLocation(program, "projectionVector");
|
||||
this.offsetVector = gl.getUniformLocation(program, "offsetVector");
|
||||
//this.dimensions = gl.getUniformLocation(this.program, "dimensions");
|
||||
|
||||
// get and store the attributes
|
||||
this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
|
||||
this.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord");
|
||||
|
||||
// get the default shader bits!
|
||||
program.vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition");
|
||||
program.colorAttribute = gl.getAttribLocation(program, "aColor");
|
||||
|
@ -35,6 +45,7 @@ PIXI.PixiShader.prototype.init = function()
|
|||
|
||||
program.projectionVector = gl.getUniformLocation(program, "projectionVector");
|
||||
program.samplerUniform = gl.getUniformLocation(program, "uSampler");
|
||||
program.offsetVector = gl.getUniformLocation(program, "offsetVector");
|
||||
|
||||
// add those custom shaders!
|
||||
for (var key in this.uniforms)
|
||||
|
@ -78,7 +89,6 @@ PIXI.PixiShader.prototype.syncUniforms = function()
|
|||
|
||||
gl.uniform1i(this.program[key], 1);
|
||||
|
||||
|
||||
// activate texture..
|
||||
// gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value);
|
||||
// gl.uniformMatrix4fv(this.program[key], false, this.uniforms[key].value);
|
||||
|
|
|
@ -46,7 +46,6 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
|
|||
PIXI.WebGLGraphics.updateGraphics(graphics);
|
||||
}
|
||||
|
||||
|
||||
PIXI.activatePrimitiveShader();
|
||||
|
||||
// This could be speeded up fo sure!
|
||||
|
@ -59,7 +58,8 @@ PIXI.WebGLGraphics.renderGraphics = function(graphics, projection)
|
|||
|
||||
gl.uniformMatrix3fv(PIXI.primitiveProgram.translationMatrix, false, m);
|
||||
|
||||
gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, projection.y);
|
||||
gl.uniform2f(PIXI.primitiveProgram.projectionVector, projection.x, -projection.y);
|
||||
gl.uniform2f(PIXI.primitiveProgram.offsetVector, -PIXI.offset.x, -PIXI.offset.y);
|
||||
|
||||
gl.uniform1f(PIXI.primitiveProgram.alpha, graphics.worldAlpha);
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ PIXI.WebGLRenderGroup = function(gl)
|
|||
this.backgroundColor;
|
||||
this.batchs = [];
|
||||
this.toRemove = [];
|
||||
|
||||
this.filterManager = new PIXI.FilterManager();
|
||||
}
|
||||
|
||||
// constructor
|
||||
|
@ -56,17 +58,20 @@ PIXI.WebGLRenderGroup.prototype.setRenderable = function(displayObject)
|
|||
* @method render
|
||||
* @param projection {Object}
|
||||
*/
|
||||
PIXI.WebGLRenderGroup.prototype.render = function(projection)
|
||||
PIXI.WebGLRenderGroup.prototype.render = function(projection, buffer)
|
||||
{
|
||||
PIXI.WebGLRenderer.updateTextures();
|
||||
|
||||
var gl = this.gl;
|
||||
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y);
|
||||
|
||||
this.filterManager.begin(projection, buffer);
|
||||
|
||||
|
||||
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
||||
// will render all the elements in the group
|
||||
var renderable;
|
||||
|
||||
for (var i=0; i < this.batchs.length; i++)
|
||||
{
|
||||
|
||||
|
@ -77,25 +82,8 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection)
|
|||
continue;
|
||||
}
|
||||
|
||||
// non sprite batch..
|
||||
var worldVisible = renderable.vcount === PIXI.visibleCount;
|
||||
|
||||
if(renderable instanceof PIXI.TilingSprite)
|
||||
{
|
||||
if(worldVisible)this.renderTilingSprite(renderable, projection);
|
||||
}
|
||||
else if(renderable instanceof PIXI.Strip)
|
||||
{
|
||||
if(worldVisible)this.renderStrip(renderable, projection);
|
||||
}
|
||||
else if(renderable instanceof PIXI.Graphics)
|
||||
{
|
||||
if(worldVisible && renderable.renderable) PIXI.WebGLGraphics.renderGraphics(renderable, projection);//, projectionMatrix);
|
||||
}
|
||||
else if(renderable instanceof PIXI.FilterBlock)
|
||||
{
|
||||
this.handleFilterBlock(renderable, projection);
|
||||
}
|
||||
// render special
|
||||
this.renderSpecial(renderable, projection);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,7 +96,7 @@ PIXI.WebGLRenderGroup.prototype.render = function(projection)
|
|||
* @param projection {Object}
|
||||
* @private
|
||||
*/
|
||||
PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection)
|
||||
PIXI.WebGLRenderGroup.prototype.renderSpecific = function(displayObject, projection, buffer)
|
||||
{
|
||||
PIXI.WebGLRenderer.updateTextures();
|
||||
|
||||
|
@ -293,41 +281,32 @@ PIXI.WebGLRenderGroup.prototype.renderSpecial = function(renderable, projection)
|
|||
}
|
||||
}
|
||||
|
||||
PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, projection)
|
||||
PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(filterBlock, projection)
|
||||
{
|
||||
/*
|
||||
* for now only masks are supported..
|
||||
*/
|
||||
var gl = PIXI.gl;
|
||||
|
||||
if(renderable.open)
|
||||
|
||||
if(filterBlock.open)
|
||||
{
|
||||
if(renderable.data instanceof Array)
|
||||
if(filterBlock.data instanceof Array)
|
||||
{
|
||||
var filter = renderable.data[0];
|
||||
var filter = filterBlock.data[0];
|
||||
//console.log(filter)
|
||||
this.filterManager.pushFilter(filterBlock);//filter);
|
||||
// ok so..
|
||||
|
||||
if(!filter.shader)
|
||||
{
|
||||
var shader = new PIXI.PixiShader();
|
||||
|
||||
shader.fragmentSrc = filter.fragmentSrc;
|
||||
shader.uniforms = filter.uniforms;
|
||||
shader.init();
|
||||
|
||||
filter.shader = shader
|
||||
}
|
||||
|
||||
PIXI.pushShader(filter.shader);
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
gl.enable(gl.STENCIL_TEST);
|
||||
|
||||
gl.colorMask(false, false, false, false);
|
||||
gl.stencilFunc(gl.ALWAYS,1,0xff);
|
||||
gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE);
|
||||
PIXI.WebGLGraphics.renderGraphics(renderable.data, projection);
|
||||
PIXI.WebGLGraphics.renderGraphics(filterBlock.data, projection);
|
||||
|
||||
gl.colorMask(true, true, true, true);
|
||||
gl.stencilFunc(gl.NOTEQUAL,0,0xff);
|
||||
|
@ -336,10 +315,11 @@ PIXI.WebGLRenderGroup.prototype.handleFilterBlock = function(renderable, project
|
|||
}
|
||||
else
|
||||
{
|
||||
if(renderable.data instanceof Array)
|
||||
if(filterBlock.data instanceof Array)
|
||||
{
|
||||
PIXI.popShader();
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y);
|
||||
this.filterManager.popFilter();
|
||||
// PIXI.popShader();
|
||||
// gl.uniform2f(PIXI.currentShader.projectionVector, projection.x, projection.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -68,6 +68,8 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
|
|||
PIXI.initDefaultStripShader();
|
||||
|
||||
|
||||
|
||||
|
||||
// PIXI.activateDefaultShader();
|
||||
|
||||
var gl = this.gl;
|
||||
|
@ -81,6 +83,9 @@ PIXI.WebGLRenderer = function(width, height, view, transparent, antialias)
|
|||
gl.colorMask(true, true, true, this.transparent);
|
||||
|
||||
PIXI.projection = new PIXI.Point(400, 300);
|
||||
PIXI.offset = new PIXI.Point(0, 0);
|
||||
|
||||
// TODO remove thease globals..
|
||||
|
||||
this.resize(this.width, this.height);
|
||||
this.contextLost = false;
|
||||
|
@ -178,6 +183,10 @@ PIXI.WebGLRenderer.prototype.render = function(stage)
|
|||
// HACK TO TEST
|
||||
|
||||
this.stageRenderGroup.backgroundColor = stage.backgroundColorSplit;
|
||||
|
||||
PIXI.projection.x = this.width/2;
|
||||
PIXI.projection.y = -this.height/2;
|
||||
|
||||
this.stageRenderGroup.render(PIXI.projection);
|
||||
|
||||
// interaction
|
||||
|
@ -303,7 +312,10 @@ PIXI.WebGLRenderer.prototype.resize = function(width, height)
|
|||
//var projectionMatrix = this.projectionMatrix;
|
||||
|
||||
PIXI.projection.x = this.width/2;
|
||||
PIXI.projection.y = this.height/2;
|
||||
PIXI.projection.y = -this.height/2;
|
||||
|
||||
//PIXI.size.x = this.width/2;
|
||||
//PIXI.size.y = -this.height/2;
|
||||
|
||||
// projectionMatrix[0] = 2/this.width;
|
||||
// projectionMatrix[5] = -2/this.height;
|
||||
|
|
|
@ -24,10 +24,14 @@ PIXI.shaderVertexSrc = [
|
|||
"attribute float aColor;",
|
||||
|
||||
"uniform vec2 projectionVector;",
|
||||
"uniform vec2 offsetVector;",
|
||||
"varying vec2 vTextureCoord;",
|
||||
|
||||
"varying float vColor;",
|
||||
//"const vec2 offsetVector = vec2(1000.0, 0.0);",
|
||||
"const vec2 center = vec2(-1.0, 1.0);",
|
||||
"void main(void) {",
|
||||
"gl_Position = vec4( aVertexPosition.x / projectionVector.x -1.0, aVertexPosition.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
|
||||
"gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);",
|
||||
"vTextureCoord = aTextureCoord;",
|
||||
"vColor = aColor;",
|
||||
"}"
|
||||
|
@ -83,10 +87,12 @@ PIXI.primitiveShaderVertexSrc = [
|
|||
"attribute vec4 aColor;",
|
||||
"uniform mat3 translationMatrix;",
|
||||
"uniform vec2 projectionVector;",
|
||||
"uniform vec2 offsetVector;",
|
||||
"uniform float alpha;",
|
||||
"varying vec4 vColor;",
|
||||
"void main(void) {",
|
||||
"vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);",
|
||||
"vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);",
|
||||
"v -= offsetVector.xyx;",
|
||||
"gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);",
|
||||
"vColor = aColor * alpha;",
|
||||
"}"
|
||||
|
@ -106,6 +112,8 @@ PIXI.initPrimitiveShader = function()
|
|||
shaderProgram.colorAttribute = gl.getAttribLocation(shaderProgram, "aColor");
|
||||
|
||||
shaderProgram.projectionVector = gl.getUniformLocation(shaderProgram, "projectionVector");
|
||||
shaderProgram.offsetVector = gl.getUniformLocation(shaderProgram, "offsetVector");
|
||||
|
||||
shaderProgram.translationMatrix = gl.getUniformLocation(shaderProgram, "translationMatrix");
|
||||
|
||||
|
||||
|
@ -122,14 +130,28 @@ PIXI.initPrimitiveShader = function()
|
|||
|
||||
PIXI.initDefaultShader = function()
|
||||
{
|
||||
PIXI.frameBufferStack = [];
|
||||
PIXI.frameBufferPool = [];
|
||||
|
||||
PIXI.defaultShader = new PIXI.PixiShader();
|
||||
PIXI.defaultShader.init();
|
||||
PIXI.pushShader(PIXI.defaultShader);
|
||||
|
||||
// offset..
|
||||
|
||||
|
||||
|
||||
// ok and also create 2 spare frame buffers..
|
||||
// PIXI.frameBuffer1 = PIXI.generateFrameBuffer(800, 600);
|
||||
// PIXI.frameBuffer2 = PIXI.generateFrameBuffer(800, 600);
|
||||
// PIXI.currentFrameBuffer;
|
||||
|
||||
/*
|
||||
PIXI.shaderStack.push(PIXI.defaultShader);
|
||||
PIXI.current*/
|
||||
}
|
||||
|
||||
|
||||
PIXI.initDefaultStripShader = function()
|
||||
{
|
||||
var gl = this.gl;
|
||||
|
@ -197,12 +219,19 @@ PIXI.compileProgram = function(vertexSrc, fragmentSrc)
|
|||
|
||||
PIXI.pushShader = function(shader)
|
||||
{
|
||||
PIXI.shaderStack.push(shader);
|
||||
|
||||
var gl = PIXI.gl;
|
||||
|
||||
gl.colorMask(true, true, true, true);
|
||||
gl.viewport(0, 0, this.width, this.height);
|
||||
gl.clearColor(0,0,0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
PIXI.shaderStack.push(shader);
|
||||
|
||||
var shaderProgram = shader.program;
|
||||
|
||||
// flip! the texture..
|
||||
// set the texture!
|
||||
|
||||
// map uniforms..
|
||||
gl.useProgram(shaderProgram);
|
||||
|
|
145
src/pixi/renderers/webgl/filters/Filter.js
Normal file
145
src/pixi/renderers/webgl/filters/Filter.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @author Mat Groves http://matgroves.com/ @Doormat23
|
||||
*/
|
||||
|
||||
|
||||
PIXI.Filter = function()
|
||||
{
|
||||
// build a program
|
||||
/*
|
||||
this.vertexSrc = [
|
||||
"attribute vec2 aVertexPosition;",
|
||||
"attribute vec2 aTextureCoord;",
|
||||
|
||||
"uniform vec2 projectionVector;",
|
||||
"uniform vec2 dimensions;",
|
||||
"uniform vec2 offsetVector;",
|
||||
|
||||
"varying vec2 vTextureCoord;",
|
||||
"const vec2 center = vec2(-1.0, 1.0);",
|
||||
|
||||
"void main(void) {",
|
||||
|
||||
"vec2 tempVector = aVertexPosition;",
|
||||
"tempVector *= dimensions;",
|
||||
|
||||
"tempVector.y -= dimensions.y;",
|
||||
"tempVector += offsetVector;",
|
||||
|
||||
"tempVector /= projectionVector;",
|
||||
|
||||
"tempVector *= 2.0;",
|
||||
|
||||
"tempVector += center;",
|
||||
|
||||
"gl_Position = vec4( tempVector, 0.0, 1.0);",
|
||||
"vTextureCoord = aTextureCoord;",
|
||||
"}"
|
||||
];*/
|
||||
|
||||
this.vertexSrc = [
|
||||
"attribute vec2 aVertexPosition;",
|
||||
"attribute vec2 aTextureCoord;",
|
||||
"attribute float aColor;",
|
||||
|
||||
"uniform vec2 projectionVector;",
|
||||
"uniform vec2 offsetVector;",
|
||||
"varying vec2 vTextureCoord;",
|
||||
|
||||
"varying float vColor;",
|
||||
"const vec2 center = vec2(-1.0, 1.0);",
|
||||
"void main(void) {",
|
||||
"gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);",
|
||||
"vTextureCoord = aTextureCoord;",
|
||||
"vColor = aColor;",
|
||||
"}"
|
||||
];
|
||||
|
||||
this.fragmentSrc = [
|
||||
"precision lowp float;",
|
||||
"varying vec2 vTextureCoord;",
|
||||
"uniform sampler2D uSampler;",
|
||||
|
||||
"void main(void) {",
|
||||
"gl_FragColor = texture2D(uSampler, vTextureCoord).grba;",
|
||||
"}"
|
||||
];
|
||||
|
||||
|
||||
// build program
|
||||
this.program = PIXI.compileProgram(this.vertexSrc, this.fragmentSrc);
|
||||
|
||||
var gl = PIXI.gl;
|
||||
|
||||
// get and store the uniforms for the shader
|
||||
this.uSampler = gl.getUniformLocation(this.program, "uSampler");
|
||||
this.projectionVector = gl.getUniformLocation(this.program, "projectionVector");
|
||||
this.offsetVector = gl.getUniformLocation(this.program, "offsetVector");
|
||||
//this.dimensions = gl.getUniformLocation(this.program, "dimensions");
|
||||
|
||||
// get and store the attributes
|
||||
this.aVertexPosition = gl.getAttribLocation(this.program, "aVertexPosition");
|
||||
this.aTextureCoord = gl.getAttribLocation(this.program, "aTextureCoord");
|
||||
|
||||
}
|
||||
|
||||
PIXI.Filter.prototype.begin = function()
|
||||
{
|
||||
var gl = PIXI.gl;
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||
|
||||
var filterArea = this.target.filterArea;
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
|
||||
|
||||
// set view port
|
||||
gl.viewport(0, 0, filterArea.width, filterArea.height);
|
||||
|
||||
// update projection
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, filterArea.width/2, -filterArea.height/2);
|
||||
gl.uniform2f(PIXI.currentShader.offsetVector, -filterArea.x, -filterArea.y);
|
||||
|
||||
gl.colorMask(true, true, true, true);
|
||||
gl.clearColor(0,0,0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
||||
PIXI.Filter.prototype.end = function(x, y, offsetX, offsetY)
|
||||
{
|
||||
var gl = PIXI.gl;
|
||||
|
||||
// set the filter proram..
|
||||
gl.useProgram(this.program);
|
||||
|
||||
var filterArea = this.target.filterArea;
|
||||
|
||||
// set the uniforms..
|
||||
gl.uniform2f(this.projectionVector, x, y)
|
||||
gl.uniform2f(this.offsetVector, filterArea.x - offsetX, -(filterArea.y-offsetY))
|
||||
gl.uniform2f(this.dimensions, filterArea.width, filterArea.height);
|
||||
|
||||
// bind the buffers..
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.vertexAttribPointer(this.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
|
||||
gl.vertexAttribPointer(this.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
|
||||
// set texture
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||
|
||||
// draw the filter...
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
|
||||
|
||||
gl.useProgram(PIXI.defaultShader.program);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// API
|
365
src/pixi/renderers/webgl/filters/FilterManager.js
Normal file
365
src/pixi/renderers/webgl/filters/FilterManager.js
Normal file
|
@ -0,0 +1,365 @@
|
|||
/**
|
||||
* @author Mat Groves http://matgroves.com/ @Doormat23
|
||||
*/
|
||||
|
||||
|
||||
PIXI.FilterManager = function()
|
||||
{
|
||||
this.filterStack = [];
|
||||
this.texturePool = [];
|
||||
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
|
||||
this.initShaderBuffers();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
PIXI.FilterManager.prototype.begin = function(projection, buffer)
|
||||
{
|
||||
this.width = projection.x * 2;
|
||||
this.height = -projection.y * 2;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
PIXI.FilterManager.prototype.pushFilter = function(filterBlock)
|
||||
{
|
||||
|
||||
// filter program
|
||||
var filter = filterBlock.data[0];
|
||||
|
||||
this.offsetX += filterBlock.target.filterArea.x;
|
||||
this.offsetY += filterBlock.target.filterArea.y;
|
||||
|
||||
this.filterStack.push(filterBlock);
|
||||
|
||||
var gl = PIXI.gl;
|
||||
|
||||
var texture = this.texturePool.pop();
|
||||
if(!texture)texture = new PIXI.FilterTexture();
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture.texture);
|
||||
|
||||
this.getBounds(filterBlock.target);
|
||||
|
||||
var filterArea = filterBlock.target.filterArea;
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, filterArea.width, filterArea.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, texture.frameBuffer);
|
||||
|
||||
// set view port
|
||||
gl.viewport(0, 0, filterArea.width, filterArea.height);
|
||||
|
||||
//PIXI.currentArea = filterArea
|
||||
|
||||
PIXI.projection.x = filterArea.width/2;
|
||||
PIXI.projection.y = -filterArea.height/2;
|
||||
|
||||
PIXI.offset.x = -filterArea.x;
|
||||
PIXI.offset.y = -filterArea.y;
|
||||
|
||||
// update projection
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, filterArea.width/2, -filterArea.height/2);
|
||||
gl.uniform2f(PIXI.currentShader.offsetVector, -filterArea.x, -filterArea.y);
|
||||
//PIXI.primitiveProgram
|
||||
|
||||
gl.colorMask(true, true, true, true);
|
||||
gl.clearColor(0,0,0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
//filter.texture = texture;
|
||||
filterBlock._glFilterTexture = texture;
|
||||
}
|
||||
|
||||
PIXI.FilterManager.prototype.popFilter = function()
|
||||
{
|
||||
var filterBlock = this.filterStack.pop();
|
||||
var filter = filterBlock.data[0];
|
||||
|
||||
//console.log( this.offsetY);
|
||||
this.offsetX -= filterBlock.target.filterArea.x;
|
||||
this.offsetY -= filterBlock.target.filterArea.y;
|
||||
|
||||
var gl = PIXI.gl;
|
||||
|
||||
var sizeX = this.width;
|
||||
var sizeY = this.height;
|
||||
|
||||
var offsetX = 0;
|
||||
var offsetY = 0;
|
||||
|
||||
var buffer = this.buffer;
|
||||
|
||||
// time to render the filters texture to the previous scene
|
||||
if(this.filterStack.length === 0)
|
||||
{
|
||||
gl.colorMask(true, true, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var currentFilter = this.filterStack[this.filterStack.length-1];
|
||||
var filterArea = currentFilter.target.filterArea;
|
||||
|
||||
sizeX = filterArea.width;
|
||||
sizeY = filterArea.height;
|
||||
|
||||
offsetX = filterArea.x;
|
||||
offsetY = filterArea.y;
|
||||
|
||||
buffer = currentFilter._glFilterTexture.frameBuffer;
|
||||
}
|
||||
|
||||
gl.viewport(0, 0, sizeX, sizeY);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, buffer );
|
||||
|
||||
///////
|
||||
if(!filter.shader)
|
||||
{
|
||||
//filter.shader = new PIXI.Filter();
|
||||
|
||||
var shader = new PIXI.PixiShader();
|
||||
|
||||
shader.fragmentSrc = filter.fragmentSrc;
|
||||
shader.uniforms = filter.uniforms;
|
||||
shader.init();
|
||||
|
||||
filter.shader = shader
|
||||
//filter.shader.target = filter.target;
|
||||
}
|
||||
|
||||
var shader = filter.shader;
|
||||
var filterArea = filterBlock.target.filterArea;
|
||||
|
||||
// set the shader
|
||||
gl.useProgram(shader.program);
|
||||
// set the uniforms..
|
||||
|
||||
PIXI.projection.x = sizeX/2;
|
||||
PIXI.projection.y = -sizeY/2;
|
||||
|
||||
gl.uniform2f(shader.projectionVector, sizeX/2, -sizeY/2);
|
||||
gl.uniform2f(shader.offsetVector, 0,0)
|
||||
|
||||
shader.syncUniforms();
|
||||
|
||||
PIXI.offset.x = offsetX;
|
||||
PIXI.offset.y = offsetY;
|
||||
|
||||
var x = filterArea.x-offsetX;
|
||||
var y = filterArea.y-offsetY;
|
||||
|
||||
// bind the buffers..
|
||||
// make sure to flip the y!
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
|
||||
this.vertexArray[0] = x;
|
||||
this.vertexArray[1] = y + filterArea.height;
|
||||
|
||||
this.vertexArray[2] = x + filterArea.width;
|
||||
this.vertexArray[3] = y + filterArea.height;
|
||||
|
||||
this.vertexArray[4] = x;
|
||||
this.vertexArray[5] = y;
|
||||
|
||||
this.vertexArray[6] = x + filterArea.width;
|
||||
this.vertexArray[7] = y;
|
||||
|
||||
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexArray);
|
||||
|
||||
|
||||
gl.vertexAttribPointer(shader.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
|
||||
gl.vertexAttribPointer(shader.aTextureCoord, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
|
||||
// set texture
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, filterBlock._glFilterTexture.texture);
|
||||
|
||||
// draw the filter...
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
|
||||
|
||||
// now restore the regular shader..
|
||||
gl.useProgram(PIXI.defaultShader.program);
|
||||
gl.uniform2f(PIXI.currentShader.projectionVector, sizeX/2, -sizeY/2);
|
||||
gl.uniform2f(PIXI.currentShader.offsetVector, -offsetX, -offsetY);
|
||||
|
||||
// return the texture to the pool
|
||||
|
||||
this.texturePool.push(filterBlock._glFilterTexture);
|
||||
filterBlock._glFilterTexture = null;
|
||||
|
||||
}
|
||||
|
||||
PIXI.FilterManager.prototype.initShaderBuffers = function()
|
||||
{
|
||||
var gl = PIXI.gl;
|
||||
|
||||
// create some buffers
|
||||
this.vertexBuffer = gl.createBuffer();
|
||||
this.uvBuffer = gl.createBuffer();
|
||||
this.indexBuffer = gl.createBuffer();
|
||||
|
||||
// bind and upload the vertexs..
|
||||
// keep a refferance to the vertexFloatData..
|
||||
this.vertexArray = new Float32Array([0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
1.0, 1.0]);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
this.vertexArray,
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
|
||||
// bind and upload the uv buffer
|
||||
this.uvArray = new Float32Array([0.0, 0.0,
|
||||
1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
1.0, 1.0]);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
this.uvArray,
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
// bind and upload the index
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
gl.bufferData(
|
||||
gl.ELEMENT_ARRAY_BUFFER,
|
||||
new Uint16Array([0, 1, 2, 1, 3, 2]),
|
||||
gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
PIXI.FilterManager.prototype.getBounds = function(displayObject)
|
||||
{
|
||||
// time to get the width and height of the object!
|
||||
var worldTransform, width, height, aX, aY, w0, w1, h0, h1, index, doTest;
|
||||
var a, b, c, d, tx, ty, x1, x2, x3, x4, y1, y2, y3, y4;
|
||||
|
||||
var tempObject = displayObject.first;
|
||||
var testObject = displayObject.last._iNext;
|
||||
|
||||
var maxX = -Infinity;
|
||||
var maxY = -Infinity;
|
||||
|
||||
var minX = Infinity;
|
||||
var minY = Infinity;
|
||||
|
||||
do
|
||||
{
|
||||
// TODO can be optimized! - what if there is no scale / rotation?
|
||||
|
||||
if(tempObject instanceof PIXI.Sprite)
|
||||
{
|
||||
width = tempObject.texture.frame.width;
|
||||
height = tempObject.texture.frame.height;
|
||||
|
||||
// TODO trim??
|
||||
aX = tempObject.anchor.x;
|
||||
aY = tempObject.anchor.y;
|
||||
w0 = width * (1-aX);
|
||||
w1 = width * -aX;
|
||||
|
||||
h0 = height * (1-aY);
|
||||
h1 = height * -aY;
|
||||
|
||||
doTest = true;
|
||||
}
|
||||
else if(tempObject instanceof PIXI.Graphics)
|
||||
{
|
||||
tempObject.updateFilterBounds();
|
||||
|
||||
var bounds = tempObject.bounds;
|
||||
|
||||
width = bounds.width;
|
||||
height = bounds.height;
|
||||
|
||||
w0 = bounds.x
|
||||
w1 = bounds.x + bounds.width;
|
||||
|
||||
h0 = bounds.y
|
||||
h1 = bounds.y + bounds.height;
|
||||
|
||||
doTest = true;
|
||||
}
|
||||
|
||||
if(doTest)
|
||||
{
|
||||
worldTransform = tempObject.worldTransform;
|
||||
|
||||
a = worldTransform[0];
|
||||
b = worldTransform[3];
|
||||
c = worldTransform[1];
|
||||
d = worldTransform[4];
|
||||
tx = worldTransform[2];
|
||||
ty = worldTransform[5];
|
||||
|
||||
x1 = a * w1 + c * h1 + tx;
|
||||
y1 = d * h1 + b * w1 + ty;
|
||||
|
||||
x2 = a * w0 + c * h1 + tx;
|
||||
y2 = d * h1 + b * w0 + ty;
|
||||
|
||||
x3 = a * w0 + c * h0 + tx;
|
||||
y3 = d * h0 + b * w0 + ty;
|
||||
|
||||
x4 = a * w1 + c * h0 + tx;
|
||||
y4 = d * h0 + b * w1 + ty;
|
||||
|
||||
minX = x1 < minX ? x1 : minX;
|
||||
minX = x2 < minX ? x2 : minX;
|
||||
minX = x3 < minX ? x3 : minX;
|
||||
minX = x4 < minX ? x4 : minX;
|
||||
|
||||
minY = y1 < minY ? y1 : minY;
|
||||
minY = y2 < minY ? y2 : minY;
|
||||
minY = y3 < minY ? y3 : minY;
|
||||
minY = y4 < minY ? y4 : minY;
|
||||
|
||||
maxX = x1 > maxX ? x1 : maxX;
|
||||
maxX = x2 > maxX ? x2 : maxX;
|
||||
maxX = x3 > maxX ? x3 : maxX;
|
||||
maxX = x4 > maxX ? x4 : maxX;
|
||||
|
||||
maxY = y1 > maxY ? y1 : maxY;
|
||||
maxY = y2 > maxY ? y2 : maxY;
|
||||
maxY = y3 > maxY ? y3 : maxY;
|
||||
maxY = y4 > maxY ? y4 : maxY;
|
||||
}
|
||||
|
||||
doTest = false;
|
||||
tempObject = tempObject._iNext;
|
||||
}
|
||||
while(tempObject != testObject)
|
||||
|
||||
displayObject.filterArea.x = minX;
|
||||
displayObject.filterArea.y = minY;
|
||||
displayObject.filterArea.width = maxX - minX;
|
||||
displayObject.filterArea.height = maxY - minY;
|
||||
}
|
||||
|
||||
PIXI.FilterTexture = function()
|
||||
{
|
||||
var gl = PIXI.gl;
|
||||
|
||||
// next time to create a frame buffer and texture
|
||||
this.frameBuffer = gl.createFramebuffer();
|
||||
this.texture = gl.createTexture();
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.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.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer );
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer );
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
|
||||
}
|
|
@ -91,12 +91,10 @@ PIXI.RenderTexture.prototype.initWebGL = function()
|
|||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.baseTexture._glTexture, 0);
|
||||
|
||||
// create a projection matrix..
|
||||
this.projection = new PIXI.Point(this.width/2 , this.height/2);
|
||||
this.projection = new PIXI.Point(this.width/2 , -this.height/2);
|
||||
|
||||
// set the correct render function..
|
||||
this.render = this.renderWebGL;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -109,7 +107,7 @@ PIXI.RenderTexture.prototype.resize = function(width, height)
|
|||
if(PIXI.gl)
|
||||
{
|
||||
this.projection.x = this.width/2
|
||||
this.projection.y = this.height/2;
|
||||
this.projection.y = -this.height/2;
|
||||
|
||||
var gl = PIXI.gl;
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.baseTexture._glTexture);
|
||||
|
@ -173,9 +171,8 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle
|
|||
displayObject.worldTransform = PIXI.mat3.create();//sthis.indetityMatrix;
|
||||
// modify to flip...
|
||||
displayObject.worldTransform[4] = -1;
|
||||
displayObject.worldTransform[5] = this.projection.y * 2;
|
||||
displayObject.worldTransform[5] = this.projection.y * -2;
|
||||
|
||||
|
||||
if(position)
|
||||
{
|
||||
displayObject.worldTransform[2] = position.x;
|
||||
|
@ -196,18 +193,18 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle
|
|||
{
|
||||
if(displayObject == renderGroup.root)
|
||||
{
|
||||
renderGroup.render(this.projection);
|
||||
renderGroup.render(this.projection, this.glFramebuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderGroup.renderSpecific(displayObject, this.projection);
|
||||
renderGroup.renderSpecific(displayObject, this.projection, this.glFramebuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!this.renderGroup)this.renderGroup = new PIXI.WebGLRenderGroup(gl);
|
||||
this.renderGroup.setRenderable(displayObject);
|
||||
this.renderGroup.render(this.projection);
|
||||
this.renderGroup.render(this.projection, this.glFramebuffer);
|
||||
}
|
||||
|
||||
displayObject.worldTransform = originalWorldTransform;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue