How did I do the 3d kaleidoscope effect?


Song of Morus: Kaleido Combat  is an isometric shooting game with characters dueling inside a kaleidoscope 3d labyrinth. The most unique element of this prototype game is the stunning 3d kaleidoscope effect, which enhances both the gameplay and visual. So in this post i would like to share how i did it in Unity.


In the story, protagonist Song got into an arguement with a vampire hunter nun, and decide to trap themselves in a kaleidoscope spell to sort it out (which quickly end up in a fight). This idea is halfly inspired by the global game jam theme (but very indirectly), and halfly inspired by the fightscenes in movie Doctor Strange.

Before i start, i would point out one thing. The 3d content is separated to 2 groups: background object & interactive obejct. And as you can see in the game screenshot, only the the background has kaleidoscope effect, while the interactive object is only duplicating. This post will only cover the kaleidoscope effect as the second one is easy to figure out after you finish the first one. And also i am not going to talk about the physics. (Not because of commerical secret, just because my physics is uglily hardcoded to hit the deadline on time)


For the minimum, it just needs one component script to handle the rendering, and one shader script which do masking. And the world editing is similar to how you usually do in other general games. But for better management, i also have a singleton script to sum up all parameters so that I can easily switch on/off the kaleidoscope effect. As you can see the left image is the world scene without the effect, and the right one is on. And the green triangle are is the area my kaleidoscope effect do sampling.


Technically, the principle is to simply render things at a correct position/rotation with a triangle masking (left pic), and do it multiple time (right pic). The key for both steps is Matrix4x4. In runtime, my script would apply an inverse matrix to the materials. And the shader uses it to mask the rendering based on the object position. It's easier to do the masking through Matrix4x4, because you need the translating,rotating,and even the scaling (the triangle angle is in 60 degree) . And then my script create a list of world transform matrix, for calling Graphics.DrawMeshInstanced() to render all triangle chip at each calculated position/rotation.


There were some challenges. The first challenge is the performance. In the very begining , i was using Graphics.DrawMesh() as i was still figuaring out the Math. it achieve the visual effect but each triangle chip is one drawcall, and there are ~100 chips for everymesh rendering. Therefore i later switched to use Graphics.DrawMeshInstanced(). But then there is another problem, as i am calling Graphics api functions in my script, it won't get the benefit of unity built-in occlusion culling, which means i need to make my own occlusion culling if the stage grows bigger. If not, the game will send too much rendering time to render things that is out of the sampling. 

And here is one more problem, which is the polygon normal. for kaleidoscope effect, half of the coontents are mirrored. If you simply mirror things with Matrix4x4, the polygon normal will be flipped. (And i haven't fully fixed the problem in my game when submit) My final solution is to clone the material with the cull mode corrected, as instancing doesn't work on cull mode setting. 


And that's how i made the 3d kaleidoscope effect. If you are interested, Please follow my account, as i planned to expand this mechanic and there will be more content for this game in the future.

Get 桑之巫韻︰萬花華鬥 Song of Morus: Kaleido Combat

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.