I was watching my younger son play Splatoon yesterday, and it’s got me thinking. First, about what an amazingly good game design it is (but that’d be a topic for the Game Design forum). And second…
How do they do that?!
In case you’ve been living in a cave, Splatoon is a Nintendo third-person shooter where, instead of ordinary weapons, all your weapons distribute paint in various ways. One team is one color, the other team is a different color.
This paint (or “ink” in Splatoon parlance) splatters very satisfyingly, and also wraps neatly around corners and edges.
So I woke up wondering to myself how I would tackle something like that. Things I know how to do:
- Cast a ray onto a mesh and get the UV coordinates (as well as the 3D coordinates) of the point hit.
- Copy a source texture into a target Texture2D (though this is a bit expensive).
But those edges and corners are the tricky part. If I had to do it this moment, I guess I would cast a pair of rays at each of 4 points around the center of the splat, and from the point hit, calculate where (in UV space) the center and scale of the splat would be. For example, I cast a ray 1 unit above and right of the aim point, and another ray 0.9 units above and right, and from the two UV points hit, extrapolate 10 times further to get where the center would be. Then I copy in my splat texture, and repeat for the other three corners, only skipping repainting if they work out to the same center.
But I foresee problems. If my two rays happen to straddle an edge/seam which goes to different parts of UV space, I could end up drawing a giant splat that spans things it shouldn’t. And I suspect there are cases where edges wouldn’t line up as neatly as I want this way.
Another approach would be to, for each hit, draw a large number of very small circular blobs of paint. And simply iterate over the whole splat area, casting a ray for each small blob. But that’s a lot of ray-casting, and a lot of overdrawing in the texture, both of which seem like a Bad Thing for performance in a game where spraying paint everywhere is kind of the point.
Any other ideas? Is there some clever solution to this I haven’t thought of?