Skip to content

Commit

Permalink
Add UI option for terrain tessellation
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Jun 25, 2024
1 parent cbb95c2 commit 6dd0e98
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Config/Localization.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Key,english
xuiOptionsVideoTerrainTessellation,Terrain Tessellation
xuiOptionsVideoTerrainTessellationTooltip,Enables tessellation on the GPU.\nPerformance impact: Very High
5 changes: 5 additions & 0 deletions Config/XUi_Menu/windows.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<configs>
<insertafter xpath="/windows/window[@name='optionsVideo']//rect[@tab_key='xuiOptionsVideoQuality']//videooption[@name='TerrainQuality']">
<videooption name="TerrainTessellation" type="ComboBoxList`1[System.String]" values="Off,Lowest,Low,Medium,High,Ultra,Ultra+" localization_prefix="xuiOptionsVideoPresets" value_wrap="false" />
</insertafter>
</configs>
4 changes: 4 additions & 0 deletions Config/worldglobal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
<!-- you may define your own shader if wanted, but we don't really recommend to mess with this directly -->
<property name="ShaderDetail" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Vertex"/>
<property name="ShaderDistant" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Distant"/>
<property name="ShaderDetailTess" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}VertexTess"/>
<property name="ShaderDistantTess" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}DistantTess"/>
<!-- metal means the mac graphics api, which requires a platform specific bundle (can't be bundles into one unfortunately) -->
<property name="MetalShaderDetail" value="#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Vertex"/>
<property name="MetalShaderDistant" value="#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Distant"/>
<property name="MetalShaderDetailTess" value="#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}VertexTess"/>
<property name="MetalShaderDistantTess" value="#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}DistantTess"/>

<property name="NoisePerlin" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/microsplat_def_perlin"/>
<property name="NoiseDetail" value="#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/microsplat_def_detail_noise"/>
Expand Down
7 changes: 0 additions & 7 deletions Harmony/FixMeshGeneratorNormals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,6 @@ private static Vector3 CalculateNormalUnscaled(
normalUnscaled.x = (float)(densityRight - densityLeft);
normalUnscaled.y = (float)(densityAbove - densityBelow);
normalUnscaled.z = (float)(densityFront - densityBack);
if (normalUnscaled.magnitude == 0)
{
//Log.Out("Found issue x {0} {1}", densityLeft, densityRight);
//Log.Out("Found issue y {0} {1}", densityBelow, densityAbove);
//Log.Out("Found issue z {0} {1}", densityBack, densityFront);
//Log.Out("Center density is {0}", getDensity(___chunksCache, x, _y1, z));
}
return normalUnscaled;
}

Expand Down
4 changes: 3 additions & 1 deletion Harmony/MicroSplat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ public static MicroSplatXmlConfig Config

public void InitMod(Mod mod)
{
// if (GameManager.IsDedicatedServer) return;
if (GameManager.IsDedicatedServer) return;
Log.Out("OCB Harmony Patch: " + GetType().ToString());
Harmony harmony = new Harmony(GetType().ToString());
harmony.PatchAll(Assembly.GetExecutingAssembly());
#if DEBUG
Log.Error("This is a test version of OcbMicroSplat!");
Log.Error("Do not redistribute or use in production!");
#endif
if (!PlayerPrefs.HasKey("TerrainTessellation"))
PlayerPrefs.SetInt("TerrainTessellation", 2);
DecalShaderBundle = DecalBundlePath = System.IO.Path
.Combine(mod.Path, "Resources/OcbDecalShader.unity3d");
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Metal)
Expand Down
123 changes: 123 additions & 0 deletions Harmony/TessellationOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using HarmonyLib;
using System.Reflection;
using UnityEngine;

public class TessellationOption
{

// Must be called by mod init too
// Since our patch is too late for early init
public static void ApplyTerrainOptions()
{
if (GameManager.IsDedicatedServer) return; // Nothing to do here
if (MeshDescription.meshes.Length < MeshDescription.MESH_TERRAIN) return;
var mesh = MeshDescription.meshes[MeshDescription.MESH_TERRAIN];
// Set tessellation options according to game settings
switch (PlayerPrefs.GetInt("TerrainTessellation"))
{
// _Tess = edgeLength
// _Phong = move to bary
case 1: // Lowest
mesh.material.SetFloat("_Tess", 128.0f);
mesh.materialDistant.SetFloat("_Tess", 128.0f);
break;
case 2: // Low
mesh.material.SetFloat("_Tess", 96.0f);
mesh.materialDistant.SetFloat("_Tess", 96.0f);
break;
case 3: // Medium
mesh.material.SetFloat("_Tess", 64.0f);
mesh.materialDistant.SetFloat("_Tess", 64.0f);
break;
case 4: // High
mesh.material.SetFloat("_Tess", 32.0f);
mesh.materialDistant.SetFloat("_Tess", 32.0f);
break;
case 5: // Ultra
mesh.material.SetFloat("_Tess", 16.0f);
mesh.materialDistant.SetFloat("_Tess", 16.0f);
break;
case 6: // Ultra+
mesh.material.SetFloat("_Tess", 8.0f);
mesh.materialDistant.SetFloat("_Tess", 8.0f);
break;
default:
mesh.material.SetFloat("_Tess", 256.0f);
mesh.materialDistant.SetFloat("_Tess", 256.0f);
break;
}
}

// Our combo box (should only even have one)
static XUiC_ComboBoxList<string> comboTessOpt = null;

// Hook our new combo box into the ui workflow
[HarmonyPatch(typeof(XUiC_OptionsVideo), "Init")]
public class XUiC_OptionsVideo_Init
{
// The original handler (use reflection for protected)
static readonly MethodInfo handler = AccessTools.Method(
typeof(XUiC_OptionsVideo), "AnyPresetValueChanged");

static void Prefix(XUiC_OptionsVideo __instance)
{
// The UI element with our combo box
comboTessOpt = __instance
.GetChildById("TerrainTessellation")
.GetChildByType<XUiC_ComboBoxList<string>>();
// Hook into event to invoke the regular UI handler
comboTessOpt.OnValueChangedGeneric += (XUiController sender) => {
handler.Invoke(__instance, new object[] { sender });
};

}
}

// Patch into function when apply is hit on the UI
[HarmonyPatch(typeof(XUiC_OptionsVideo), "applyChanges")]
public class XUiC_OptionsVideo_applyChanges
{
static void Prefix(XUiC_OptionsVideo __instance)
{
PlayerPrefs.SetInt("TerrainTessellation", comboTessOpt.SelectedIndex);
}
}

// Patch into function when video settings UI is loaded
[HarmonyPatch(typeof(XUiC_OptionsVideo), "updateGraphicOptions")]
public class XUiC_OptionsVideo_updateGraphicOptions
{
static void Prefix(XUiC_OptionsVideo __instance)
{
comboTessOpt.SelectedIndex = PlayerPrefs.GetInt("TerrainTessellation");
}
}

// Patch into function when options are applied to materials
[HarmonyPatch(typeof(GameOptionsManager), "ApplyTerrainOptions")]
public class GameOptionsManager_ApplyTerrainOptions
{
static void Postfix()
{
ApplyTerrainOptions();
}
}

// Patch into function when video settings are set to defaults
[HarmonyPatch(typeof(GameOptionsManager), "SetGraphicsQuality")]
public class GameOptionsManager_SetGraphicsQuality
{
static void Postfix()
{
switch (GamePrefs.GetInt(EnumGamePrefs.OptionsGfxQualityPreset))
{
case 1: PlayerPrefs.SetInt("TerrainTessellation", 1); break;
case 2: PlayerPrefs.SetInt("TerrainTessellation", 2); break;
case 3: PlayerPrefs.SetInt("TerrainTessellation", 3); break;
case 4: PlayerPrefs.SetInt("TerrainTessellation", 4); break;
default: PlayerPrefs.SetInt("TerrainTessellation", 0); break;
}
}
}

}
18 changes: 16 additions & 2 deletions Library/Configs/MicroSplatShader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public class MicroSplatShader
private DataLoader.DataPathIdentifier PathShaderDistant;
private DataLoader.DataPathIdentifier MetalShaderDetail;
private DataLoader.DataPathIdentifier MetalShaderDistant;
private DataLoader.DataPathIdentifier PathShaderDetailTess;
private DataLoader.DataPathIdentifier PathShaderDistantTess;
private DataLoader.DataPathIdentifier MetalShaderDetailTess;
private DataLoader.DataPathIdentifier MetalShaderDistantTess;
private DataLoader.DataPathIdentifier PathTexNoiseDetail;
private DataLoader.DataPathIdentifier PathTexNoiseDistant;
private DataLoader.DataPathIdentifier PathTexNoisePerlin;
Expand Down Expand Up @@ -156,8 +160,13 @@ public void LoadTerrainShaders(MeshDescription terrain)
Shader ShaderDetail = null; Shader ShaderDistant = null;
// Try to load the shader assets (may load from platform specific asset bundle)
bool IsMetal = SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Metal;
LoadAsset(IsMetal ? MetalShaderDetail : PathShaderDetail, ref ShaderDetail, false);
LoadAsset(IsMetal ? MetalShaderDistant : PathShaderDistant, ref ShaderDistant, false);
if (PlayerPrefs.GetInt("TerrainTessellation") > 0) {
LoadAsset(IsMetal ? MetalShaderDetailTess : PathShaderDetailTess, ref ShaderDetail, false);
LoadAsset(IsMetal ? MetalShaderDistantTess : PathShaderDistantTess, ref ShaderDistant, false);
} else {
LoadAsset(IsMetal ? MetalShaderDetail : PathShaderDetail, ref ShaderDetail, false);
LoadAsset(IsMetal ? MetalShaderDistant : PathShaderDistant, ref ShaderDistant, false);
}
// Give error messages to the console if loading failed
if (ShaderDetail == null) Log.Error("Could not load custom detail shader: {0}/{1}",
PathShaderDetail.BundlePath, PathShaderDetail.AssetName);
Expand All @@ -168,6 +177,7 @@ public void LoadTerrainShaders(MeshDescription terrain)
terrain.material.shader = ShaderDetail;
if (ShaderDistant != null && terrain.materialDistant != null)
terrain.materialDistant.shader = ShaderDistant;
TessellationOption.ApplyTerrainOptions();
}

