Jump to content

Fading RenderTexture


MichaelZ
 Share

Recommended Posts

Hello,

I'm trying to implement a fading buffer to use for rendering particle "trails". The effect is pretty much what is described here. Specifically the fiddle there makes it clear quickly.

The core idea behind the approach is:

  1. Allocate 2 buffers (renderTextures)
  2. Render particles to active texture
  3. For fading then: clear the alternative texture, render the primary texture to the secondary one with alpha (the fade), swap primary/alt textures.
  4. Render active renderTexture to screen (after everything else that goes under it)
  5. Loop back to 2 and repeat...

I have this working pretty much, but I am fighting 2 things: performance + weird bug that occurs only on-device (iPad3/4 ios8/9). Due to this I wanted to get some feedback on my approach. 

I'd like to ask 2 things. First, in the setup above, there are 2 options I can image for swapping the textures: either swap the textures on the sprites objects... or swap the sprites associated with them. Since it would be annoying to add/remove the wrapper sprites on each "swap" I choose to instead simply swap the texture references on the sprites. Any red flags around this? Seems ok to me. 

The 2nd question... is my PIXI setup around the high-level approach correct (using 2 renderTextures and 2 wrapper Sprites)? 

And of course, if anyone can think of a more optimal approach I'm all ears. It seems no matter how you slice it the "fade" requires touching each pixel in the buffer and therefore will be an expensive operation. The totally different approach of storing the trail history and rendering it out per frame.... no. 

Sincerely,

Michael Z.

 

 

Link to comment
Share on other sites

Sure, here is one of the bunny examples hacked with this approach (so you can copy-paste this into any of the examples):

var renderer = PIXI.autoDetectRenderer(800, 600,{backgroundColor : 0x1099bb});
document.body.appendChild(renderer.view);

var currentTextureIsA;
var renderTextureA;
var renderTextureB;

var displaySprite;
var bufferSprite;

// create the root of the scene graph
var stage = new PIXI.Container();

// create a texture from an image path
var texture = PIXI.Texture.fromImage('_assets/basics/bunny.png');

// create a new Sprite using the texture
var bunny = new PIXI.Sprite(texture);

// center the sprite's anchor point
bunny.anchor.x = 0.5;
bunny.anchor.y = 0.5;

// move the sprite to the center of the screen
bunny.position.x = 200;
bunny.position.y = 150;

//stage.addChild(bunny);

currentTextureIsA = true;
        
renderTextureA = new PIXI.RenderTexture(renderer, 800, 600);
renderTextureB = new PIXI.RenderTexture(renderer, 800, 600);

displaySprite = new PIXI.Sprite(renderTextureA);
displaySprite.alpha = 1.0;

bufferSprite = new PIXI.Sprite(renderTextureB);
bufferSprite.alpha = 0.9;

stage.addChild(displaySprite);

// Needed because otherwise our bunny doesn't move... ???
var dummyContainerForBunny = new PIXI.Container();
dummyContainerForBunny.addChild(bunny);

// Needed because otherwise the alpha is not honored when rendering to texture... ???
var dummyContainerForBuffer = new PIXI.Container();
dummyContainerForBuffer.addChild(bufferSprite);

// start animating
animate();
function animate() {
    requestAnimationFrame(animate);

    // just for fun, let's rotate mr rabbit a little
    bunny.position.x = (bunny.position.x + 1);
    bunny.position.y = (bunny.position.y + 1);
  
    renderTextureA.render(dummyContainerForBunny);
  
  	var otherTexture = (currentTextureIsA === true) ? renderTextureB : renderTextureA;

    // Clear it to start fresh
    otherTexture.clear();

    // Render our current sprite into our fresh texture, but with some alpha (fade)
    bufferSprite.texture = (currentTextureIsA === true) ? renderTextureA : renderTextureB;
    otherTexture.render(dummyContainerForBuffer);
    displaySprite.texture = otherTexture;

    // Other texture with fade now becomes our main texture with this flip!
    currentTextureIsA = !currentTextureIsA;

  
    // render the container
    renderer.render(stage);
}

 

Side-note: any easy way I can get this to run on an iPad (my own code in the samples)? I'm trying to reproduce a device-only bug with a minimal example (and think this should be it). 

Link to comment
Share on other sites

Ended up adding a scale factor to my trails buffer size since my trails don't need to be high res (and are small). The hope here was to optimize step 3 due to the smaller buffer size. The performance results on iPad4 were marginally better. This probably makes sense as there are also steps 2 and 4 which don't really get much better with the smaller buffer size. 

More importantly though this allowed me to get the buffer size under 2048 on iPad and this magically makes a very strange critical bug go away. Using a ratio of 0.5 and my buffer is roughly screen size.

Thanks for the quick sanity checks!

Link to comment
Share on other sites

If you only need trailing then one option would be to say rendereroptions.clearBeforeRender = false; Then just draw some fullscreen 1px sprite with alpha and you have trailing rendering done without bufferswapping.

If you want to render anything else without trails then this option is not going to work.

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