From e759d6d3d53a022452a7049522ef858ea9ff156e Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Fri, 28 Jul 2023 22:23:41 +0200 Subject: [PATCH] Fixed world generation artefacts after changing world size. --- scenes/Game.cs | 33 +++--- scenes/Game.tscn | 18 ++-- scenes/TileWorld.cs | 180 ++++++++++++++++++++------------ scenes/TileWorld.tscn | 12 ++- scenes/tests/NavigationTests.cs | 4 +- 5 files changed, 157 insertions(+), 90 deletions(-) diff --git a/scenes/Game.cs b/scenes/Game.cs index b0329ef..9148e37 100644 --- a/scenes/Game.cs +++ b/scenes/Game.cs @@ -313,21 +313,11 @@ public class Game : Spatial public void OnWorldGenerated() { - GD.Print("Using new map. Size: " + (int)_tileWorld.Colormap.GetSize().x); + GD.Print("Using new map. Size: " + (int)_tileWorld.ColormapImage.GetSize().x); _goldCountLabel.Text = "0"; - - ImageTexture newWorldTexture = new ImageTexture(); - newWorldTexture.CreateFromImage(_tileWorld.Colormap, - (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat)); - _worldTextureRect.Texture = newWorldTexture; - _tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture); - _tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.Colormap.GetSize().x); - - ImageTexture newHeightTexture = new ImageTexture(); - newHeightTexture.CreateFromImage(_tileWorld.Heightmap, - (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat)); - _heightTextureRect.Texture = newHeightTexture; + + UpdateWorldTextures(); _streamContainer.OnWorldGenerated(); @@ -344,6 +334,23 @@ public class Game : Spatial } } + private void UpdateWorldTextures() + { + GD.Print("Updating World textures"); + + ImageTexture newWorldTexture = new ImageTexture(); + newWorldTexture.CreateFromImage(_tileWorld.ColormapImage, + (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat)); + _worldTextureRect.Texture = newWorldTexture; + _tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture); + _tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.ColormapImage.GetSize().x); + GD.Print("Texture size: " + (int)_tileWorld.ColormapImage.GetSize().x); + + ImageTexture newHeightTexture = new ImageTexture(); + newHeightTexture.CreateFromImage(_tileWorld.HeightmapImage, + (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat)); + _heightTextureRect.Texture = newHeightTexture; + } public void OnGoldCountChanged(int goldCount) { diff --git a/scenes/Game.tscn b/scenes/Game.tscn index 3411594..78008f0 100644 --- a/scenes/Game.tscn +++ b/scenes/Game.tscn @@ -42,7 +42,7 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0 ) [node name="TileWorld" parent="." instance=ExtResource( 8 )] GenerationMapType = 0 -Size = 96 +Size = 64 [node name="GameUI" type="HBoxContainer" parent="."] anchor_left = 1.0 @@ -259,21 +259,21 @@ margin_bottom = 84.0 text = "Textures" [node name="WorldTextureRect" type="TextureRect" parent="Generator Container/WorldGeneratorContainer"] -visible = false margin_top = 88.0 -margin_right = 135.0 +margin_right = 100.0 margin_bottom = 188.0 rect_min_size = Vector2( 100, 100 ) -stretch_mode = 1 +expand = true +stretch_mode = 5 flip_v = true [node name="HeightTextureRect" type="TextureRect" parent="Generator Container/WorldGeneratorContainer"] -visible = false -margin_top = 88.0 -margin_right = 135.0 -margin_bottom = 188.0 +margin_top = 192.0 +margin_right = 100.0 +margin_bottom = 292.0 rect_min_size = Vector2( 100, 100 ) -stretch_mode = 1 +expand = true +stretch_mode = 5 flip_v = true [node name="EditorUI" parent="." instance=ExtResource( 4 )] diff --git a/scenes/TileWorld.cs b/scenes/TileWorld.cs index 6788999..3b70415 100644 --- a/scenes/TileWorld.cs +++ b/scenes/TileWorld.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Diagnostics; using Godot.Collections; using Namespace; -using Array = Godot.Collections.Array; using Vector2 = Godot.Vector2; using Vector3 = Godot.Vector3; @@ -19,8 +18,8 @@ public class TileWorld : Spatial } // constants - private static readonly Color RockColor = new Color(0.5f, 0.5f, 0.4f, 1f); - private static readonly Color GrassColor = new Color(0, 0.4f, 0, 1f); + private static readonly Color RockColor = new Color(0.5f, 0.5f, 0.4f); + private static readonly Color GrassColor = new Color(0, 0.4f, 0); private GenerationState _currentGenerationState = GenerationState.Heightmap; @@ -39,11 +38,11 @@ public class TileWorld : Spatial [ExportFlagsEnum(typeof(MapType))] public MapType GenerationMapType = MapType.Debug; [Export] public int Size = 64; - [Export] public bool DebugMap = false; + [Export] public bool DebugMap; public float HeightScale = 2.0f; - public Image Heightmap; - public Image Colormap; + public Image HeightmapImage; + public Image ColormapImage; public int Seed = 0; public Spatial Entities; public HexGrid HexGrid; @@ -55,10 +54,12 @@ public class TileWorld : Spatial private TextureRect _worldOffscreenTextureRect; private Viewport _heightmapOffscreenViewport; private TextureRect _heightmapOffscreenTextureRect; - private Array _rockAssets = new Array(); - private Array _grassAssets = new Array(); - private Array _treeAssets = new Array(); + private Array _rockAssets = new(); + private Array _grassAssets = new(); + private Array _treeAssets = new(); private Spatial _environmentNode; + private bool _resizeTriggered; + private int _resizeExtraFrameCount = 0; // Called when the node enters the scene tree for the first time. public override void _Ready() @@ -100,23 +101,57 @@ public class TileWorld : Spatial _environmentNode = GetNode("Environment"); Entities = GetNode("Entities"); - Generate(Size); + ResetWorldImages(Size); } + public void ResetWorldImages(int size) + { + GD.Print("Resetting World Images to size " + size); + + Vector2 sizeVector = new Vector2(size, size); + + ColormapImage = new Image(); + ColormapImage.Create(size, size, false, Image.Format.Rgba8); + ColormapImage.FillRect(new Rect2(0, 0, size, size), Colors.Black); + _worldOffscreenTextureRect.SetSize(sizeVector); + _worldOffscreenViewport.Size = sizeVector; + + HeightmapImage = new Image(); + HeightmapImage.Create(size, size, false, Image.Format.Rf); + HeightmapImage.FillRect(new Rect2(0, 0, size, size), Colors.ForestGreen); + _heightmapOffscreenTextureRect.SetSize(sizeVector); + _heightmapOffscreenViewport.Size = sizeVector; + } + + public void PrintTextureSizes() + { + GD.Print("Color Viewport: " + _worldOffscreenViewport.Size); + GD.Print("Color TextureRect: " + _worldOffscreenTextureRect.Texture.GetSize()); + GD.Print("Heightmap Viewport: " + _heightmapOffscreenViewport.Size); + GD.Print("Heightmap TextureRect: " + _heightmapOffscreenTextureRect.Texture.GetSize()); + } public void Generate(int size) { GD.Print("Triggering generation for size: " + size); + + if (Size != size) + { + ResetWorldImages(size); + _resizeTriggered = true; + _resizeExtraFrameCount = 1; + } + Size = size; _worldOffscreenViewport.Size = new Vector2(size, size); _heightmapOffscreenViewport.Size = new Vector2(size, size); - _halfSize = Mathf.RoundToInt((float)size) / 2; + _halfSize = Mathf.RoundToInt(size) / 2; HexGrid.SetBounds( TextureCoordToCell(new Vector2(0, 0)), TextureCoordToCell(new Vector2(size, size)) - ); + ); HexGrid.Obstacles.Clear(); HexGrid.Barriers.Clear(); @@ -139,29 +174,29 @@ public class TileWorld : Spatial private void GenerateDebugMap() { - Colormap = new Image(); - Colormap.Create(Size, Size, false, Image.Format.Rgba8); + ColormapImage = new Image(); + ColormapImage.Create(Size, Size, false, Image.Format.Rgba8); - Heightmap = new Image(); - Heightmap.Create(Size, Size, false, Image.Format.Rf); + HeightmapImage = new Image(); + HeightmapImage.Create(Size, Size, false, Image.Format.Rf); - Heightmap.Lock(); - Colormap.Lock(); + HeightmapImage.Lock(); + ColormapImage.Lock(); - foreach (int coord_x in Enumerable.Range(0, Size)) + foreach (int coordX in Enumerable.Range(0, Size)) { - foreach (int coord_y in Enumerable.Range(0, Size)) + foreach (int coordY in Enumerable.Range(0, Size)) { - Colormap.SetPixel(coord_x, coord_y, - new Color((float)Mathf.Min(coord_x, coord_y) / Size, (float)0, 0, 1)); - Heightmap.SetPixel(coord_x, coord_y, - new Color((float)Mathf.Min(coord_x, coord_y) / Size, (float)0, 0, 1)); + ColormapImage.SetPixel(coordX, coordY, + new Color((float)Mathf.Min(coordX, coordY) / Size, 0, 0)); + HeightmapImage.SetPixel(coordX, coordY, + new Color((float)Mathf.Min(coordX, coordY) / Size, 0, 0)); } } // Colormap.SetPixel(Size - 1, Size - 1, new Color(1, 1, 1, 1)); - Colormap.Fill(Colors.ForestGreen); - Colormap.Unlock(); + ColormapImage.Fill(Colors.ForestGreen); + ColormapImage.Unlock(); OnMapGenerationComplete(); } @@ -169,26 +204,26 @@ public class TileWorld : Spatial private void GenerateFlatMap() { - Colormap = new Image(); - Colormap.Create(Size, Size, false, Image.Format.Rgba8); + ColormapImage = new Image(); + ColormapImage.Create(Size, Size, false, Image.Format.Rgba8); - Heightmap = new Image(); - Heightmap.Create(Size, Size, false, Image.Format.Rf); + HeightmapImage = new Image(); + HeightmapImage.Create(Size, Size, false, Image.Format.Rf); - Heightmap.Lock(); - Colormap.Lock(); + HeightmapImage.Lock(); + ColormapImage.Lock(); - foreach (int coord_x in Enumerable.Range(0, Size)) + foreach (int coordX in Enumerable.Range(0, Size)) { - foreach (int coord_y in Enumerable.Range(0, Size)) + foreach (int coordY in Enumerable.Range(0, Size)) { - Heightmap.SetPixel(coord_x, coord_y, - new Color(0, 0, 0, 1)); + HeightmapImage.SetPixel(coordX, coordY, + new Color(0, 0, 0)); } } - Colormap.Fill(Colors.ForestGreen); - Colormap.Unlock(); + ColormapImage.Fill(Colors.ForestGreen); + ColormapImage.Unlock(); OnMapGenerationComplete(); } @@ -196,8 +231,8 @@ public class TileWorld : Spatial private void GenerateNoiseMap() { - Heightmap = new Image(); - Heightmap.Create(Size, Size, false, Image.Format.Rgba8); + HeightmapImage = new Image(); + HeightmapImage.Create(Size, Size, false, Image.Format.Rgba8); OpenSimplexNoise noiseGenerator = new OpenSimplexNoise(); @@ -208,10 +243,9 @@ public class TileWorld : Spatial noiseGenerator.Lacunarity = 4; ImageTexture heightmapTexture = new ImageTexture(); - heightmapTexture.CreateFromImage(noiseGenerator.GetSeamlessImage((int)Size)); + heightmapTexture.CreateFromImage(noiseGenerator.GetSeamlessImage(Size)); heightmapTexture.Flags = 0; _heightmapOffscreenTextureRect.Texture = heightmapTexture; - Heightmap.CopyFrom(_heightmapOffscreenViewport.GetTexture().GetData()); OnHeightMapChanged(); } @@ -231,6 +265,7 @@ public class TileWorld : Spatial private void OnHeightMapChanged() { + GD.Print("Triggering rendering of height map"); _currentGenerationState = GenerationState.Heightmap; _heightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once; } @@ -238,6 +273,11 @@ public class TileWorld : Spatial private void OnMapGenerationComplete() { _currentGenerationState = GenerationState.Done; + _worldOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled; + _heightmapOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Disabled; + _resizeTriggered = false; + + HeightmapImage.Lock(); EmitSignal("WorldGenerated"); } @@ -275,12 +315,14 @@ public class TileWorld : Spatial { Random environmentRandom = new Random(Seed); - Colormap.Lock(); + ColormapImage.Lock(); + HeightmapImage.Lock(); + foreach (int textureCoordU in Enumerable.Range(0, Size)) { foreach (int textureCoordV in Enumerable.Range(0, Size)) { - Color colorValue = Colormap.GetPixel(textureCoordU, textureCoordV); + Color colorValue = ColormapImage.GetPixel(textureCoordU, textureCoordV); Vector2 textureCoord = new Vector2(textureCoordU, textureCoordV); HexCell cell = TextureCoordToCell(textureCoord); Vector2 offsetCoord = cell.OffsetCoords; @@ -316,39 +358,53 @@ public class TileWorld : Spatial } } - Colormap.Unlock(); + HeightmapImage.Unlock(); + ColormapImage.Unlock(); } public override void _Process(float delta) { + if (_resizeTriggered && _resizeExtraFrameCount > 0) + { + _resizeExtraFrameCount--; + return; + } + if (_currentGenerationState == GenerationState.Heightmap) { + HeightmapImage.CopyFrom(_heightmapOffscreenViewport.GetTexture().GetData()); + _currentGenerationState = GenerationState.Color; ImageTexture imageTexture = new ImageTexture(); - imageTexture.CreateFromImage(Heightmap); + imageTexture.CreateFromImage(HeightmapImage); imageTexture.Flags = 0; _worldOffscreenTextureRect.Texture = imageTexture; + + GD.Print("Triggering rendering of color map"); + _worldOffscreenViewport.RenderTargetUpdateMode = Viewport.UpdateMode.Once; + _resizeExtraFrameCount = 1; } else if (_currentGenerationState == GenerationState.Color) { - Colormap = new Image(); - Colormap.Create(Size, Size, false, Image.Format.Rgb8); - Colormap.CopyFrom(_worldOffscreenViewport.GetTexture().GetData()); - Heightmap.Lock(); + ColormapImage = new Image(); + ColormapImage.Create(Size, Size, false, Image.Format.Rgb8); + ColormapImage.CopyFrom(_worldOffscreenViewport.GetTexture().GetData()); _currentGenerationState = GenerationState.Objects; PopulateEnvironment(); - + } + else if (_currentGenerationState == GenerationState.Objects) + { OnMapGenerationComplete(); } } public bool IsOffsetCoordValid(Vector2 offsetCoord) { - return ((int)Math.Clamp(offsetCoord.x, -Size / 2, Size / 2 - 1) == (int)offsetCoord.x - && (int)Math.Clamp(offsetCoord.y, -Size / 2, Size / 2 - 1) == (int)offsetCoord.y); + return ((int)Math.Clamp(offsetCoord.x, -(float)Size / 2, (float)Size / 2 - 1) == (int)offsetCoord.x + && (int)Math.Clamp(offsetCoord.y, -(float)Size / 2, (float)Size / 2 - 1) == (int)offsetCoord.y); } @@ -365,7 +421,6 @@ public class TileWorld : Spatial public Vector2 OffsetToTextureCoord(Vector2 offsetCoord) { -// Vector2 textureCoord = (offsetCoord - Vector2.One * (Mathf.Floor(Size / 2))) % (Vector2.One * Size); Vector2 mapSize = Vector2.One * Size; Vector2 textureCoord = (offsetCoord + mapSize / 2).PosMod(mapSize); return textureCoord; @@ -375,7 +430,7 @@ public class TileWorld : Spatial { Vector2 textureCoord = OffsetToTextureCoord(offsetCoord); - Heightmap.SetPixel((int)textureCoord.x, (int)textureCoord.y, new Color(height, 0f, 0f)); + HeightmapImage.SetPixel((int)textureCoord.x, (int)textureCoord.y, new Color(height, 0f, 0f)); } public float GetHeightAtOffset(Vector2 offsetCoord) @@ -387,15 +442,12 @@ public class TileWorld : Spatial Vector2 textureCoord = OffsetToTextureCoord(offsetCoord); - float heightmapHeight = Heightmap.GetPixel((int)textureCoord.x, (int)(textureCoord.y)).r; - + float heightmapHeight = HeightmapImage.GetPixel((int)textureCoord.x, (int)(textureCoord.y)).r; + if (heightmapHeight > 0.5) { heightmapHeight = 0.6f; } -// heightmapHeight = Mathf.Floor(heightmapHeight); -// heightmapHeight = heightmapHeight * 10) -// heightmapHeight = Mathf.Clamp(heightmapHeight, -1f, 5); return heightmapHeight * HeightScale; } @@ -405,11 +457,11 @@ public class TileWorld : Spatial { Vector2 textureCoord = OffsetToTextureCoord(offsetCoord); - Colormap.Lock(); - Colormap.SetPixel((int)textureCoord.x, (int)textureCoord.y, color); - Colormap.Unlock(); + ColormapImage.Lock(); + ColormapImage.SetPixel((int)textureCoord.x, (int)textureCoord.y, color); + ColormapImage.Unlock(); - EmitSignal("WorldGenerated"); + OnMapGenerationComplete(); } public Vector2 WorldToOffsetCoords(Vector3 worldCoord) diff --git a/scenes/TileWorld.tscn b/scenes/TileWorld.tscn index 00ebb5a..90aa145 100644 --- a/scenes/TileWorld.tscn +++ b/scenes/TileWorld.tscn @@ -26,7 +26,11 @@ hdr = false disable_3d = true usage = 0 render_target_v_flip = true -render_target_update_mode = 1 +render_target_update_mode = 0 +shadow_atlas_quad_0 = 0 +shadow_atlas_quad_1 = 0 +shadow_atlas_quad_2 = 0 +shadow_atlas_quad_3 = 0 [node name="TextureRect" type="TextureRect" parent="WorldOffscreenViewport"] material = ExtResource( 3 ) @@ -42,7 +46,11 @@ hdr = false disable_3d = true usage = 0 render_target_v_flip = true -render_target_update_mode = 1 +render_target_update_mode = 0 +shadow_atlas_quad_0 = 0 +shadow_atlas_quad_1 = 0 +shadow_atlas_quad_2 = 0 +shadow_atlas_quad_3 = 0 [node name="TextureRect" type="TextureRect" parent="HeightmapOffscreenViewport"] material = ExtResource( 4 ) diff --git a/scenes/tests/NavigationTests.cs b/scenes/tests/NavigationTests.cs index deb57c3..d4a7b9c 100644 --- a/scenes/tests/NavigationTests.cs +++ b/scenes/tests/NavigationTests.cs @@ -81,10 +81,10 @@ public class NavigationTests : Spatial _player.Transform = playerTransform; ImageTexture newWorldTexture = new ImageTexture(); - newWorldTexture.CreateFromImage(_tileWorld.Colormap, + newWorldTexture.CreateFromImage(_tileWorld.ColormapImage, (uint)(Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat)); _tileMaterial.SetShaderParam("MapAlbedoTexture", newWorldTexture); - _tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.Colormap.GetSize().x); + _tileMaterial.SetShaderParam("TextureSize", (int)_tileWorld.ColormapImage.GetSize().x); }