Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Mask based on renderTarget dont update correctly #10491

Open
Makio64 opened this issue Apr 29, 2024 · 2 comments
Open

Bug: Mask based on renderTarget dont update correctly #10491

Makio64 opened this issue Apr 29, 2024 · 2 comments
Assignees
Labels
👯‍♀️ Needs Reproduction Very common: basically need an example that reproduces the issue so that it's easier to identify.

Comments

@Makio64
Copy link

Makio64 commented Apr 29, 2024

Current Behavior

I got an interesting bug while making a reveal effect :

I'm drawing into a RenderTexture and I used a sprite base on it as a mask on another sprite
this.drawingSurface2 = new Sprite(this.renderTexture);
this.foregroundImage.mask = this.drawingSurface2;

When the sprite is assigned to a mask like this.foregroundImage.mask = this.drawingSurface2;

  • then the mask will not be updated in the futur and the drawing effect not work
  • if some drawing was already done they will show but will not be update in the futur

The workaround i'm using here is to add two sprite based on the same renderTexture, one with alpha=0 and the other as the mask.
This way the renderTarget is correctly updated and the mask is working well :

// workaround
Stage2d.add(this.drawingSurface);
Stage2d.add(this.drawingSurface2);
this.drawingSurface.alpha=0
this.drawingSurface2.alpha=1
this.foregroundImage.mask = this.drawingSurface2;

Full example

// full example
import { Assets, Container, Sprite, Graphics, RenderTexture, Point, Texture } from "pixi.js"

export default class ImageRevealGame extends Container {
	constructor() {
			super();
			this.setupImages();
			this.setupMask();
			this.setupInteraction();
	}

	setupImages() {
			this.backgroundImage = new Sprite(Assets.get('game5-aquamonster'));
			this.backgroundImage.scale.set(0.5);
			this.foregroundImage = new Sprite(Assets.get('game5-biscuit'));
			this.foregroundImage.scale.set(0.5);
			this.addChild(this.backgroundImage);
			this.addChild(this.foregroundImage);
	}

	setupMask() {
			this.renderTexture = RenderTexture.create({
					antialias: true,
					width: this.foregroundImage.width,
					height: this.foregroundImage.height,
			});
			this.drawingSurface = new Sprite(this.renderTexture);
			this.drawingSurface2 = new Sprite(this.renderTexture);
			Stage2d.app.renderer.render({
				container:new Container(),
					target: this.renderTexture,
					clear: true,
			});
			Stage2d.add(this.drawingSurface);
			Stage2d.add(this.drawingSurface2);
			this.drawingSurface.alpha=0
			this.drawingSurface2.alpha=1
			this.foregroundImage.mask = this.drawingSurface2;

			this.brush = new Graphics().circle(0, 0, 20).fill({color: 0xffffff, alpha: 1});
			this.lineFill = new Graphics();
			this.prevPosition = new Point();
	}

	setupInteraction() {
			this.drawingSurface.interactive = true;
			this.drawingSurface.on('pointerdown', this.startDrawing, this);
			this.drawingSurface.on('pointerup', this.stopDrawing, this);
			this.drawingSurface.on('pointerupoutside', this.stopDrawing, this);
			this.drawingSurface.on('pointermove', this.draw, this);
	}

	startDrawing(event) {
			this.drawing = true;
			this.prevPosition.copyFrom(event.data.getLocalPosition(this.drawingSurface));
			this.draw(event, true);
	}

	stopDrawing() {
			this.drawing = false;
	}

	draw(event) {
			if (!this.drawing) return;
			let position = event.data.getLocalPosition(this.drawingSurface);
			this.brush.position.set(position.x, position.y);

			Stage2d.app.renderer.render({
				container:this.brush,
				target: this.renderTexture,
				clear: false,
			});


			this.lineFill.clear()
					.moveTo(this.prevPosition.x, this.prevPosition.y)
					.lineTo(position.x, position.y)
					.stroke({texture:Texture.WHITE,alpha:1, color:0xffffff, width:40})

			Stage2d.app.renderer.render( {
				container: this.lineFill,
				target: this.renderTexture,
				clear: false,
			});

			this.prevPosition.copyFrom(position);
	}
}

Expected Behavior

Not having to add the sprite twice and the mask still correctly updated.

Steps to Reproduce

  • Assign a sprite based on a renderTexture to another sprite. it will update only the first time and then stop updating.
  • add another sprite on the scene based on the same renderTexture with alpha 0, now everything working

Environment

  • pixi.js version: 8.10
  • Browser & Version: all
  • OS & Version: all

Possible Solution

No response

Additional Information

No response

@GoodBoyDigital
Copy link
Member

gonna take a look at this guy today! 👍

@GoodBoyDigital
Copy link
Member

heya, tried recreating this in the playground - can you verify im doing the right thing pls?

Cheers man!

@Zyie Zyie added 👯‍♀️ Needs Reproduction Very common: basically need an example that reproduces the issue so that it's easier to identify. 🧰 Needs Verification PRs require an example to prove that it was fixed. Can also be a unit-test. and removed 👯‍♀️ Needs Reproduction Very common: basically need an example that reproduces the issue so that it's easier to identify. 🧰 Needs Verification PRs require an example to prove that it was fixed. Can also be a unit-test. labels May 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👯‍♀️ Needs Reproduction Very common: basically need an example that reproduces the issue so that it's easier to identify.
Projects
None yet
Development

No branches or pull requests

3 participants