Procedural Jellyfish
Procedural Content Generation - Jellyfish Customisation
In gaming, 3D character and creature models often focus on familiar archetypes like humanoids and dragons, leaving intriguing designs like jellyfish largely underrepresented. Their diverse textures and fluid, sine-wave movements make jellyfish ideal candidates for Procedural Content Generation (PCG).
The initial aim of this project was to create a jellyfish customization game using UI sliders for real-time adjustments. As development progressed, the project evolved to include multiple updates that enhance technical efficiency, such as an API for streamlined asset management and an array of jellyfish clones to populate the environment. These features not only optimize performance but also enable a rich variety of jellyfish while minimizing file size and resource usage, showcasing the powerful capabilities of PCG in game development.
Skills Gained:
- Procedural generation for textures & animations.
- Vertex displacement animation.
- Math-based programming
- UI sliders & widgets in UE5
- Data-driven-based design using arrays.
- Performance optimization.
- Environment & lighting design.
- 3D creature design.
Materials
In developing the jellyfish textures, I focused on enhancing my expertise with material nodes (specifcially, learning the ‘Parallax occlusion Mapping’ and ‘Fresnel’ nodes) and exploring advanced techniques for generating unique visual effects. My objectives included creating a realistic jellyfish texture that captures its characteristic transparency, along with more striking and visually appealing options designed to attract players, such as the camouflage material, inspired by the mimic octopus.
- The regular material uses a fresnel & noise node to create a realistic jellyfish appearance.
- The chrome material uses the fresnel node to create a realistic metallic, rainbow chrome effect.
- The rock material uses a texture sample (which I generated procedurally & converted into a texture sample) into a parallax occlusion node, creating a fake, cheap 3D effect.
- The camouflage material uses a black to white gradient multiplied by noise, animated to periodically become transparent. The base colour is also animated to change between 3 colours.
With numerous unique customizable variables, such as color, animation speed, transparency, and pattern manipulation, my effective and optimised use of PCG textures allow for multiple jellyfish variations with minimal disk space usage.
Movement
Jellyfish move in flowing, sine-like motions, making vertex displacement—a branch of PCG—ideal for capturing this behaviour.
This technique enables organic, fluid movements while minimising disk space. Therefore, I created 3 different animations using
this method.
- The “Drift” movement aims to replicate the man o' war jellyfish. The equation uses an asymmetric sine equation to give the appearance of drifting with the water.
- The “Twist” movement was developed through creative exploration and experimentation. Starting with the “Drift” nodes, I added a linear fall off sine equation and rotation nodes, giving it its twisting motion.
- The final “Bounce” movement aimed to replicate the sea nettle jellyfish. Starting by replicating a sine wave from Alexander Hoover’s dissertation, I added an absolute wave to create a propelling motion. I then used a tapering function to remove an artefact, as well as removing unwanted harshness from the absolute values.
By leveraging multiple sine equations and advanced mathematical methods, I created numerous animation variations with customizable parameters, allowing for a multitude of unique possible outcomes.
Profiling & Optimization
An experienced technical artist recommended that I improve my equations, and through GPU profiling, I found that a populated scene with these equations was indeed impacting performance. By consolidating all calculations into a single sine equation, I successfully optimized my movement blueprints. While the unoptimized equations had only a slight effect on frame rates, this practice is crucial for maintaining sustained performance in larger-scale games.
UI Sliders - What if there were 100 jellyfish models and textures?
During an interview, I was challenged with a crucial question: how could my code accommodate 100 jellyfish models for an MMO open-world
setting? At that time, my approach relied on copy-pasting code for each jellyfish (in my case, 2 models), which was neither efficient
nor scalable. Therefore, I set out to completely restructure my codebase.
For the sliders, users can cycle through several widgets, each controlling specific materials and their variables. Initially, I
repeated code for the light switch and buttons within each widget. To eliminate this redundancy, I added a separate “select model”
widget that remains fixed on top, consolidating all controls for jellyfish model selection and lighting.
To accomodate 100 jellyfish, I used a static variable that would update to whichever jellyfish is currently being displayed. This is possible as all relevant variables share the same name. All of the jellyfish models and textures are stored in a list array that an artist could comfortably edit. As my game currently uses buttons, when a jellyfish button is selected, its corresponding index is called from the list array, updating the static variable. Of course, a keyboard input or number-insert system could easily be used in its place.
This newer method allows the user to instantiate multiple, unique jellyfish with much fewer lines of code. This improvement not only streamlined the implementation process but also significantly improved performance, allowing for a cheap, intuitive method to populate an environment.
Environment
In developing the environment for the jellyfish, I aimed to create a underwater atmosphere that would compliment the jellyfish models & MMO scenario
I created a PCG sand texture and a Post Processing volume (PPV) to create an underwater atmosphere with animated sand rays and a disappearing render distance. I also added a daytime/night-time switch to better view emissive customisation options. Finally, I created god rays; they were made using simple geometric shapes & a PCG material. I created different instances with out of sync sine values to create a seemingly random scattering-light effect.
The sand texture and PPV enhance the environment while cleverly masking the small loaded area, conserving disk space. Meanwhile, the god rays provide a visually effective and cost-effective alternative to Unreal’s more expensive environment light mixture effects.
Jellyfish Clone System
As mentioned, users can populate their environment with custom jellyfish. I included this feature to showcase how artists could utilize my project to fill a space with NPCs or allow players to save their personalized jellyfish creations.
To do this, I used an array and velocity script. The submitted jellyfish is cloned, with the clone containing a random velocity that changes direction if colliding with an invisible wall, to avoid jellyfish leaving the area. The clone is also added to an array list that deletes that oldest list item once 10 items have been added, to avoid overcrowding. This creates an intuitive, easily editable set up for an artist to use or for a player, of any specs, to admire their creations.
Conclusion
This extensive project began as my final project for a computing MA and has since undergone numerous updates as my technical art and programming skills have evolved. After utilizing Unreal Engine’s colorblind testing feature and adding several original soundtracks, my jellyfish program was complete. With optimized movement equations, an API for jellyfish models and textures, an enhanced environment, numerous stored materials & movements all within a zipped file size of under 100MB, I take great pride in this project as it demonstrates essential skills in both programming and technical art.