Permalink
Browse files

simplified matrix calculations of filters

  • Loading branch information...
1 parent 2e6a19f commit d5c4b37cc9e020803962bce880ce335db3ef88a1 @PrimaryFeather PrimaryFeather committed Sep 7, 2012
View
19 starling/src/starling/core/RenderSupport.as
@@ -58,7 +58,7 @@ package starling.core
mQuadBatches = new <QuadBatch>[new QuadBatch()];
loadIdentity();
- setOrthographicProjection(400, 300);
+ setOrthographicProjection(0, 0, 400, 300);
}
/** Disposes all quad batches. */
@@ -71,9 +71,10 @@ package starling.core
// matrix manipulation
/** Sets up the projection matrix for ortographic 2D rendering. */
- public function setOrthographicProjection(width:Number, height:Number):void
+ public function setOrthographicProjection(x:Number, y:Number, width:Number, height:Number):void
{
- mProjectionMatrix.setTo(2.0/width, 0, 0, -2.0/height, -1.0, 1.0);
+ mProjectionMatrix.setTo(2.0/width, 0, 0, -2.0/height,
+ -(2*x + width) / width, (2*y + height) / height);
}
/** Changes the modelview matrix to the identity matrix. */
@@ -170,7 +171,8 @@ package starling.core
setBlendFactors(premultipliedAlpha, mBlendMode);
}
- /** The blend mode to be used on rendering. */
+ /** The blend mode to be used on rendering. To apply the factor, you have to manually call
+ * 'applyBlendMode' (because the actual blend factors depend on the PMA mode). */
public function get blendMode():String { return mBlendMode; }
public function set blendMode(value:String):void
{
@@ -179,18 +181,17 @@ package starling.core
// render targets
- /** The texture that is currently being rendered into,
- * or 'null' to render into the back buffer. */
+ /** The texture that is currently being rendered into, or 'null' to render into the
+ * back buffer. If you set a new target, it is immediately activated. */
+ public function get renderTarget():Texture { return mRenderTarget; }
public function set renderTarget(target:Texture):void
- {
+ {
mRenderTarget = target;
if (target) Starling.context.setRenderToTexture(target.base);
else Starling.context.setRenderToBackBuffer();
}
- public function get renderTarget():Texture { return mRenderTarget; }
-
// optimized quad rendering
/** Adds a quad to the current batch of unrendered quads. If there is a state change,
View
2 starling/src/starling/core/Starling.as
@@ -354,7 +354,7 @@ package starling.core
if (!mShareContext)
RenderSupport.clear(mStage.color, 1.0);
- mSupport.setOrthographicProjection(mStage.stageWidth, mStage.stageHeight);
+ mSupport.setOrthographicProjection(0, 0, mStage.stageWidth, mStage.stageHeight);
mSupport.renderTarget = null; // back buffer
mStage.render(mSupport, 1.0);
View
89 starling/src/starling/filters/FragmentFilter.as
@@ -27,7 +27,6 @@ package starling.filters
import starling.core.RenderSupport;
import starling.core.Starling;
import starling.display.DisplayObject;
- import starling.display.Image;
import starling.display.Stage;
import starling.errors.AbstractClassError;
import starling.errors.MissingContextError;
@@ -126,14 +125,29 @@ package starling.filters
public function render(object:DisplayObject, support:RenderSupport, parentAlpha:Number):void
{
+ if (mode == FragmentFilterMode.ABOVE)
+ object.render(support, parentAlpha);
+
+ renderPasses(object, support, parentAlpha);
+
+ if (mode == FragmentFilterMode.BELOW)
+ object.render(support, parentAlpha);
+ }
+
+ // helper methods
+
+ private function renderPasses(object:DisplayObject, support:RenderSupport,
+ parentAlpha:Number):void
+ {
var stage:Stage = object.stage;
if (stage == null) return;
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
- if (mode == FragmentFilterMode.ABOVE)
- object.render(support, parentAlpha);
+ support.finishQuadBatch();
+ support.raiseDrawCount(mNumPasses);
+ support.pushMatrix();
// save original projection matrix and render target
mProjMatrix.copyFrom(support.projectionMatrix);
@@ -145,52 +159,42 @@ package starling.filters
"This limitation will be removed in a future Stage3D version.");
// get bounds in stage coordinates
- // can be expensive, so we optimize at least for full-screen effects
+ // optimize for full-screen effects
if (object == stage || object == Starling.current.root)
mBounds.setTo(0, 0, stage.stageWidth, stage.stageHeight);
else
object.getBounds(stage, mBounds);
+ // the bounds are a rectangle around the object, in stage coordinates,
+ // and with an optional margin. To fit into a POT-texture, it will grow towards
+ // the right and bottom.
var deltaMargin:Number = mResolution == 1.0 ? 0.0 : 1.0 / mResolution; // to avoid hard edges
mBounds.x -= mMarginX + deltaMargin;
mBounds.y -= mMarginY + deltaMargin;
mBounds.width += 2 * (mMarginX + deltaMargin);
mBounds.height += 2 * (mMarginY + deltaMargin);
- mBounds.width = getNextPowerOfTwo(mBounds.width * mResolution);
- mBounds.height = getNextPowerOfTwo(mBounds.height * mResolution);
+ var textureWidth:int = getNextPowerOfTwo(mBounds.width * mResolution);
+ var textureHeight:int = getNextPowerOfTwo(mBounds.height * mResolution);
- updatePassTextures(mBounds.width, mBounds.height);
+ mBounds.width = textureWidth / mResolution;
+ mBounds.height = textureHeight / mResolution;
- // update the vertices that span up the filter rectangle
- updateBuffers(context, mBounds.width, mBounds.height);
-
- // now prepare filter passes
- support.finishQuadBatch();
- support.raiseDrawCount(mNumPasses);
-
- support.pushMatrix();
- support.loadIdentity();
- support.setOrthographicProjection(mBounds.width, mBounds.height);
-
- // draw the original object into a render texture
- var matrix:Matrix = support.modelViewMatrix;
- object.getTransformationMatrix(stage, matrix);
- matrix.translate(-mBounds.x, -mBounds.y);
- matrix.scale(mResolution, mResolution);
+ // prepare the textures we will render into, and the quad that spans up the filter
+ updatePassTextures(textureWidth, textureHeight);
+ updateBuffers(context, mBounds);
+ // draw the original object into a texture
support.renderTarget = mPassTextures[0];
support.clear();
-
+ support.setOrthographicProjection(mBounds.x, mBounds.y, mBounds.width, mBounds.height);
object.render(support, parentAlpha);
-
support.finishQuadBatch();
- support.loadIdentity();
- // force blend mode "normal" for render passes
- RenderSupport.setBlendFactors(PMA);
+ // prepare drawing of actual filter passes
+ RenderSupport.setBlendFactors(PMA); // force blend mode "normal" for filter passes
+ support.loadIdentity(); // now we'll draw in stage coordinates!
- // set shader attributes
context.setVertexBufferAt(0, mVertexBuffer, VertexData.POSITION_OFFSET, Context3DVertexBufferFormat.FLOAT_2);
context.setVertexBufferAt(1, mVertexBuffer, VertexData.TEXCOORD_OFFSET, Context3DVertexBufferFormat.FLOAT_2);
@@ -206,8 +210,7 @@ package starling.filters
{
support.renderTarget = previousRenderTarget;
support.projectionMatrix.copyFrom(mProjMatrix); // restore projection matrix
- support.translateMatrix(mBounds.x + mOffsetX, mBounds.y + mOffsetY);
- support.scaleMatrix(1.0/mResolution, 1.0/mResolution);
+ support.translateMatrix(mOffsetX, mOffsetY);
}
var passTexture:Texture = getPassTexture(i);
@@ -226,18 +229,14 @@ package starling.filters
context.setTextureAt(0, null);
support.popMatrix();
-
- if (mode == FragmentFilterMode.BELOW)
- object.render(support, parentAlpha);
}
- // helper methods
-
- private function updateBuffers(context:Context3D, width:Number, height:Number):void
+ private function updateBuffers(context:Context3D, bounds:Rectangle):void
{
- mVertexData.setPosition(1, width, 0);
- mVertexData.setPosition(2, 0, height);
- mVertexData.setPosition(3, width, height);
+ mVertexData.setPosition(0, bounds.x, bounds.y);
+ mVertexData.setPosition(1, bounds.right, bounds.y);
+ mVertexData.setPosition(2, bounds.x, bounds.bottom);
+ mVertexData.setPosition(3, bounds.right, bounds.bottom);
if (mVertexBuffer == null)
{
@@ -261,7 +260,9 @@ package starling.filters
{
if (mPassTextures)
{
- for each (var texture:Texture in mPassTextures) texture.dispose();
+ for each (var texture:Texture in mPassTextures)
+ texture.dispose();
+
mPassTextures.length = numPassTextures;
}
else
@@ -316,7 +317,11 @@ package starling.filters
// properties
public function get resolution():Number { return mResolution; }
- public function set resolution(value:Number):void { mResolution = value; }
+ public function set resolution(value:Number):void
+ {
+ if (value <= 0) throw new ArgumentError("Resolution must be > 0");
+ else mResolution = value;
+ }
public function get mode():String { return mMode; }
public function set mode(value:String):void { mMode = value; }
View
2 starling/src/starling/textures/RenderTexture.as
@@ -86,7 +86,7 @@ package starling.textures
mActiveTexture = Texture.empty(width, height, PMA, true, scale);
mSupport = new RenderSupport();
- mSupport.setOrthographicProjection(mNativeWidth/scale, mNativeHeight/scale);
+ mSupport.setOrthographicProjection(0, 0, mNativeWidth/scale, mNativeHeight/scale);
if (persistent)
{

0 comments on commit d5c4b37

Please sign in to comment.