LaptevPavel

fromCanvas as texture

Recommended Posts

Hello, guys! Who could help me with that issue? I want to update canvas background texture with a new image capturing full canvas with all elements trough reguestainmationframe on mousedown (bake canvas to image and replace the old texture with new bake canvas texture every time) achieve some kind of "smudge tool" like in Photoshop. But when I trying to call fromCanvas method I get an only black rectangle. I'm a little confused I mixed up something, but don't know what. Thank you!

 

Share this post


Link to post
Share on other sites
49 minutes ago, ivan.popelyshev said:

Ah, now I understand what you want. We need two separate renderTexture to do that trick :) Also, we need a loader instead of fromImage(). I'll write you code later. We'll make an example out of it.

@ivan.popelyshev Many thanks! I will be waiting, even a clue or direction in which way I need to dig will be great :-)

UPD. Sorry, I attached the wrong pen above that's why I removed it. I don't know why but my pen wasn't saved :-)

This is right pen :-)

 

Share this post


Link to post
Share on other sites

OK, put that thing into pixi-examples, or make fiddle out of it:

var app = new PIXI.Application(800, 600, {autoStart: false} );
document.body.appendChild(app.view);

var rt = [];
for (var i=0;i<2;i++) rt.push(PIXI.RenderTexture.create(app.screen.width, app.screen.height));
var current = 0;

var bg;
var brush;

app.loader.add('bg', 'https://raw.githubusercontent.com/pixijs/examples/gh-pages/required/assets/bkg-grass.jpg');
app.loader.add('one', 'https://raw.githubusercontent.com/PavelLaptev/test-rep/master/one.png');
app.loader.load(function(loader, resources) {
    var tempBg = new PIXI.Sprite(resources.bg.texture);
    tempBg.width = app.screen.width;
    tempBg.height = app.screen.height;

    app.renderer.render(tempBg, rt[0]);

    bg = new PIXI.Sprite(rt[0]);
    app.stage.addChild(bg);
    brush = new PIXI.Sprite(resources.one.texture);
    app.stage.addChild(brush);
    brush.anchor.set(0.5);

    bg.filters = [new PIXI.filters.DisplacementFilter(brush)];

    app.stage.interactive = true;
    app.stage.on('pointerdown', onPointerDown);
    app.stage.on('pointerup', onPointerUp);
    app.stage.on('pointermove', onPointerMove);

    app.start();
});

function snap() {
    app.renderer.render(app.stage, rt[1 - current]);
    bg.texture = rt[1 - current];
    current = 1 - current;
}

var dragging = false;

function onPointerDown(event) {
    dragging = true;
    onPointerMove(event);
}

function onPointerMove(event) {
    brush.position.copy(event.data.global);
    if (dragging) snap();
}

function onPointerUp() {
    dragging = false;
}

 

Now you can see that your texture doesnt have 0x808080 at the edge as its supposed too, and that's why whole grass field is moved too. I think you can deduce how it works without my help, if not please post the questions here.

Of course its not perfect: my demo makes snap() only on mouse move, and instead you should add something to ticker.

Share this post


Link to post
Share on other sites

@ivan.popelyshev Thank you again. I have nooby questions to better understand what's going on in code :-) Could you some things when you will have time. I marked questions on the picture below.

1) It's array where we push updated texture on mouse move?

2) We are pushing new textures here, but why i<2 ?

3) Why we need this current var?

4) Is it a texture for the very first canvas loading?

5) Here we are rendering updated texture?

Thank you!

code-screen-questions.png

Share this post


Link to post
Share on other sites

The issue I was trying to avoid is to render renderTexture on itself, that's why I used two of them. However, we use filter, and it uses one more temporary buffer, so, one texture will be enough for task :)

"current" is the number of the render texture we use right now.

4) is initialization of the texture, its possible only when bg is loaded , so we really need a loader there.

Share this post


Link to post
Share on other sites

@ivan.popelyshev Sorry for bothering you again :-) But I think you know answers for all PIXI questions :-) I made three containers with different RGB channels and applied for last two blend mode to achieve "normal" picture. But now I'm struggling how to snap all 3 containers into one. Might be I need to create the fourth container and capture all 3 containers into 4, but how? :-) Or use pixiRGBsplitFilter and mask it somehow :-) Might be you know in which direction I need to dig? Thank you!

I trying to achieve some kind of this effect

 

Share this post


Link to post
Share on other sites

Also, the easiest way to me seems like to render multiple containers, and then just blend them, but I didn't find how to do this.

app.renderer.render(containerRed, rt[1 - current]);
app.renderer.render(containerGreen, rt[1 - current]);
app.renderer.render(containerBlue, rt[1 - current]);

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now