Jump to content

Using Sprite.filters to replace Sprite.shader


Taz
 Share

Recommended Posts

The docs say that Sprite.shader "will be used to render the sprite", but this doesn't work for Pixi V4 so I'm using Sprite.filters instead. I set filterArea.width and filterArea.height once and then each frame I set filterArea.x and filterArea.y to sprite.x and sprite.y. But IDK if this is good practice or is there a better performing way?

Here's example code that shows what I mean:

var app = new PIXI.Application({width: window.innerWidth, height: window.innerHeight});
document.body.appendChild(app.view);

// Create sprite
var sprite = new PIXI.Sprite();
sprite.filterArea = new PIXI.Rectangle(
    sprite.position.x,
    sprite.position.y,
    100,
    100
);
app.stage.addChild(sprite);

// Stop application wait for load to finish
app.stop();

PIXI.loader.add('shader', 'shader.frag')
    .load(onLoaded);

var filter;

// Handle the load completed
function onLoaded (loader,res) {

    // Create the new filter, arguments: (vertexShader, fragmentSource)
    filter = new PIXI.Filter(null, res.shader.data);

    // Add the filter
    sprite.filters = [filter];

    // Resume application update
    app.start();
}

// Animate
app.ticker.add(function(delta) {
    sprite.x += 1.5 * delta;
    sprite.filterArea.x = sprite.x;

    filter.uniforms.customUniform += 0.04 * delta;
});

 

Link to comment
Share on other sites

Is there please any example of a shader plugin that isn't filtering an existing texture? I just want to programmatically draw the texture from scratch each frame using my shader, but the pixi plugin example is instead clamping an existing texture which looks like a very different use case so IDK how to proceed... For example a simple plugin that draws a circle based on radius and color (which can be set each frame) or anything along those lines in terms of use case?

Link to comment
Share on other sites

None of the tutorials on pixi shaders cover texture binding or vao or rendering stuff => PictureRenderer.js doesn't make sense to me, especially since it has the different use case of filtering...

Link to comment
Share on other sites

Yeah, and API will change for v5 so you dont have to memorize it that good. Just hack something until it works. If you share me your code somehow, i can help with it (github?) :)

Its good that I have made pixi-plugin-example, pixi-picture and pixi-tilemap, otherwise there would be NO EXAMPLES OF V4 SHADERS AT ALL. A number of users actually made their renderer plugins based on it.

Link to comment
Share on other sites

Thanks it's less intimidating when you put it like that :)

I wonder, with a plugin like this will there be a way to update the uniform values? Something akin to "sprite.shader.uniforms.color = newColor;" but using the plugin approach?

Link to comment
Share on other sites

No, you have to store values in sprite itself and then copy them to uniform in the renderer. May be add object "props" to sprite that have values you want to copy. The thing is, when renderer does "shader.uniforms.xxx=yyy", it actually calls "gl.uniform1f" or another webgl function. It can be done only when shader is bound and sprite is ready to be rendered.

Also , take a note that there's no batching in that example, only one sprite is drawn per one drawcall, 1000 sprites will slow it down.

Link to comment
Share on other sites

Thanks, just one more question before I dive in, do I bind to Texture.WHITE like this:

renderer.bindTexture(Texture.WHITE, 0, true);

BTW I'm hoping to experiment with something more minimal like 1 to 10 dynamic sprites per onscreen player (maybe 100 sprites or so altogether)

Link to comment
Share on other sites

Almost there I think :)

There's this part in PictureRenderer.js that uses the sprite's texture. But if I know the width and height  that I want to draw then can you please help refactor it to work with an empty sprite (without texture)? Right now it only works when sprite has a texture.

// desired size
var width  = 2 * sprite.pluginRadius;
var height = width;

// existing code from example below:

var uvs = sprite.texture._uvs;

//sprite already has calculated the vertices. lets transfer them to quad
var vertices = quad.vertices;
for (var i=0;i<8;i++) {
    quad.vertices[i] = sprite.vertexData[i];
}

//SpriteRenderer works differently, with uint32 UVS
//but for our demo float uvs are just fine
quad.uvs[0] = uvs.x0;
quad.uvs[1] = uvs.y0;
quad.uvs[2] = uvs.x1;
quad.uvs[3] = uvs.y1;
quad.uvs[4] = uvs.x2;
quad.uvs[5] = uvs.y2;
quad.uvs[6] = uvs.x3;
quad.uvs[7] = uvs.y3;
Link to comment
Share on other sites

OK so I just need to set quad.vertices based on desired width and height somehow, otherwise nothing draws when sprite is created without texture.

UPDATE: Nope, I set quad.vertices to the proper values and ignore quad.uvs, but still it doesn't draw anything unless I create the sprite with a texture.

Link to comment
Share on other sites

OK 2 things I learned and it works now:)

1. calculating vertices for rectangle is more straightforward than I thought

2. remove the check for !sprite.texture.valid to make it work without texture;)

Thanks for the tips along the way otherwise it would have taken *lots* longer to get going with shader plugin!

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...