Let’s pretend we have a BitmapData
atlas with two graphics in it:
[ A | B ]
Assuming each side is 100 pixels all around, you should be able to use drawQuads
in order to draw both, like this:
graphics.beginBitmapFill (bitmapData);
graphics.drawQuads (Vector.ofArray ([
0, 0, 100, 100,
100, 0, 100, 100
]));
This draws both A and B from the source BitmapData
, using the proper UV coordinates for each rectangle. You could use drawRect
with the full-size of the BitmapData
again and get the same effect. However, drawQuads
supports the ability to transform the target draw position. The source UV remains the same, but we can override the rectangle position and define our own (x, y) pair, abcd, or full (a, b, c, d, tx, ty) transform.
graphics.beginBitmapFill (bitmapData);
graphics.drawQuads (Vector.ofArray ([
0, 0, 100, 100,
100, 0, 100, 100
]), null, Vector.ofArray ([
100, 200,
300, 100
]));
The second parameter can be used to reference rectangles (from the first parameter) by index. You can define the rect
data as in the above examples, or another way is the Tileset
class (for example) exposes the data for each rectangle in the tileset as an array that can be used with drawQuads.
var tileset = new Tileset (bitmapData);
tileset.addRect (new Rectangle (0, 0, 100, 100));
tileset.addRect (new Rectangle (100, 0, 100, 100));
graphics.beginBitmapFill (bitmapData);
graphics.drawQuads (tileset.rectData, Vector.ofArray ([ 0, 1 ]));
It’s not currently possible to add alpha without using a shader fill. I think a shader with alpha only would look something like this:
import openfl.display.GraphicsShader;
class AlphaGraphicsShader extends GraphicsShader {
@:glVertexSource(
"#pragma header
attribute float alpha;
varying float alphav;
void main(void) {
alphav = alpha;
#pragma body
}"
)
@:glFragmentSource(
"#pragma header
varying float alphav;
void main(void) {
#pragma body
gl_FragColor = gl_FragColor * alphav;
}"
)
public function new () {
super ();
}
}
Then rendering would look more like:
var shader = new AlphaGraphicsShader ();
shader.bitmap.input = bitmapData;
shader.alpha.value = [ 0.5 ];
graphics.beginShaderFill (shader);
graphics.drawQuads (tileset.rectData, new Vector ([ 0, 1 ]));
This would set 0.5 as a constant value for all vertices. The set the alpha for each vertex (and ultimately, quad) separately, you would need to define enough alpha values to cover the render. In the latest OpenFL release, you need 6 values per quad. In the next release, I think this will be dropping down to 4 since we’ll be using an index buffer instead.
var shader = new AlphaGraphicsShader ();
shader.alpha = [];
for (i in 0...6) shader.alpha.push (0.5);
for (i in 0...6) shader.alpha.push (0.25);
graphics.beginShaderFill (shader);
graphics.drawQuads (tileset.rectData, new Vector ([ 0, 1 ]));
You are not trying to abuse the API, though (depending on your use case) you might also consider Tilemap
, which is easier to use
var tilemap = new Tilemap (stage.stageWidth, stage.stageHeight);
var tile = new Tile (0);
tile.tileset = tileset;
tile.alpha = 0.5;
tile.x = 200;
tilemap.addTile (tile);
var tile = new Tile (1);
tile.tileset = tileset;
tile.alpha = 0.25;
tile.x = 300;
tile.y = 100;
tilemap.addTile (tile);
Tilemap
lets you set a default Tileset
for the whole map, but you also can set/override the tileset
on each Tile
, making it pretty flexible.
You can do alpha, x, y, scale, color transform, custom shaders and other properties on each Tile
, or group using TileContainer
, so it’s sort of a mix of drawQuads
and the display list rendering. Some features (like color transform or shaders) don’t work on software (cairo, canvas, DOM) targets, but otherwise Tilemap (like drawQuads) should work on these renderers