Hi all !
I'm having some issues with getting tilemap layers to render to textures if added to custom groups instead of the default game.world.
Context : I'm working on a top-down pixel-art a-rpg (think Zelda 3-like). I have a mix of tilemap layers and sprites. Nothing too fancy.
Goal : I want to implement a custom upscaling shader (e.g. hq4x). I'm changing my scene to draw layers and sprites to a texture, so that I can use that texture with my custom shader.
Progress : I can easily get sprites to render to my texture, and using my shader to display that texture also works well
Problem : To avoid overhead of individual draw calls per sprite/layer, I use a top-level Group container ; but I can only get tilemap layers to appear if they are added to the game.world and not to my top-level container :-?
In my preload() : nothing exciting, just the tilemap (Tiled json), some images/spritesheets, and a shader/fragment
In my create() :
// The top-level container to hold display objects this.m_group = new Phaser.Group(this.game, null); // The render texture where I want all display objects to appear this.m_renderTarget = this.game.add.renderTexture(g_screenWidth, g_screenHeight, "RenderTarget"); // The actual sprite using the render texture let rtSprite : Phaser.Sprite = this.game.add.sprite(0, 0, this.m_renderTarget); // Sprite test ; this works nicely let sprite : Phaser.Sprite = this.game.make.sprite(0, 0, "Player"); this.m_group.add(sprite); // Layer test ; this does NOT work this.m_map = this.game.make.tilemap("Overworld"); this.m_map.addTilesetImage("Tileset", "Tileset"); this.m_layer = this.m_map.createLayer("Layer", g_gameWidth, g_gameHeight, this.m_group);
(I've excluded the shader/filter setup, not relevant for the problem)
In my Update() :
this.m_renderTarget.renderXY(this.m_group, 0, 0);
I was thinking using the 4th parameter "parent" of the createlayer method to add it to top-container would be sufficient. This is not the case.
The only way I found to get my layer to appear on my render texture is 1. add the layer to the default game.world, 2. turn off the layer.renderable (because I don't actually want it in the default scene), 3. create a sprite using the layer texture. 4. add the sprite to my container group. Which looks like :
this.m_layer = this.m_map.createLayer("Layer"); this.m_layer.renderable = false; let sprite : Phaser.Sprite = this.game.make.sprite(0, 0, this.m_layer.texture); this.m_group.add(sprite);
While this is functional, this sounds overly convoluted and non-intuitive, so surely I'm not using the whole thing correctly ! The layer should behave as a display object and I don't understand why it needs to be treated differently :-?
Additionally, I tried having a separate rendertexture.renderXY() call for the layer (this.m_renderTarget.renderXY(this.m_layer, 0, 0, true);) ; same problem, the layer only appears if added to the game.world and not to any other container.
Any idea what I'm missing or doing wrong ? Any help would be greatly appreciated !