// ####################################################################
Expand Down Expand Up @@ -229,6 +239,10 @@ public void Parse(XElement child)
PathShaderDistant = GetPath(props, "ShaderDistant", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Distant");
MetalShaderDetail = GetPath(props, "MetalShaderDetail", "#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Vertex");
MetalShaderDistant = GetPath(props, "MetalShaderDistant", "#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}Distant");
PathShaderDetailTess = GetPath(props, "ShaderDetailTess", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}VertexTess");
PathShaderDistantTess = GetPath(props, "ShaderDistantTess", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}DistantTess");
MetalShaderDetailTess = GetPath(props, "MetalShaderDetailTess", "#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}VertexTess");
MetalShaderDistantTess = GetPath(props, "MetalShaderDistantTess", "#@modfolder:Resources/OcbMicroSplat.metal.unity3d?assets/OcbMicroSplat/OcbMicroSplat{1}{0}DistantTess");
PathTexNoisePerlin = GetPath(props, "NoisePerlin", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/microsplat_def_perlin");
PathTexNoiseDetail = GetPath(props, "NoiseDetail", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/microsplat_def_detail_noise");
PathTexNoiseDistant = GetPath(props, "NoiseDistant", "#@modfolder:Resources/OcbMicroSplat.unity3d?assets/OcbMicroSplat/microsplat_def_detail_noise");
Expand Down
3 changes: 3 additions & 0 deletions MicroSplat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<Compile Include="Harmony\MicroSplatXmlFilters.cs" />
<Compile Include="Harmony\OcbDecalShader.cs" />
<Compile Include="Harmony\SkipTexturesRelease.cs" />
<Compile Include="Harmony\TessellationOption.cs" />
<Compile Include="Library\Configs\MicroSplatBiomeColor.cs" />
<Compile Include="Library\Configs\MicroSplatBiomeLayer.cs" />
<Compile Include="Library\Configs\MicroSplatShader.cs" />
Expand All @@ -126,7 +127,9 @@
</ItemGroup>
<ItemGroup>
<Content Include="Config\blocks.xml" />
<Content Include="Config\Localization.txt" />
<Content Include="Config\worldglobal.xml" />
<Content Include="Config\XUi_Menu\windows.xml" />
<Content Include="ModInfo.xml" />
<Content Include="README.md" />
</ItemGroup>
Expand Down

0 comments on commit 6dd0e98

Please sign in to comment.