iPhone game 2d shadows
We're in the process of creating an iPhone game using cocos2d. We're trying to layer several sprites on top of each other and have them cast shadows.
Right now the shadows are rendered as sprites which works fine for the most part. But we only want the shadows to hit the closest layer.
I've made an image that hopefully explains what we're trying to accomplish:
And here's what we have at the moment:
Basically we want the sprite to only render the part of the shadow that is at the same depth as the z-buffer.
We've played around with glDepthFunc
and GL_DEPTH_TEST
but nothing 开发者_如何转开发seems to work.
Here's how we're rendering the shadow sprite (subclassed CCSprite):
- (void)draw {
glDisable( GL_BLEND );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glDepthMask( GL_FALSE );
[super draw];
glDepthMask( GL_TRUE );
glDisable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
}
The GL_BLEND
calls are only there so we can see the sprite at all times.
All sprites that aren't shadows use glDepthMask( GL_TRUE )
and we're clearing the depth buffer on each frame.
Any help would be much appreciated!
glDepthFunc(GL_LESS)
is actually the default value; it means "draw the pixel only if the thing currently in the depth buffer is further away". If you wanted exactly equal you'd use glDepthFunc(GL_EQUAL), but in practice you'll get all sorts of rounding oddities if you do that.
Assuming you're able to use depth values for this purpose, if you have ten objects then I'd suggest you:
- set glClearDepth to 0 before you glClear; this'll fill the depth buffer with the nearest storable value so that with normal depth buffering nothing else would be drawn.
- disable the depth and draw the shadows such as they're supposed to fall on the back plane; at this point your depth buffer will still be full of the nearest possible value.
- enable the depth test but set glDepthFunc to GL_ALWAYS. Then draw all your solid rectangles in back to front order with their depth values set appropriately.
- set glDepthFunc to GL_LESS and draw the shadows that are meant to fall on other sprites, each positioned further back than the sprite they're associated with but in front of the sprite behind.
By the time you get to step 4, you'll have correct depth information everywhere a sprite was drawn and you'll have the closest possible value set wherever the background plane was. So normal depth testing will work on the intermediate shadows — they'll draw on top of anything drawn in step 3 but not on top of anything drawn in step 2.
You're sort of using the depth buffer as a surrogate stencil, which the older iPhones don't support.
If you can't afford to use the depth buffer for this task then all I can think of is projecting the shadows as textures in the second texture unit, using the first for a mask texture (or not if you're actually drawing rectangles, but I guess you're probably not) and doing one rendering pass per sprite per shadow that falls upon it. Is that a passable solution?
精彩评论