forked from Gamua/Starling-Framework
/
RenderTexture.as
211 lines (180 loc) · 7.84 KB
/
RenderTexture.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// =================================================================================================
//
// Starling Framework
// Copyright 2011 Gamua OG. All Rights Reserved.
//
// This program is free software. You can redistribute and/or modify it
// in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================
package starling.textures
{
import flash.display3D.Context3D;
import flash.display3D.textures.TextureBase;
import flash.geom.Rectangle;
import starling.core.RenderSupport;
import starling.core.Starling;
import starling.display.DisplayObject;
import starling.display.Image;
import starling.errors.MissingContextError;
import starling.utils.VertexData;
import starling.utils.getNextPowerOfTwo;
/** A RenderTexture is a dynamic texture onto which you can draw any display object.
*
* <p>After creating a render texture, just call the <code>drawObject</code> method to render
* an object directly onto the texture. The object will be drawn onto the texture at its current
* position, adhering its current rotation, scale and alpha properties.</p>
*
* <p>Drawing is done very efficiently, as it is happening directly in graphics memory. After
* you have drawn objects onto the texture, the performance will be just like that of a normal
* texture - no matter how many objects you have drawn.</p>
*
* <p>If you draw lots of objects at once, it is recommended to bundle the drawing calls in
* a block via the <code>drawBundled</code> method, like shown below. That will speed it up
* immensely, allowing you to draw hundreds of objects very quickly.</p>
*
* <pre>
* renderTexture.drawBundled(function():void
* {
* for (var i:int=0; i<numDrawings; ++i)
* {
* image.rotation = (2 * Math.PI / numDrawings) * i;
* renderTexture.draw(image);
* }
* });
* </pre>
*
*/
public class RenderTexture extends Texture
{
private var mActiveTexture:Texture;
private var mBufferTexture:Texture;
private var mHelperImage:Image;
private var mDrawing:Boolean;
private var mNativeWidth:int;
private var mNativeHeight:int;
private var mSupport:RenderSupport;
/** Creates a new RenderTexture with a certain size. If the texture is persistent, the
* contents of the texture remains intact after each draw call, allowing you to use the
* texture just like a canvas. If it is not, it will be cleared before each draw call.
* Persistancy doubles the required graphics memory! Thus, if you need the texture only
* for one draw (or drawBundled) call, you should deactivate it. */
public function RenderTexture(width:int, height:int, persistent:Boolean=true)
{
mSupport = new RenderSupport();
mNativeWidth = getNextPowerOfTwo(width);
mNativeHeight = getNextPowerOfTwo(height);
mActiveTexture = Texture.empty(width, height, 0x0, true);
if (persistent)
{
mBufferTexture = Texture.empty(width, height, 0x0, true);
mHelperImage = new Image(mBufferTexture);
}
}
/** @inheritDoc */
public override function dispose():void
{
mActiveTexture.dispose();
if (isPersistent)
{
mBufferTexture.dispose();
mHelperImage.dispose();
}
super.dispose();
}
/** Draws an object onto the texture, adhering its properties for position, scale, rotation
* and alpha. */
public function draw(object:DisplayObject, antiAliasing:int=0):void
{
if (object == null) return;
if (mDrawing)
render();
else
drawBundled(render, antiAliasing);
function render():void
{
mSupport.pushMatrix();
mSupport.transformMatrix(object);
object.render(mSupport, 1.0);
mSupport.popMatrix();
}
}
/** Bundles several calls to <code>draw</code> together in a block. This avoids buffer
* switches and allows you to draw multiple objects into a non-persistent texture. */
public function drawBundled(drawingBlock:Function, antiAliasing:int=0):void
{
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
// limit drawing to relevant area
context.setScissorRectangle(
new Rectangle(0, 0, mActiveTexture.width, mActiveTexture.height));
// persistent drawing uses double buffering, as Molehill forces us to call 'clear'
// on every render target once per update.
// switch buffers
if (isPersistent)
{
var tmpTexture:Texture = mActiveTexture;
mActiveTexture = mBufferTexture;
mBufferTexture = tmpTexture;
mHelperImage.texture = mBufferTexture;
}
context.setRenderToTexture(mActiveTexture.base, false, antiAliasing);
RenderSupport.setDefaultBlendFactors(true);
mSupport.setOrthographicProjection(mNativeWidth, mNativeHeight);
mSupport.clear();
// draw buffer
if (isPersistent)
mHelperImage.render(mSupport, 1.0);
try
{
mDrawing = true;
// draw new objects
if (drawingBlock != null)
drawingBlock();
}
finally
{
mDrawing = false;
mSupport.finishQuadBatch();
mSupport.nextFrame();
context.setScissorRectangle(null);
context.setRenderToBackBuffer();
}
}
/** Clears the texture (restoring full transparency). */
public function clear():void
{
var context:Context3D = Starling.context;
if (context == null) throw new MissingContextError();
context.setRenderToTexture(mActiveTexture.base);
mSupport.clear();
if (isPersistent)
{
context.setRenderToTexture(mActiveTexture.base);
mSupport.clear();
}
context.setRenderToBackBuffer();
}
/** @inheritDoc */
public override function adjustVertexData(vertexData:VertexData, vertexID:int, count:int):void
{
return mActiveTexture.adjustVertexData(vertexData, vertexID, count);
}
/** Indicates if the texture is persistent over multiple draw calls. */
public function get isPersistent():Boolean { return mBufferTexture != null; }
/** @inheritDoc */
public override function get width():Number { return mActiveTexture.width; }
/** @inheritDoc */
public override function get height():Number { return mActiveTexture.height; }
/** @inheritDoc */
public override function get premultipliedAlpha():Boolean
{
return mActiveTexture.premultipliedAlpha;
}
/** @inheritDoc */
public override function get base():TextureBase
{
return mActiveTexture.base;
}
}
}