phaser icon indicating copy to clipboard operation
phaser copied to clipboard

RenderTexture does not respect masking of drawn GameObject.

Open OdinvonDoom opened this issue 3 years ago • 3 comments

Phaser Version: 3.55.2 Operating system: Windows 10

Description

Simply as titled, after creating a masked object and drawing it to a renderTexture, what's drawn is not masked.

To be more specific, I'm trying to apply a tiled texture over another texture, then use the renderTexture to take a snapshot, to then cache the new texture and use as required. Every part of the process works except that when the masked texture is drawn, it's no longer masked.

Of course I would expect that what's drawn to the renderTexture is the same as what's drawn to the screen when the orinigal objects are added to the scene.

Example Test Code

// Base image, added to scene just to confirm it works
const baseTexture = scene.make.image({ key: "someTexture" }, true);
const srcImg = baseTexture.texture.getSourceImage();
const halfW = srcImg.width * 0.5;
const halfH = srcImg.height * 0.5;

// Image to mask, also added to scene.
const tileSprite = scene.make.tileSprite({ key: "someTileTextureKey",  width: srcImg.width,  height: srcImg.height }, true);

// Apply mask, everything works perfectly well up to his point! The masking is spot-on.
const mask = new BitmapMask(scene, baseTexture);
tileSprite.setMask(mask);

// Set up render texture, also added to scene to see it's output before snapshot.
const config = { width: srcImg.width, height: srcImg.height };
const rt = scene.make.renderTexture(config, true); 

// Renderable objects are drawn, but masking of "tileSprite" not respected.
rt.draw(baseTexture, halfW, halfH);
rt.draw(tileSprite, halfW, halfH);

// Extra bit not specific to bug, but just to emphasize, the snapshot is taken and cached successfully, but of the unmasked objects. It looks the same as the renderTexture added to scene, as it should, but both are inaccurate to what's expected.
rt.snapshot(imgElem => {
    scene.textures.addImage("newTexureName", imgElem as HTMLImageElement);
    Callback("newTexureName");      
});

Additional Information

It's such a straight-forward and obvious omission, I thought perhaps it was a known impossibility in the capability of the renderTexture, but have found no such warnings in the documentation.

I tried to force some update/render calls on the "tileSprite" before it gets drawn, thinking it might need at least 1 frame for the mask to be active? I tied wrapping the draw calls in a setTimeout delay for the same reason, just sanity testing.

Am I wrong in expecting the mask to be in place on the renderTexture?

OdinvonDoom avatar Aug 24 '22 21:08 OdinvonDoom

This is correct, masking is a renderer feature, so isn't applied to RenderTextures (or anything else, actually).

I'll flag it as a Feature Request for now.

photonstorm avatar Aug 26 '22 15:08 photonstorm

Sounds good, thanks.

I thought it would work specifically because of what is working, which is shading. I've had no problem adding a pipeline to a given gameobject and using a custom shader to say, tint the colour, then drawing that to the renderTexture, and successfully getting a snapshot of it, now tinted. That's allowed me to dynamically generate "team coloured" versions of some generic characters/objects.

To that end, I'm now trying to either write a custom shader to do the masking myself, or use the existing BitmapMaskPipeline directly, presuming that I can make it work as I have with the tinting pipeline/shader, but only having some difficulty in that only have a very tenuous grasp on how the entire set of pipelines work, thus am struggling to set default shader attributes like "uMaskSampler"; I might find success in overriding a "SinglePipeline" instead and passing a secondary texture through "setPipelineData", but I'm obviously spinning my wheels a bit here trying to figure this out without "re-inventing the wheel" so to speak.

OdinvonDoom avatar Aug 26 '22 16:08 OdinvonDoom

Would probably be easier to implement your own RenderTexture render function that incorporated what the WebGL Renderer does: https://github.com/photonstorm/phaser/blob/master/src/renderer/webgl/WebGLRenderer.js#L2576-L2632

I.e. monkeypatch out this with a variation of the Renderer approach: https://github.com/photonstorm/phaser/blob/master/src/gameobjects/rendertexture/RenderTexture.js#L1212-L1237

photonstorm avatar Aug 26 '22 16:08 photonstorm

Just to say that I'm closing this feature request as it's now possible to draw masked sprites to Dynamic Textures (and by proxy, Render Textures).

photonstorm avatar Nov 21 '22 21:11 photonstorm