¿ How to darken everything with some exceptions without changing z-order?

At some levels of my game I would like to darken all the elements but with some exceptions. I have added a top layer with a dark transparent color, but I dont know how to avoid some elements to get this color without changing all my z-order.

Thank you.

Changing z-order is the best choice but if you want another way:
-You can use clipper for the layer
or
-addchild the objects you want to keep to the dark layer

I want to darken everything except some element (lets say the moon) that will appear behind all the darken elements, so I chaning the z-order is not an option.

I didnt know about clippingNode, I am going to look for information about it, I think It will work.:slight_smile: Thank you very much.

You can also change the shader of the sprites you want to get darker.

Ok, after some thinking, the ClippingNode solution will not work , because the elements that go thought the “cropped” area of the layer will lost the darkness. :frowning:

Have you setAlphaThreshold(0) of the clipnode?
And also use the moon as stencil…

Yes, I have done that (and I glad to learnt this feature :slight_smile: ) . But maybe I havent explained myself very well or maybe I dont understand something.

This is a very simplified hierarchy of the layers:
-Background layer (with the Moon)
-Game Layer
-Darken layer (Layer with transparency above all layers, to darken all the elements)

I want to darken all the elements except the moon, but the moon has to be behind all the elements.

If I crop the “darken layer” to see the moon, it will also affect the game layer and its elements (Sometimes the moon hides behind elements.)

Now I am reading about the shader solution, lets see.

@saraguatox hey… i dont know if this is a good solution. I haven’t tried anything like it.

maybe something like this

void tintRecursive(Node *node, bool isTint, Color3B color)
{
if(isTint)
{
node->setColor(color);
}
else{
node->setColor(Color3B::WHITE);
}
auto& children = node->getChildren();
for (size_t i = 0; i < children.size(); i++)
{
tintRecursive(children.at(i), isTint, color);
}
}

and you would simply call it like this… lets say you have a scene gameScene

gamescene::init(){




tintRecursive(this,true,Color3B(200,200,200));
tintRecursive(moonSprite,false,Color3B::WHITE);
return true;
}

this can be optimized … see if this works for you…

@saraguatox i am not sure if i understand your requirement, but Node::setColor() can make node darker. And Node::setCascadeColorEnabled() can change its children’s color.

1 Like

Thank you very much, @zhangxm and @b12345 , for your answers.
I had thought already in this solution, but in the game sometimes some elements change already its colors and opacities under some circumstances with this method (sometimes tinted to red, sometimes tinted to blue…) so I supposed that this kind of solution will affect the other setcolors. Am i wrong?

Yep, you are right. May be you can render Game Layer to a rendertexture, and make it darker. Of course, it will slow down the app, but it works if it is just use it not frequently.

1 Like

How about blending functions?

I tested your moon scene idea by having a background, a “moon” and something obscuring part of the moon, and used a LayerColor to cover the entire screen to darken it. Using blending functions, I was able to have the moon remain undarkened, while part of it is covered by a darkened sprite in front of it. Here’s how I did it:

  1. Give your moon a blending function of (GL_ZERO, GL_ONE_MINUS_SRC_ALPHA).
  2. Add a LayerColor in front of everything you want darkened and give it a blending function of (GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
  3. Add a second copy of the moon in the same location as your first one and above the LayerColor. Give it a blending function of (GL_ONE_MINUS_DST_ALPHA, GL_ONE).

And that should work. Just set the colour of the LayerColor to black and adjust the opacity to darken/lighten the scene. (The higher the opacity, the darker the scene.) Here’s an explanation of what is happening:

  1. The blending function of the first moon means it is “cutting a hole” in the scene, i.e. setting the alpha value to 0 of each pixel covered by the non-transparent pixels of the moon.
  2. The blending function of the LayerColor means that it will only draw where the alpha value of a pixel is not 0, e.g. the hole cut in the first step.
  3. The blending function of the second moon means it will draw where the alpha value of a sprite is 0, e.g. the hole. Because the second moon is in front of the darkening layer, it will fill in the hole with the undarkened moon.
3 Likes

Thank you all for your messages, specially to @grimfate for his explanation and solution, it works perfectly!