Shadow sprites

I want to put a “shadow” sprite on a background sprite using the equation:

max(0, Cd*1 - Cs*S)

where Cd is the destination color (that is, a background pixel), Cs is the source color (the shadow pixel) , S is the scale factor (between 0 and 1).
The max() function is used to avoid negative results. This is a lighting effect: when the shadow sprite pixel is 0, there is no effect on the background
pixel, otherwise, the background pixel becomes darker.

Now, the only way that comes to my mind is to change the blending equation to GL_FUNC_SUBTRACT, but it doesn’t compile with cocos2d-x…

I would subclass the CCSprite class in order to implement the draw() method in order to change, when needed,
the blending equation, call the original draw() method and restore the blending equation to its previous state at the end of the method.

So my questions are two:

  1. how to use glBlendEquation() with cocos2d-x? Keep in mind that i am writing a game for iphone/android/windows.
  2. are shadows handled this way in 2D games?

Thx

Ok, i have solved this. Subclass the CCSprite class, overload the virtual method draw():

void CMySprite::draw()
{
  // is_shadow is true if this sprite is to be considered like a shadow sprite, false otherwise.@
  if (is_shadow)
  {
    ccBlendFunc blend;
    // Change the default blending factors to this one.
    blend.src = GL_SRC_ALPHA;
    blend.dst = GL_ONE;
    setBlendFunc( blend );
    // Change the blending equation to thi in order to subtract from the values already written in the frame buffer
    // the ones of the sprite.
    glBlendEquationOES(GL_FUNC_REVERSE_SUBTRACT_OES);
  }

  CCSprite::draw();

  if (is_shadow)
  {
     // The default blending function of cocos2d-x is GL_FUNC_ADD.
    glBlendEquationOES(GL_FUNC_ADD_OES);        
  }
}

Generally speaking, the glBlendEquationOES() can be used to change the blend equation in order to get different effects. Just remember to
take care of the blending factors…

Maybe this isn’t what you want, but wouldn’t it be easier to have a sprite image which is black. Then draw this sprite with the opacity set like “mySprite->setOpacity(70)”.

That would cast a rectangular shadow image, while the effect i wanted to have is a non-uniform brightness change across the shadow image
(a shadow sprite of constant RGB would be equal to what you say, while a shadow sprite like a 3D gaussian would cast a round-shaped soft
shadow).

You could try something like this:

Create a shadow using a vector mask (black shadow, vector mask makes it transparent and more transparent in a direction). See these files:

And the result - having a laugh :slight_smile: http://www.gmtdev.com/files/car_finished.png

In them I made a copy of the car, flipped it upside down, add a layer mask, gradient fill the mask so it becomes more transparent in one direction, then I also skewed it to add some perspective. There are tutorials on the net,

Gimp: http://docs.gimp.org/en/gimp-layer-mask-add.html
Photoshop, steps 3 & 4: http://www.photoshopcafe.com/tutorials/blend/blend.html

Or you could do it another way if that’s not what you want, just a suggestion.

That’s cool! Exactly the effect i wanted to obtain. I render them simply subtracting the shadow from the background (i don’t know if
there are are methods).

@Gav Hey Gav, what’s if I have space for thing inside sprite to translate. That space is by mean to allow its center position to be aligned with other animations as well. In that case, I can’t just track the current position of the sprite and set it to shadow sprite then finally draw in different layer. Because we have no information of current x-position of thing inside its own sprite while’s it’s moving internally.
I created the question here, if you would like to take a look http://cocos2d-x.org/boards/6/topics/23551.

Have you tried doing an CCSprite::UpdateTransform on both the sprite and its shadow sprite?

Or….Are you using actions to move the sprites? Perhaps moving them manually with setPosition and then doing an UpdateTransform would solve this too.