Draw CCParticleSystem on CCRenderTexture

Forums Programming cocos2d support (graphics engine) Draw CCParticleSystem on CCRenderTexture

This topic contains 7 replies, has 2 voices, and was last updated by  aramk 2 years, 2 months ago.

Viewing 8 posts - 1 through 8 (of 8 total)
Author Posts
Author Posts
January 27, 2012 at 6:48 am #238739

aramk
Participant
@aramk

How would one go about adding a CCRenderTexture into a CCParticleSystem and draw the CCParticleSystem into the CCRenderTexture, then draw this texture instead of the CCParticleSystem. This will allow a blend function to be used between the CCParticleSystem and the CCRenderTexture. The reason being this:

http://gamedev.stackexchange.com/questions/22989/how-can-i-achieve-a-good-fire-effect-with-alpha-blending-and-particles/22990#22990

Here’s what I have in the draw: of CCParticleSystem:



-(void) draw {
CCRenderTexture *rte = [CCRenderTexture renderTextureWithWidth:200 height:300];
[rte beginWithClear:0 g:0 b:0 a:0.5];
[super draw];
[rte end];
[rte visit];
}

Whatever I’m doing is slightly wrong, because the CCParticleSystem texture drawn onto the CCRenderTexture is moving across the CCParticleSystem as the CCParticleSystem moves around. This is probably something to do with draw and how it works with positions. Is there a way to still do all this inside the CCParticleSystem (so I can still keep it all in one object), or do I have to make a second class to store both the CCRenderTexture and also the CCParticleSystem?

January 27, 2012 at 10:15 am #363603

Birkemose
Keymaster
@birkemose

It isnt nearly as complicated as you think :)

The particle system will obey the coordinate system of the render texture. If you have a render texture of 100 * 100, setting the position of the particle system to 50, 50, will place it in the center.

You do not visit the render texture. To draw it, you simply add it as a child to ex your layer.

You do also not create the render texture each frame, or call visit inside a draw method. This is very bad for performance. In stead you create a single instance of the render texture, and place rendering in you scheduled frame tick.

Something like this

// init of class

rte = [ CCRenderTexture renderTextureWithWidth:200 height:300 ];
rte.position = RTE_POSITION;
[ self addChild: rte ];

// manually retain the particles as you dont add them to a container
particles = [ [ CCParticleSystemQuad particleWithFile:PARTICLE_FILE ] retain ];

And in update

-( void )update:( ccTime )dt {

[ particles update:dt ];

[ rte beginWithClear ];
[ particles visit ];
[ rte end ];

}

January 27, 2012 at 10:29 am #363604

aramk
Participant
@aramk

I had to use [child onEnter] to trigger the particle into rendering. I don’t know why, since .active == YES. Also, I call [rt beginWithClear:0 g:0 b:0 a:0];. So I have a similar setup to what you’ve outlined and I’ve now got this:

Both are the same particle. The left one is a child of the layer. The right one is first drawn onto the CCRenderTexture and then this is added to a CCNode, which is added to the layer. For some reason, the right one differs. Both particles use the same blend function and I have also tried adding the same particle into the CCNode and it looks identically to the left particle. So something is not quite right with drawing the particle onto the CCRenderTexture. Would you have any idea what could cause it?

January 27, 2012 at 10:31 am #363605

aramk
Participant
@aramk

Even weirder than that, I can even add an Icon.png into the CCRenderTexture, and it looks fine:

So what else could cause the particle to be different when adding it to a texture :S

EDIT: reading a bit further into this, could it be a premultiplied alpha problem?

January 27, 2012 at 11:43 am #363606

Birkemose
Keymaster
@birkemose

I guess it is because you render particles on a surface with no alpha. I think, that if you changed particle blending to additive, that it would look more the same.

I am not sure how you can avoid that.

January 27, 2012 at 12:03 pm #363607

aramk
Participant
@aramk

I sort of understand that the transparency is causing an issue, but don’t I render the particles first and then add then onto a transparent surface? Wouldn’t this leave the resulting texture the same as the one on the left?

January 27, 2012 at 12:45 pm #363608

Birkemose
Keymaster
@birkemose

No. When you render the particles, in normal blending, they blend with the underlaying image. If that image has alpha = 0, it will look different from an image with alpha = 1.

In additive blending, you just add the color + alpha of the particle system. This often causes particle systems like fire to “whiten out” because every pixel finally adds to full white, full opacity.

January 27, 2012 at 2:03 pm #363609

aramk
Participant
@aramk

Yep, I got it. The difference is that a normal particle drawn on the screen with GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA will cut out from the black background, whereas if that background was alpha = 0, then it wouldn’t have anything to cut out of and would appear as only the coloured parts of the particle, missing all the black. You can see this in my screenshot.

The trick was to first grab this black by making a CCRenderTexture and drawing the particles on it with GL_SRC_ALPHA, GL_ZERO. This would leave just the background and remove all the alpha that the particles would take up. I made this a green texture with [rt1 beginWithClear:0 g:1 b:0 a:1]; just for fun, since it’ll be used to get rid of the unused black and nothing else.

I then created another texture with [rt2 beginWithClear:0 g:0 b:0 a:0]; and drew the particles on it with the usual GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA of alpha blending.

Then I created my main texture with [rt beginWithClear:0 g:0 b:0 a:1] and drew this black texture onto it. I then drew the green one with GL_ZERO, GL_ONE_MINUS_SRC_ALPHA and I got the same result as usual.

However, I only did this because the reason behind it was bugging me. Now that I’ve figured that out, I can get back to making the effect I was after: an additive blend flame particle but without blending it into the background :)

Thanks a lot for your help!

Viewing 8 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic.