2
\$\begingroup\$

This question builds upon the following question: How can I achieve a good fire effect with alpha blending and particles?

I want to achieve the visual effect of using SKBlendModeAdd on a black layer, but adding it to another (random) color background.

In the question posted above, it is explained how to do this: either by using an extra texture from which the alpha layer is removed or by using alpha premultiplication.

I've tried implementing both, but to no avail.

This probably has to do with the following:

A particle is a textured and colored node whose contents are blended into the framebuffer. Although there is no visible class representing particles added by the emitter node, you can think of a particle as having properties like any other object.

From Apple's Documentation

My guess is that because it's a framebuffer, the workaround solutions do not work for Sprite-Kit.

So how would I go about implementing this with SKTexture or SKSpriteNode ?

See below an example of the difference in colours between dark and light backgrounds. I would like to get the exact same colours on the light background as I get on the dark background (because on the dark background it actually looks like fire).

enter image description here

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I am not a programmer of IOS in particular, but it seems to me you are using a wrong blend mode in the case of that blue background. I do work with directx tough and I have learnt about its blend modes which are pretty much universal. You can find a very good and detailed summary about blend modes and their formulae here msdn.microsoft.com/en-us/library/windows/desktop/… . Hope that helps. \$\endgroup\$ – Bryan Arbelo - MaG3Stican Jul 7 '14 at 17:12
  • \$\begingroup\$ @MaG3Stican Of course I can change the blend mode, but then I also lose the nice effect that the 'Add' blend mode gives me. So I want to preserve the colours that are created when I use the 'add' blend mode on a black background, but use it as an overlay on another background. \$\endgroup\$ – Jean-Paul Jul 7 '14 at 18:24
3
+50
\$\begingroup\$

Wrapping the SKEmitterNode in an SKEffectNode allows the EmitterNode to be rendered into a framebuffer which is subsequently rendered onto the screen. I tested this out (after much push and pull of different nodes and scenes and views) and this results in the exact effect you want, where the Add blend mode is applied to a background that is not rendered onto the final scene, and the final scene's background is therefore not added to the values of the particles.

The only problem is that there is a dark outline to the "fire", but this is a result of the blended color being originally very dark (which is not noticeable against a dark background, but is very against a light background). This could be changed by refining the particle's color and various other properties, or accepted altogether.

Example:

SKEffectNode *effectNode = [[SKEffectNode alloc] init];

NSString *firePath = [[NSBundle mainBundle] pathForResource:@"Fire 3" ofType:@"sks"];
SKEmitterNode *fireEmitter = [NSKeyedUnarchiver unarchiveObjectWithFile:firePath];

fireEmitter.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

[effectNode addChild:fireEmitter];
[self addChild:effectNode];

The SKEffectNode renders all descendants onto a framebuffer, so it's as simple as adding the emitter as a child to the SKEffectNode. The position is arbitrary in the example.

This isn't very efficient, and there seems to be a performance problem with little else but the fire effect. Other than editing the emitter somewhat (lowering the birthrate, etc), I imagine the best way to get this effect would be a custom shader, with the downside that it would be much more complicated and not technically "SpriteKit" mechanics.

\$\endgroup\$
  • \$\begingroup\$ AWESOME! Would you be so kind to share your code (the working example) with me? Could you add it to your answer? I will then accept it. Thank you for your effort! \$\endgroup\$ – Jean-Paul Jul 8 '14 at 8:45
  • \$\begingroup\$ Thanks. Don't you have to specify the black background for the SKEffectNode ? Or does it use black automatically? And for the performance issue, could that be solved by setting the shouldRasterize feature to YES? \$\endgroup\$ – Jean-Paul Jul 8 '14 at 23:50
  • 1
    \$\begingroup\$ I didn't mess around with it too much, but the black background seems to be the default. You might not be able to use the same process exactly if you made an emitter that looked good with a Subtract blend mode on a white background, but you wanted it on a dark background. You can test it out and see for yourself. And, no, shouldRasterize was what I tried first, and the performance was awful. The particles change too often to save on performance with that. I would try lowering the birthRate and scaling the particles larger. \$\endgroup\$ – Attackfarm Jul 9 '14 at 3:24
  • 1
    \$\begingroup\$ You're quite welcome \$\endgroup\$ – Attackfarm Jul 9 '14 at 9:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.