Skip to main content

Nerdy referential title out of the way, I’ve been on a hot streak this month. For starters, I’ve been up to my neck in Amplify Shader Editor shenaniganery, but I’ve also brought the hull and superstructure up to what I might consider about 90% base completion (not counting stylistic detailing). As with most of these posts, a lot has happened within the month of October, so I’ll keep this post to the big points.

Stairs! Everywhere!


So after months of having to parkour up the front turrets to get to the bridge area, I finally went through and added stairs and height transfers all over the place. I really like how the stairs behind the bridge came out, actually; it feels very “industrial” when running up them in VR.

This change also includes putting functionality on all the existing ladder models to allow the player to ascend and descend with on interact (no fancy Udon climbing scripts… yet?).

There’s not too awfully much to say about this change; it’s more of a backbone than anything too fancy.

The Aft Mast


This is probably the first superstructure object on the ship that doesn’t have a uniquely baked material. Because of this, the texture work looks a bit spartan, but because it’s all so spindly, it doesn’t really show up too bad.

The Aft Mast features 3 different observation levels at which to post up: the main watch deck, a weird intermediate platform that I don’t know entirely what to do with, and the obligatory Crow’s Nest.

To tie this new feature into the rest of the ship, I’ve finally put the Metal Cable material from last post to work in some interesting-looking (and also realistically problematic but just ignore that) rigging between the mast and several anchor points on the ship. The reference ship, the Scharnhorst, has HF wires for communication everywhere, which filled everything out nicely. However, radio doesn’t exist in this universe, so it’s mainly setup to look a bit like tallship rigging.

The Depth Pulse (Animations)


So I went through and actually animated the deploy/undeploy sequences for the Depth Pulse and its Aft Housing roof retraction. This was actually what caused me to finally take the plunge into UdonSharp stuff. As this will need to check if the roof is open before deploying the Depth Pulse (or else the thing will just phase through the roof), some Udon scripting was needed. Also, this made me learn that Udon’s networking is…odd, but serviceable.

Doors and Lights


These door models have actually been complete for quite a bit of time, as can be seen by the second post on this project Stuck in Drydock. However, they were without animations nor functionality until this month. Kaderen baked in some animations for locking, unlocking, opening, and closing the door, and I made a simple networked toggle script to get the door animations to run on both local player and networked players.

As can be seen above the doors, I also completed a pack of light fixture assets to be used around the place. They’re all based on existing light fixture types, like the cage lights seen here, but all the bulbs have been replaced with glowy magic crystals.

The ominous red glow is due to an actual real-life requirement on warships that exterior lights be kept red so as not to screw with dark vision, as well as to not be near as visible to other (possibly enemy) ships. Thanks go to EnDjinn for the suggestion on this one.

Abusing Symmetry Paint for Fun and Profit

I haven’t fully rigged up all the light types just yet, but the cage light (with bendy and straight mounts) as well as the above dome light are both setup with proper prefabs.

The Void…
Bright-ass Cylinders

Also available now are the Directional Indicator Lights for depicting to other ships which way the Stiletto is currently sailing. I actually had to tone down the bloom for the above shot because I made them REALLY BRIGHT on the emissive multiplier. This makes them really visible from across the map, but it does make them blow the image out to hell when your face is right up against them.

Along with the light objects, I also spent a fair whack of time trying to come up with a setup that would allow us to run a Day/Night cycle without having to bake a multitude of Lightmaps and Reflection Probes in order to get a smooth transition.

What I settled on was enabling Realtime GI, setting the Baked GI to Shadowmask (props to Kaderen for pointing me at a better mode than Baked Indirect), and making a couple Realtime Reflection Probes. Yes, realtime reflections, bad idea I know. However, the main reflection probe for the exterior is the only one that updates per-frame in actual realtime. The other two main ones so far (one for under the arch between the Aft Housing and Midships and one for inside the Aft Housing) are set to On Awake, and I will eventually write a script to manually update these once every 10 seconds or so, since they’re in positions where lighting conditions shouldn’t change much.

The Ocean

Rough Seas Ahead

And now for the biggest, most noticeable change during this month: We now have an ocean to sail on rather than The Void.

I have been and continue to be slamming my head into this freaking shader for the better part of two weeks now, as of this post. This was all made in Amplify Shader Editor, and is essentially a mashup of the Water sample that comes with ASE, and the Ocean Shader by Evan Edwards whom had posted most of the Shader Graph to his blog. I say “most” because directly copying the graph itself doesn’t work, and it’s missing a lot of features presented in the actual asset video.

Being the insane person that I am, I decided to try to make my own version based on the parts above. If anyone’s ever tried to do this themselves, they’re probably familiar with the term Gerstner Waves, which is basically a 3-fold trigonometry set applied to the offset of the ocean plane’s vertexes.

Basically, to use a common meme from the date of this writing: math go brrr.

32,805,000 tris of OH GOD WHY

The first thing that needed to be done to make this shader was to bake a convincing Normal Map. I COULD use all the math in the world to make the shader generate all of this detail, or I could pre-bake it and save the frames.

So that’s what I did. As can be seen in the screenshot above, I cracked open Blender, made a plane, and applied the Ocean modifier to it. Then, I slammed the Resolution all the way up to 45 (enjoy the laaaag if you try to do this). Then, I stuck another non-deformed plane in the center of the ocean plane, moved the ocean plane out by 50% of its width on either axis, and Array’d it so as to get automatic tiling sorted. After that, it was just down to the arduous process of making the Baking process behave itself and actually bake the Normal and Height maps from this geometry to textures.

Speeding through the many hours spent trying to get the shader itself to work (which would make this post like 3 times longer in detailing all the stupid I went through to figure out what I have), it was finally down to just tweaking the Gerstner inputs until things looked right.

With all this done, we now have a realtime tweakable ocean surface to play with, where we can use scripts or animators on the Material values in order to change the choppiness of the ocean on the fly.

For an extra bit of interesting effects, I made the Global Exterior Reflection Probe reflect the Water layer as well. This made for some interesting pseudo-caustics in the reflection maps, since the probe is set to realtime.


However, my work on this shader is irritatingly incomplete. I still have an issue in the ocean shader where, at oblique angles, the ocean will start to render reflections from below itself rather than sky. This leads to dark splotches here and there when the Water reflections are enabled, or grey-brown splotches when only the Unity Default Skybox is reflected.

This will be solved once I figure out how the hell to do Vertex Normal Reconstruction to actually make the geometry of the water point its Normals in the correct direction. Unfortunately for me, my understanding of the math behind this is eluding me, and trying to port in any existing examples from either ASE or the internet at large is proving unfruitful. For now, this will do as long as I keep the Normal Map scale down to 0.3 or below.