From 4a80ef547b2990a8d37d112c66b6646ae669a4f1 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Wed, 28 Aug 2024 07:44:07 +0100 Subject: [PATCH] Support toggling lightmap layers --- project/code/TMV/Mission.cs | 75 ++++++++++++++++++++++++++++++++++++- project/materials/base.tres | 31 ++++++++++----- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/project/code/TMV/Mission.cs b/project/code/TMV/Mission.cs index fb4b120..1e3802d 100644 --- a/project/code/TMV/Mission.cs +++ b/project/code/TMV/Mission.cs @@ -45,12 +45,16 @@ public partial class Mission : Node3D DbFile _file; TextureLoader _textureLoader; ModelLoader _modelLoader; + List _materials; + Vector2I _lmLayerMask; public override void _Ready() { var extractPath = ProjectSettings.GlobalizePath($"user://extracted/tmp"); _installPaths = new ResourcePathManager(extractPath); _modelLoader = new ModelLoader(_installPaths); + _materials = new List(); + _lmLayerMask = new Vector2I(~0, ~0); var missionSelector = GetNode("%MissionSelector") as MissionSelector; missionSelector.pathManager = _installPaths; missionSelector.MissionSelected += (string campaign, string mission) => @@ -84,6 +88,10 @@ public partial class Mission : Node3D { Build = true; } + if (keyEvent.Keycode == Key.O) + { + ToggleLightmap(); + } } } @@ -93,6 +101,8 @@ public partial class Mission : Node3D { node.QueueFree(); } + + _materials.Clear(); } public void RebuildMap() @@ -111,6 +121,60 @@ public partial class Mission : Node3D } } + public void ToggleLightmap() + { + if (_lmLayerMask == Vector2I.Zero) + { + _lmLayerMask = new Vector2I(~0, ~0); + } + else + { + _lmLayerMask = Vector2I.Zero; + } + + foreach (var mat in _materials) + { + mat.SetShaderParameter("lightmap_bitmask", _lmLayerMask); + } + } + + public void ToggleLmLayer(uint layer) + { + if (layer >= 64) + { + throw new ArgumentOutOfRangeException(nameof(layer)); + } + + static int ToggleBit(int bitIdx, int val) + { + var mask = 1 << bitIdx; + var isEnabled = (val & mask) != 0; + if (isEnabled) + { + val &= ~mask; + } + else + { + val |= mask; + } + return val; + } + + if (layer < 32) + { + _lmLayerMask.X = ToggleBit((int)layer, _lmLayerMask.X); + } + else + { + _lmLayerMask.Y = ToggleBit((int)layer - 32, _lmLayerMask.Y); + } + + foreach (var mat in _materials) + { + mat.SetShaderParameter("lightmap_bitmask", _lmLayerMask); + } + } + // TODO: Make this less of a mess private ObjectHierarchy BuildHierarchy() { @@ -239,10 +303,12 @@ public partial class Mission : Node3D } var albedoTexture = _textureLoader.Get(textureId); + var mat = BuildMaterial(albedoTexture, lightmapTexture, lmHdr, _lmLayerMask); + _materials.Add(mat); var mesh = new ArrayMesh(); mesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surface.BuildSurfaceArray()); - mesh.SurfaceSetMaterial(0, BuildMaterial(albedoTexture, lightmapTexture, lmHdr)); + mesh.SurfaceSetMaterial(0, mat); var meshInstance = new MeshInstance3D { Mesh = mesh }; AddChild(meshInstance); @@ -472,12 +538,17 @@ public partial class Mission : Node3D } const string MATERIAL_PATH = "res://project/materials/base.tres"; - private static Material BuildMaterial(Texture2D albedoTexture, Texture2DArray lightmapTexture, bool lmHdr) + private static ShaderMaterial BuildMaterial( + Texture2D albedoTexture, + Texture2DArray lightmapTexture, + bool lmHdr, + Vector2I layerMask) { var material = ResourceLoader.Load(MATERIAL_PATH).Duplicate() as ShaderMaterial; material.SetShaderParameter("texture_albedo", albedoTexture); material.SetShaderParameter("lightmap_albedo", lightmapTexture); material.SetShaderParameter("lightmap_2x", lmHdr); + material.SetShaderParameter("lightmap_bitmask", layerMask); return material; } } \ No newline at end of file diff --git a/project/materials/base.tres b/project/materials/base.tres index 8854037..1a0121a 100644 --- a/project/materials/base.tres +++ b/project/materials/base.tres @@ -6,6 +6,7 @@ render_mode blend_mix,depth_draw_opaque,cull_back,unshaded; uniform sampler2D texture_albedo : filter_linear_mipmap_anisotropic,repeat_enable; uniform sampler2DArray lightmap_albedo : filter_linear_mipmap_anisotropic,repeat_enable; uniform bool lightmap_2x; +uniform ivec2 lightmap_bitmask; float srgb_to_linear_e(float input) { float output; @@ -28,16 +29,27 @@ vec3 srgb_to_linear(vec3 input) { void fragment() { vec4 albedo_tex = texture(texture_albedo,UV); - vec4 lightmap_tex = vec4(0.0); - for (int i = 0; i < 33; i++) { - lightmap_tex += texture(lightmap_albedo, vec3(UV2, float(i))); + if (lightmap_bitmask.x == 0 && lightmap_bitmask.y == 0) { + ALBEDO = srgb_to_linear(albedo_tex.rgb); + } else { + vec4 lightmap_tex = vec4(0.0); + int mask = lightmap_bitmask.x; + for (int i = 0; i < 33; i++) { + if (i == 32) { + mask = lightmap_bitmask.y; + } + bool layer_enabled = (mask & (1 << (i % 32))) != 0; + if (layer_enabled) { + lightmap_tex += texture(lightmap_albedo, vec3(UV2, float(i))); + } + } + lightmap_tex = min(vec4(1.0), lightmap_tex); + + if (lightmap_2x) { + lightmap_tex *= 2.0f; + } + ALBEDO = srgb_to_linear((albedo_tex * lightmap_tex).rgb); } - lightmap_tex = min(vec4(1.0), lightmap_tex); - - if (lightmap_2x) { - lightmap_tex *= 2.0f; - } - ALBEDO = srgb_to_linear((albedo_tex * lightmap_tex).rgb); } " @@ -45,3 +57,4 @@ void fragment() { render_priority = 0 shader = SubResource("Shader_eumy4") shader_parameter/lightmap_2x = null +shader_parameter/lightmap_bitmask = null