-
Notifications
You must be signed in to change notification settings - Fork 9
Everything you never wanted to know about depth masks
KSP uses multiple cameras to render the scene. The two we are most concerned about are the LocalSpace camera which renders the exterior of parts and nearby terrain, and the Internal camera which renders IVAs, props, kerbals, etc. The LocalSpace camera renders first, and then the Internal camera renders on top of it. They live in completely different coordinate systems and cannot share depth information, so whatever the Internal camera draws will appear on TOP of the parts and terrain.
This is normally fine if all you're doing is drawing the interior of the cockpit that you're currently sitting in. But in FreeIva, we have to draw the internals of other parts because you might have opened a hatch into them. This means that without special care, if you look out of a window at some other part you will be able to see its internals drawn on top of the part exterior. In order to prevent this, we need to make sure that something is drawn over each part's windows that will write to the z-buffer, and this needs to be done before other internals are rendered.
A depth mask is a special shader that is invisible, but writes to the z-buffer. This prevents anything else from being drawn behind it. The stock game uses these in the interior overlay view so that the entire IVA isn't visible from outside - typically it lets you see through just the windows or hatches. It's important to remember that the mask covers areas that should NOT be visible.
The stock depth mask shader does not perform backface culling, so it presents a problem for FreeIva: if we did nothing, the depth mask would prevent you from being able to see through hatches into other parts (because most stock parts have depth mask geometry covering the hatch areas). To solve this, FreeIva tries to find the existing depth mask and disables it when in IVA mode.
In order to prevent other internals from being visible from windows, one solution is to create a depth mask over the window that will be active when in IVA mode. You can include some geometry in a model with the DepthMask shader and tell FreeIva to use it as the internal depth mask:
MODULE
{
name = InternalModuleFreeIva
internalDepthMaskName = depthMask
}
FreeIva will activate these meshes when in IVA mode and deactivate them in external mode. Further, it will also switch their shader to use a version of the DepthMask shader that does backface culling. You can use this to create a loose "curtain" around any windows in the internal model so that other IVAs won't be drawn behind them. This curtain needs to be tight enough that it will not extend into any other internal models that might be placed nearby, and that nothing but the curtain is visible when looking out the windows.
If there is not an internal depth mask specified, FreeIva will look for meshes in the internal model with the following shaders and assume they are windows:
- Unlit/Transparent
- KSP/Alpha/Translucent Specular
- KSP/Alpha/Translucent
- KSP/Alpha/Unlit Transparent
Note: Unlit/Transparent
does not write to the z-buffer, so FreeIva will change meshes that use this shader into using KSP/Alpha/Unlit Transparent
instead.
FreeIva will change the renderqueue value on these meshes so that they draw right before the opaque geometry. This prevents any other internals from being visible through the window.
If any other mesh in the internal model uses these shaders and isn't a window, then there will likely be rendering artifacts because you will now be able to see whatever the LocalSpace camera drew behind that mesh. To address this issue, you can explicitly tell FreeIva which meshes are windows, and it will only alter those meshes' renderqueue values:
MODULE
{
name = InternalModuleFreeIva
windowName = Glass_Int
windowName = windows
}
As you can see above, you can specify multiple windowName
fields as necessary.
- If your part has windows, use one of the KSP alpha shaders
- If you also have non-windows using alpha shaders, use the
windowName
field - If that doesn't work for some reason, create a shell around the windows to block viewing other IVAs and use the
internalDepthMaskName
field