I’ll keep on writing here in case someone else has a similar problem. Ok, so the current approach seems to be working. I’m still not sure if it’s the right one though. I created two objects, a ContextBuffer and a BufferRenderer.
class ContextBuffer
{
public var context(default, null):RenderContext;
public var target(default, null):Texture;
public var bitmap(default, null):Bitmap;
public function new(aScene:Scene, aWidth:Int, aHeight:Int):Void
{
context = new RenderContext(aScene);
target = new Texture(aWidth, aHeight, [Target]);
bitmap = new Bitmap(Tile.fromTexture(target));
}
public function render():Void
{
context.pushTarget(target);
context.begin();
context.clear(0);
context.drawScene();
context.popTarget();
context.end();
}
}
class BufferRenderer
{
public var buffers(default, null):Array<ContextBuffer>;
public var width(default, null):Int;
public var height(default, null):Int;
public function new(aWidth:Int, aHeight:Int):Void
{
width = aWidth;
height = aHeight;
buffers = [];
}
public function createBuffer(aScene:Scene):ContextBuffer
{
var buffer:ContextBuffer = new ContextBuffer(aScene, width, height);
buffers.push(buffer);
return buffer;
}
public function render():Void
{
for (buffer in buffers)
{
buffer.render();
}
}
}
Finally, I extended the Bitmap class in a ContextBitmap that will only render in the correct context. Is this the right approach? I don’t know, but it sure fits the litteral meaning of “context”, so for now it works.
class ContextBitmap extends Bitmap
{
public var expectedContext:RenderContext;
public function new(?context:RenderContext, ?tile:h2d.Tile, ?parent:h2d.Object):Void
{
expectedContext = context;
super(tile, parent);
}
override private function draw(ctx:RenderContext):Void
{
if (ctx == expectedContext)
{
super.draw(ctx);
}
}
}
Now it’s all a matter of creating a ship, putting each texture in a ContextBitmap of the right context (Normal Texture in NormalContext, Diffuse Texture in DiffuseContext, etc.) and it renders correctly. The mask bitmap without context is a black bitmap of the ship to hide stuff that are under it as it renders before the current pass.
renderer = new BufferRenderer(engine.width, engine.height);
var bufferScene = new Scene();
var diffuse = renderer.createBuffer(bufferScene);
var normal = renderer.createBuffer(bufferScene);
var ship:Object = new Object(bufferScene);
var shipMask = new Bitmap(shipImage.toTile(), ship);
var shipDiffuseBitmap = new ContextBitmap(diffuse.context, shipImage.toTile(), ship);
var shipNormalBitmap = new ContextBitmap(normal.context, shipNormal.toTile(), ship);
This is all terribly complicated and I feel like there’s a better solution for 2d multi-pass deferred rendering.
The ultimate objective is to have normal maps in a 2d game (which does not need all of this) but also support an insane amount of lights and other effect passes I come up with (I plan on using shaders to show physical damage to ships using some kind of damage heightmap and a damage texture).