Jump to content

Affine vs perspective bilinear transformation


toowren
 Share

Recommended Posts

Let's say there is an arbitrary composite (wall.png) shape in PixiJS.

 

I need to project a texture onto it by some kind of a grid warp in a way, so the result would be similar to output.png.

 

I have tried to do it via PIXI.SimplePlane and it seems that default projection algorithm at this framework is affine transformation. And the result have to be based on quad bi-linear projection.

 

let pattern64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAEACAIAAABK8lkwAAAACXBIWXMAAAAnAAAAJwEqCZFPAAAFIGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjItMTAtMDdUMTk6MDI6NTErMDM6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjItMTAtMDdUMTk6MDI6NTErMDM6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIyLTEwLTA3VDE5OjAyOjUxKzAzOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0Mjc0YWNkZS05OTYwLTQ3YTQtOTQyOS1kMGQ0MmZkNzAwZDIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDI3NGFjZGUtOTk2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";

    
const app = new PIXI.Application({ width: 512, height: 324, antialias: true });
document.body.appendChild(app.view);

app.loader.add('pattern', pattern64).load(inits);

function inits() {

    const graphics = new PIXI.Graphics();

    let path = [34, 100, 176, 100, 176, 224, 34, 224];

    graphics.lineStyle(0);
    graphics.beginFill(0xBCBCBC, 1);
    graphics.drawPolygon(path);
    graphics.endFill();

    path = [176, 100, 258, 60, 258, 264, 176, 224];

    graphics.lineStyle(0);
    graphics.beginFill(0xCDCDCD, 1);
    graphics.drawPolygon(path);
    graphics.endFill();

    path = [258, 60, 422, 104, 422, 220, 256, 264];

    graphics.lineStyle(0);
    graphics.beginFill(0x606060, 1);
    graphics.drawPolygon(path);
    graphics.endFill();

    path = [422, 104, 478, 104, 478, 220, 422, 220];

    graphics.lineStyle(0);
    graphics.beginFill(0x909090, 1);
    graphics.drawPolygon(path);
    graphics.endFill();

    app.stage.addChild(graphics);

    const texture = app.loader.resources.pattern.texture;

    const plane = new PIXI.SimplePlane(texture, 5, 3);
    app.stage.addChild(plane);

    let buffer = plane.geometry.getBuffer('aVertexPosition');

    // graphics.beginFill(0xFF0000);
    // graphics.drawRect(buffer.data[20], buffer.data[21], 8, 8);
    // graphics.endFill();

    //manually set just for this demo
    buffer.data[0] = 34;
    buffer.data[1] = 100;
    buffer.data[2] = 176;
    buffer.data[3] = 100;
    buffer.data[4] = 258;
    buffer.data[5] = 60;
    buffer.data[6] = 422;
    buffer.data[7] = 104;
    buffer.data[8] = 478;
    buffer.data[9] = 104;

    buffer.data[10] = 34;
    buffer.data[11] = 162;
    buffer.data[12] = 176;
    buffer.data[13] = 162;
    buffer.data[14] = 258;
    buffer.data[15] = 162;
    buffer.data[16] = 422;
    buffer.data[17] = 162;
    buffer.data[18] = 478;
    buffer.data[19] = 162;

    buffer.data[20] = 34;
    buffer.data[21] = 224;
    buffer.data[22] = 176;
    buffer.data[23] = 224;
    buffer.data[24] = 258;
    buffer.data[25] = 264;
    buffer.data[26] = 422;
    buffer.data[27] = 220;
    buffer.data[28] = 478;
    buffer.data[29] = 220;

    buffer.update();

}

 

The code returns output2.png

 

Yes, PixiJS has additional projections plugin (https://pixijs.io/examples/#/plugin-projection/quad-homo.js), but it seems that output could be controlled just by four corner points. In my case, I need more. At least 10 or even 15.

 

If I couldn't use projection plugin, maybe there is a way to implement a custom shader for aVertexPositions and UVs?!

 

 

 

wall.png

output.png

output2.png

Link to comment
Share on other sites

  • toowren changed the title to Affine vs perspective bilinear transformation

but it seems that output could be controlled just by four corner points. In my case, I need more. At least 10 or even 15.

You are , honestly, first or second user who needs bilinear. I made that demo as a way to show "we can do it". I couldnt do the whole way with mesh because of time. I had to stop somewhere: I didnt know whether there are ppl who need it, and there were so many other features in other plugins that were needed.

How to proceed? There are several ways, I suppose:

1. you do it yourself, using my bilinear shader. Yes, shader needs adjustments - need to move all those bilinear things into arguments instead of uniforms, either re-set uniforms and call shader for each quad separately.

2. post a discussion with a bounty on it in https://github.com/pixijs/pixijs/discussions , and i'll take it
3. try to persuade someone in pixijs discord to do it.

Edited by ivan.popelyshev
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...