Jump to content

Understanding RenderTexture to create a mirror effect


amadeus
 Share

Recommended Posts

I am trying to wrap my head around RenderTexture and how to use it for a mirror effect in a small scene I am creating, but I think I am missing something pretty major in how I am attempting to use it.

 

The basic premise is this: I want to render out a good portion of a scene (buildings, vehicles, lights) then I want to render a portion of that to a RenderTexture, and then render that RenderTexture vertically flipped and underneath, to create a reflection over water.

 

To begin, I have created a small scene that I can experiment with the effect.

 

The code for that scene is pretty simple:

 



States.Menu = {

images: {
'bg-gradient': 'media/menu/bg-gradient.png',
'bg-building': 'media/menu/bg-building.png'
},

preload: function(game){
var key;

for (key in this.images) {
game.load.image(key, this.images[key]);
}
},

create: function(game){
this.background = game.add.sprite(0, 0, 'bg-gradient');
this.background.width = game.camera.width;

this.buildings = game.add.sprite(0, 0, 'bg-building');
this.buildings.alpha = 0.2;
}

};

This scene rendered out looks like this (forgive the crappy assets, just testing):

 


 

Next, I set out just simply add a RenderTexture on top of this, which, if I am understanding how this all works properly, should not have any discernible difference. That updated code looks like this:

 



States.Menu = {

images: {
'bg-gradient': 'media/menu/bg-gradient.png',
'bg-building': 'media/menu/bg-building.png'
},

preload: function(game){
var key;

for (key in this.images) {
game.load.image(key, this.images[key]);
}
},

create: function(game){
this.background = game.add.sprite(0, 0, 'bg-gradient');
this.background.width = game.camera.width;

this.buildings = game.add.sprite(0, 0, 'bg-building');
this.buildings.alpha = 0.2;

// Create mirrorTexture that is the same width, but not height
this.mirrorTexture = game.make.renderTexture(game.width, 154);
// Add a sprite to the world that uses this mirrorTexture
this.mirror = game.add.sprite(0, 0, this.mirrorTexture);
},

update: function(game){
// Render scene to mirrorTexture
this.mirrorTexture.renderXY(game.stage, 0, 0);
}

};

However, when I do this, I get the following results:

 


 

This is not even close to what I would remotely assume to see. I haven't even applied any sort of scaling transforms to the renderTexture, yet it's flipped. Furthermore it's blacking out everything that is NOT the mirrorTexture already.

 

I am not wholly clear on how the update/render pipeline works in Phaser. So it's certainly possible I am getting myself in some weird rendering state that I don't understand. I've tried digging into the source, but when it's so deeply coupled with PIXI it's a bit hard to follow the inheritance pathways.


Link to comment
Share on other sites

First of all you should clear the render texture before drawing to it again. Pass a 'true' flag as the fourth parameter of #renderXY

 

Regarding your problem:

In webgl the pixi stage is transformed and aligned to the viewport center. You can see it yourself in WebGLRenderer.js in the pixi source.

https://github.com/GoodBoyDigital/pixi.js/blob/88661f02228f03e1698bbe2e16f4fc47a1948e71/src/pixi/renderers/webgl/WebGLRenderer.js#L404 (Pixi v2.2)

 

On the other site you will lose all transformations of a display object when you render it to a another texture.

(see: http://www.goodboydigital.com/pixijs/docs/classes/RenderTexture.html).

 

That should be the reason why you see those strange effects. You simply loose the webgl stage transformations. If your force phaser to use canvas everything should be fine. Therefore you should introduce a new group which will hold all your sprites but the mirrored one. 

 

See this:

http://jsfiddle.net/georgie/jcxguv1c/2/

 

The group 'renderGroup' is holds the world. With this all transformation & scalings of the containing sprites are preserved. 

 

Regards George

Link to comment
Share on other sites

Thanks so much for the detailed response, that was precisely my problem and your fix worked perfectly. I was aware of the clearing argument, but while I was playing around with it, trying to get it to work, I had it disabled as part of a test and thus was reflected here in the code example.

 

It's all starting to make a bit more sense.

 

I guess one piece I am still not quite clear on, is the update/render relationship. In my head, update shouldn't actually be handling any rendering pieces, so the fact that we are putting #renderXY inside the update method seems a bit weird.

 

I am also unclear on the rendering order of things.

 

As it stands, both background and sprite must be rendered first, then the state.update is called, which creates the mirror?

 

Or are we just creating some form of render queue, which will get rendered later in a render cycle?

 

Is there somewhere this is more clearly documented that I could read?

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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