Render Texture Example
Overview
An example showing the use of render textures as a canvas that can be drawn on. The display object provided is drawn with it's respective transform matrix and alpha. The matrix parameter on the draw functions can be used to override the transform and alpha can be modified by the alpha multiplier parameter.
Try It
Use the following Loom CLI commands to run this example:
loom new MyRenderTextureExample --example RenderTextureExample
cd MyRenderTextureExample
loom run
Screenshot

Code
src/RenderTextureExample.ls
package
{
import loom.Application;
import loom.graphics.Texture2D;
import loom.graphics.TextureInfo;
import loom2d.display.BlendMode;
import loom2d.display.Graphics;
import loom2d.display.Shape;
import loom2d.display.Sprite;
import loom2d.display.Stage;
import loom2d.display.StageScaleMode;
import loom2d.display.Image;
import loom2d.events.Touch;
import loom2d.events.TouchEvent;
import loom2d.events.TouchPhase;
import loom2d.Loom2D;
import loom2d.math.Matrix;
import loom2d.math.Rectangle;
import loom2d.textures.ConcreteTexture;
import loom2d.textures.RenderTexture;
import loom2d.textures.Texture;
import loom2d.textures.TextureSmoothing;
import loom2d.ui.SimpleLabel;
import system.platform.Platform;
import system.Void;
/**
* Shows example usage of the render texture API.
*/
public class RenderTextureExample extends Application
{
private var outlines:Shape;
private var container:Sprite;
private var logo:Image;
private var shape:Shape;
private var image:Image;
private var renderTexture:RenderTexture;
private var roll:RenderTexture;
private var rollDisplay:Image;
private var persistent:RenderTexture;
private var persistentDisplay:Image;
private var gt:Number = 0;
private var t:Number = 0;
override public function run():void
{
// Comment out this line to turn off automatic scaling.
stage.scaleMode = StageScaleMode.LETTERBOX;
// Setup anything else, like UI, or game objects.
var bg = new Image(Texture.fromAsset("assets/bg.png"));
bg.width = stage.stageWidth;
bg.height = stage.stageHeight;
stage.addChild(bg);
outlines = new Shape();
// Create an empty, transparent render texture
// that is 200px wide and 200px high
renderTexture = new RenderTexture(200, 200);
// Create an image that will display the render texture
image = new Image(renderTexture);
image.x = 10;
image.y = 10;
container = new Sprite();
var logoTex = Texture.fromAsset("assets/logo.png");
logo = new Image(logoTex);
logo.center();
shape = new Shape();
container.x = 85;
container.y = 80;
container.scale = 0.7;
container.addChild(logo);
stage.addChild(image);
stage.addChild(outlines);
draw();
// The bottom roll texture
roll = new RenderTexture(stage.stageWidth, 110, false);
rollDisplay = new Image(roll);
rollDisplay.y = stage.stageHeight-roll.height;
stage.addChild(rollDisplay);
// The right persistent drawing texture
persistent = new RenderTexture(renderTexture.width, renderTexture.height, true);
persistentDisplay = new Image(persistent);
persistentDisplay.x = image.x+renderTexture.width+10;
persistentDisplay.y = image.y;
stage.addChild(persistentDisplay);
stage.addEventListener(TouchEvent.TOUCH, onTouch);
}
private function onTouch(e:TouchEvent):void {
var t:Touch = e.getTouch(stage, TouchPhase.BEGAN);
if (!t) return;
switch (stage.vectorQuality) {
case Stage.VECTOR_QUALITY_ANTIALIAS | Stage.VECTOR_QUALITY_STENCIL_STROKES:
stage.vectorQuality = Stage.VECTOR_QUALITY_ANTIALIAS;
trace("Vector quality set to ANTIALIAS");
break;
case Stage.VECTOR_QUALITY_ANTIALIAS:
stage.vectorQuality = Stage.VECTOR_QUALITY_STENCIL_STROKES;
trace("Vector quality set to STENCIL");
break;
case Stage.VECTOR_QUALITY_STENCIL_STROKES:
stage.vectorQuality = Stage.VECTOR_QUALITY_NONE;
trace("Vector quality set to NONE");
break;
default:
stage.vectorQuality = Stage.VECTOR_QUALITY_ANTIALIAS | Stage.VECTOR_QUALITY_STENCIL_STROKES;
trace("Vector quality set to ANTIALIAS and STENCIL");
}
}
function draw() {
// Clear the texture in case the function
// is called multiple times.
renderTexture.clear();
// Set the logo state we want to work from
// This is needed in case we change logo elsewhere
// (e.g. in a loop below)
logo.x = 25;
logo.y = 70;
logo.alpha = 0.8;
logo.rotation = 0;
logo.scale = 1;
// Outlines of bounds
var g:Graphics = outlines.graphics;
g.clear();
g.lineStyle(1, 0x53C109);
var m = new Matrix();
// Setup background matrix
m.translate(-logo.width/2, -logo.height/2);
m.scale(4, 4);
m.translate(renderTexture.width/2, renderTexture.height/2);
// Draw background
renderTexture.draw(logo, m);
g.drawRect(image.x, image.y, renderTexture.width, renderTexture.height);
// No matrix default draw
renderTexture.draw(container);
g.drawRect(image.x+container.x+(logo.x-logo.width/2)*container.scale, image.y+container.y+(logo.y-logo.height/2)*container.scale, logo.width*container.scale, logo.height*container.scale);
// Smaller matrix
m.identity();
m.scale(0.5, 0.5);
m.translate(55, 20);
// Draw the container using the provided `m` transform matrix
renderTexture.draw(container, m);
g.drawRect(image.x+(logo.x-logo.width/2)*0.5+55, image.y+(logo.y-logo.height/2)*0.5+20, logo.width*0.5, logo.height*0.5);
// Offset Poly with different alpha
m.translate(65, 0);
renderTexture.draw(container, m, 0.5);
g.drawRect(image.x+(logo.x-logo.width/2)*0.5+120, image.y+(logo.y-logo.height/2)*0.5+20, logo.width*0.5, logo.height*0.5);
m.identity();
m.scale(0.25, 0.25);
m.translate(12.5, renderTexture.height-30);
renderTexture.drawBundled(function() {
for (var i:int = 0; i < 10; i++) {
renderTexture.draw(container, m);
m.translate((renderTexture.width-container.width*0.25)/10, 0);
}
});
}
override public function onTick() {
// Uncomment to draw the static test every frame
//draw();
///*
// Draw a funky evolving shape
t = 0;
logo.x = 0;
logo.alpha = 1;
// Begin drawing into the `roll` texture
// This will set `roll` to be the current render
// texture, so the only valid `draw` calls
// will be the ones made on the `roll` texture.
roll.drawBundledLock();
while (logo.x-logo.width/2 < roll.width) {
var radius = 256;
var angle = t*0.5*Math.TWOPI;
logo.x = t*0.3*roll.width;
//logo.x = t*3*roll.width;
logo.y = roll.height*0.5;
logo.rotation = t*Math.sin(gt*0.1*Math.TWOPI)*3+(Math.sin(t*0.3)*0.5)*0.07;
logo.scale = (Math.sin(t*0.3*Math.TWOPI+Math.sin(gt*0.03*Math.TWOPI)*10)*0.5+0.5)*0.8+0.2;
roll.draw(logo);
t += 1/60;
}
// End drawing into the texture
// This submits all the batched `draw` calls
// to the GPU and draws them into the `roll` texture.
roll.drawBundledUnlock();
// Draw into a persistent buffer
// Random position in texture
logo.x = Math.random()*persistent.width;
logo.y = Math.random()*persistent.height;
// Random rotation
logo.rotation = Math.random()*Math.TWOPI;
// Random scale with a bias towards smaller ones
logo.scale = 0.2+0.8*(1-Math.exp(-Math.pow(Math.random(), 10)))*2;
// Alternate between drawing and erasing
logo.blendMode = gt%3 < 2 ? BlendMode.NORMAL : BlendMode.ERASE;
persistent.draw(logo);
var g = shape.graphics;
g.clear();
g.beginFill(Math.random()*0xFFFFFF);
g.drawCircle(Math.random()*persistent.width, Math.random()*persistent.height, 10);
persistent.draw(shape);
// Restore blendmode
logo.blendMode = BlendMode.NORMAL;
gt += 1/60;
//*/
}
}
}