Heightmap and Colormap generation kind of works now.

WorldChunkRefactoring
Martin Felis 2023-05-21 17:24:37 +02:00
parent 55da2346d3
commit 866fd11399
9 changed files with 236 additions and 131 deletions

View File

@ -1,59 +1,6 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
render_mode skip_vertex_transform;
void vertex() {
VERTEX = (WORLD_MATRIX * (EXTRA_MATRIX * vec4(VERTEX, 0.0, 1.0))).xy;
}
vec3 color_ramp(float h) {
if (h < 0.4f) {
return vec3(0, 0, 0.6);
} else if (h < 0.45f) {
return vec3(0, 0, 0.7);
} else if (h < 0.5f) {
return vec3(0, 0, 1);
} else if (h < 0.55){
return vec3(0.8, 0.8, 0.1);
} else if (h < 0.6){
return vec3(0, 0.6, 0);
} else if (h < 0.68){
return vec3(0, 0.4, 0);
} else if (h <= 0.78){
return vec3(0.6, 0.6, 0.6);
} else if (h < 1.0){
return vec3(0.8, 0.8, 0.8);
}
return vec3(1.0);
}
vec3 rgbToGrayscale(vec3 color) {
return vec3(dot(color.rgb, vec3(0.299, 0.587, 0.144)));
}
float borderFalloff(vec2 uv) {
return min(
(0.5 - abs(-uv.x + 0.5)) * 2.0,
(0.5 - abs(-uv.y + 0.5)) * 2.0);
}
float borderFalloffCircle(vec2 uv) {
return (0.5 - length(vec2(uv - vec2(0.5, 0.5)))) * 2.0;
}
void fragment() {
vec4 texture_color = texture(TEXTURE, UV);
COLOR.rgb = vec3(abs(UV.x - 0.5) * 2.0);
//COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
COLOR.rgb = color_ramp(texture_color.r * borderFalloff(UV) * 1.8);
}
"
[ext_resource path="res://materials/shader/IslandColorRampShader.gdshader" type="Shader" id=1]
[resource]
shader = SubResource( 1 )
shader = ExtResource( 1 )

View File

@ -0,0 +1,6 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
[ext_resource path="res://materials/shader/IslandHeightmapFalloffShader.gdshader" type="Shader" id=1]
[resource]
shader = ExtResource( 1 )

View File

@ -47,7 +47,7 @@ void vertex() {
}
void fragment() {
ALBEDO = texture(MapAlbedoTexture, map_coord).rgb;
ALBEDO = pow(texture(MapAlbedoTexture, map_coord).rgb, vec3(2.4));
}
void light() {

View File

@ -0,0 +1,52 @@
shader_type canvas_item;
render_mode skip_vertex_transform;
void vertex() {
VERTEX = (WORLD_MATRIX * (EXTRA_MATRIX * vec4(VERTEX, 0.0, 1.0))).xy;
}
vec3 color_ramp(float h) {
if (h < 0.4f) {
return vec3(0, 0, 0.6);
} else if (h < 0.45f) {
return vec3(0, 0, 0.7);
} else if (h < 0.5f) {
return vec3(0, 0, 1);
} else if (h < 0.55){
return vec3(0.8, 0.8, 0.1);
} else if (h < 0.6){
return vec3(0, 0.6, 0);
} else if (h < 0.68){
return vec3(0, 0.4, 0);
} else if (h <= 0.78){
return vec3(0.6, 0.6, 0.6);
} else if (h < 1.0){
return vec3(0.8, 0.8, 0.8);
}
return vec3(1.0);
}
vec3 rgbToGrayscale(vec3 color) {
return vec3(dot(color.rgb, vec3(0.299, 0.587, 0.144)));
}
float borderFalloff(vec2 uv) {
return min(
(0.5 - abs(-uv.x + 0.5)) * 2.0,
(0.5 - abs(-uv.y + 0.5)) * 2.0);
}
float borderFalloffCircle(vec2 uv) {
return (0.5 - length(vec2(uv - vec2(0.5, 0.5)))) * 2.0;
}
void fragment() {
vec4 texture_color = texture(TEXTURE, UV);
COLOR.rgb = vec3(abs(UV.x - 0.5) * 2.0);
//COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
COLOR.rgb = color_ramp(texture_color.r);
}

View File

@ -0,0 +1,52 @@
shader_type canvas_item;
render_mode skip_vertex_transform;
void vertex() {
VERTEX = (WORLD_MATRIX * (EXTRA_MATRIX * vec4(VERTEX, 0.0, 1.0))).xy;
}
vec3 color_ramp(float h) {
if (h < 0.4f) {
return vec3(0, 0, 0.6);
} else if (h < 0.45f) {
return vec3(0, 0, 0.7);
} else if (h < 0.5f) {
return vec3(0, 0, 1);
} else if (h < 0.55){
return vec3(0.8, 0.8, 0.1);
} else if (h < 0.6){
return vec3(0, 0.6, 0);
} else if (h < 0.68){
return vec3(0, 0.4, 0);
} else if (h <= 0.78){
return vec3(0.6, 0.6, 0.6);
} else if (h < 1.0){
return vec3(0.8, 0.8, 0.8);
}
return vec3(1.0);
}
vec3 rgbToGrayscale(vec3 color) {
return vec3(dot(color.rgb, vec3(0.299, 0.587, 0.144)));
}
float borderFalloff(vec2 uv) {
return min(
(0.5 - abs(-uv.x + 0.5)) * 2.0,
(0.5 - abs(-uv.y + 0.5)) * 2.0);
}
float borderFalloffCircle(vec2 uv) {
return (0.5 - length(vec2(uv - vec2(0.5, 0.5)))) * 2.0;
}
void fragment() {
vec4 texture_color = texture(TEXTURE, UV);
COLOR.rgb = vec3(abs(UV.x - 0.5) * 2.0);
//COLOR.rgb = color_ramp(texture_color.r * borderFalloffCircle(UV) * 1.8);
COLOR.rgb = vec3(texture_color.r * borderFalloff(UV) * 1.8);
}

View File

@ -9,17 +9,17 @@
config_version=4
_global_script_classes=[ {
"base": "Node",
"base": "Reference",
"class": "ClickableComponent",
"language": "GDScript",
"path": "res://components/ClickableComponent.gd"
}, {
"base": "KinematicBody2D",
"base": "Reference",
"class": "CollisionLine",
"language": "GDScript",
"path": "res://utils/CollisionLine.gd"
}, {
"base": "Node",
"base": "Reference",
"class": "ColorComponent",
"language": "GDScript",
"path": "res://components/ColorComponent.gd"
@ -54,7 +54,7 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://utils/SpringDamper.gd"
}, {
"base": "Sprite",
"base": "Reference",
"class": "TintedSpriteComponent",
"language": "GDScript",
"path": "res://components/TintedSpriteComponent.gd"

View File

@ -244,26 +244,33 @@ public class Game : Spatial
}
public void ResetGameState()
{
Transform playerStartTransform = Transform.Identity;
float height = _tileWorld.GetHeightAtOffset(new Vector2(0, 0));
playerStartTransform.origin.y = height;
_player.Transform = playerStartTransform;
_player.TaskQueueComponent.Reset();
_player.Navigation.PlanDirectPath(playerStartTransform.origin, playerStartTransform.origin, playerStartTransform.basis.Quat());
}
public void OnWorldGenerated()
{
GD.Print("Using new map");
ImageTexture newWorldTexture = new ImageTexture();
newWorldTexture.CreateFromImage(_tileWorld.Colormap, (uint) (Texture.FlagsEnum.Mipmaps | Texture.FlagsEnum.Repeat));
ImageTexture newHeightTexture = new ImageTexture();
newHeightTexture.CreateFromImage(_tileWorld.Heightmap, (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;
_streamContainer.OnWorldGenerated();
// Reset player transform to offset 0,0 and at current height
Transform playerStartTransform = Transform.Identity;
float height = _tileWorld.GetHeightAtOffset(new Vector2(0, 0));
playerStartTransform.origin.y = height;
_player.Transform = playerStartTransform;
ResetGameState();
}
}

View File

@ -9,12 +9,21 @@ using Vector3 = Godot.Vector3;
public class TileWorld : Spatial
{
private enum GenerationState
{
Heightmap,
Color,
Done
}
private GenerationState CurrentGenerationState = GenerationState.Heightmap;
// signals
[Signal]
delegate void WorldGenerated();
// public members
public float Size = 5;
public float Size = 100;
public float HeightScale = 10.0f;
public Image Heightmap;
public Image Colormap;
@ -23,39 +32,42 @@ public class TileWorld : Spatial
// private members
private HexGrid _hexGrid;
private Random _tileTypeRandom;
private Viewport _offscreenViewport;
private TextureRect _offscreenTextureRect;
private Viewport _worldOffscreenViewport;
private TextureRect _worldOffscreenTextureRect;
private Viewport _heightmapOffscreenViewport;
private TextureRect _heightmapOffscreenTextureRect;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
_hexGrid = new HexGrid();
_tileTypeRandom = new Random();
_offscreenViewport = (Viewport)GetNode("OffscreenViewport");
Debug.Assert(_offscreenViewport != null);
_offscreenViewport.Size = new Vector2(Size, Size);
_offscreenTextureRect = (TextureRect)GetNode("OffscreenViewport/TextureRect");
Debug.Assert(_offscreenTextureRect != null);
_offscreenTextureRect.SetSize(new Vector2(Size, Size));
//VisualServer.Singleton.Connect("frame_post_draw", this, nameof(GenerateNoiseColorMap));
_worldOffscreenViewport = (Viewport)GetNode("WorldOffscreenViewport");
Debug.Assert(_worldOffscreenViewport != null);
_worldOffscreenViewport.Size = new Vector2(Size, Size);
_worldOffscreenTextureRect = (TextureRect)GetNode("WorldOffscreenViewport/TextureRect");
Debug.Assert(_worldOffscreenTextureRect != null);
_worldOffscreenTextureRect.SetSize(new Vector2(Size, Size));
_heightmapOffscreenViewport = (Viewport)GetNode("HeightmapOffscreenViewport");
Debug.Assert(_heightmapOffscreenViewport != null);
_heightmapOffscreenViewport.Size = new Vector2(Size, Size);
_heightmapOffscreenTextureRect = (TextureRect)GetNode("HeightmapOffscreenViewport/TextureRect");
Debug.Assert(_heightmapOffscreenTextureRect != null);
_heightmapOffscreenTextureRect.SetSize(new Vector2(Size, Size));
Generate();
}
public void Generate()
{
//GenerateSimpleMap();
//GenerateNoiseMap();
GenerateNoiseColorMap();
GenerateNoiseMap();
//GenerateDebugMap();
EmitSignal("WorldGenerated");
}
private void GenerateDebugMap()
{
Colormap = new Image();
@ -63,7 +75,7 @@ public class TileWorld : Spatial
Heightmap = new Image();
Heightmap.Create((int)Size, (int)Size, false, Image.Format.Rf);
Heightmap.Lock();
Colormap.Lock();
foreach (int coord_x in Enumerable.Range(0, (int)Size))
@ -78,16 +90,17 @@ public class TileWorld : Spatial
{
coord_to_height = 1;
}
SetHeightAtOffset(new Vector2(coord_x, coord_y), coord_to_height);
}
}
Colormap.Unlock();
ImageTexture imageTexture = new ImageTexture();
imageTexture.CreateFromImage(Heightmap);
imageTexture.Flags = 0;
_offscreenTextureRect.Texture = imageTexture;
_worldOffscreenTextureRect.Texture = imageTexture;
Colormap.CopyFrom(imageTexture.GetData());
}
@ -97,40 +110,21 @@ public class TileWorld : Spatial
Heightmap.Create((int)Size, (int)Size, false, Image.Format.Rf);
Heightmap.Lock();
foreach (int coord_x in Enumerable.Range(-(int) Size / 2, (int)Size))
foreach (int coord_x in Enumerable.Range(-(int)Size / 2, (int)Size))
{
foreach (int coord_y in Enumerable.Range(-(int) Size / 2, (int)Size))
foreach (int coord_y in Enumerable.Range(-(int)Size / 2, (int)Size))
{
SetHeightAtOffset(new Vector2(coord_x, coord_y), 5f);
}
}
}
private void GenerateNoiseMap()
{
Heightmap = new Image();
Heightmap.Create((int)Size, (int)Size, false, Image.Format.Rf);
NoiseTexture noiseTexture = new NoiseTexture();
OpenSimplexNoise noiseGenerator = new OpenSimplexNoise();
Heightmap.Create((int)Size, (int)Size, false, Image.Format.Rgba8);
noiseGenerator.Seed = Seed;
noiseGenerator.Octaves = 4;
noiseGenerator.Period = 20;
noiseGenerator.Persistence = 0.1f;
noiseGenerator.Lacunarity = 2;
Heightmap.CopyFrom(noiseGenerator.GetImage((int)Size, (int)Size, null));
}
private void GenerateNoiseColorMap()
{
Colormap = new Image();
Colormap.Create((int)Size, (int)Size, false, Image.Format.Rgba8);
NoiseTexture noiseTexture = new NoiseTexture();
OpenSimplexNoise noiseGenerator = new OpenSimplexNoise();
noiseGenerator.Seed = Seed;
@ -139,30 +133,55 @@ public class TileWorld : Spatial
noiseGenerator.Persistence = 0.2f;
noiseGenerator.Lacunarity = 4;
ImageTexture imageTexture = new ImageTexture();
Heightmap = noiseGenerator.GetSeamlessImage((int)Size);
imageTexture.CreateFromImage(Heightmap);
imageTexture.Flags = 0;
_offscreenTextureRect.Texture = imageTexture;
Colormap.CopyFrom(_offscreenViewport.GetTexture().GetData());
Heightmap.Lock();
ImageTexture heightmapTexture = new ImageTexture();
// heightmapTexture.CreateFromImage(noiseGenerator.GetImage((int)Size, (int)Size));
heightmapTexture.CreateFromImage(noiseGenerator.GetSeamlessImage((int) Size));
heightmapTexture.Flags = 0;
_heightmapOffscreenTextureRect.Texture = heightmapTexture;
Heightmap.CopyFrom(_heightmapOffscreenViewport.GetTexture().GetData());
CurrentGenerationState = GenerationState.Heightmap;
}
public override void _Process(float delta)
{
if (CurrentGenerationState == GenerationState.Heightmap)
{
CurrentGenerationState = GenerationState.Color;
ImageTexture imageTexture = new ImageTexture();
imageTexture.CreateFromImage(Heightmap);
imageTexture.Flags = 0;
_worldOffscreenTextureRect.Texture = imageTexture;
}
else if (CurrentGenerationState == GenerationState.Color)
{
Colormap = new Image();
Colormap.Create((int)Size, (int)Size, false, Image.Format.Rgba8);
Colormap.CopyFrom(_worldOffscreenViewport.GetTexture().GetData());
Heightmap.Lock();
CurrentGenerationState = GenerationState.Done;
EmitSignal("WorldGenerated");
}
}
public void ApplyHeightmap(Image heightmap)
{
foreach (int coord_x in Enumerable.Range(-(int) Size / 2, (int)Size))
foreach (int coord_x in Enumerable.Range(-(int)Size / 2, (int)Size))
{
foreach (int coord_y in Enumerable.Range(-(int) Size / 2, (int)Size))
foreach (int coord_y in Enumerable.Range(-(int)Size / 2, (int)Size))
{
Vector2 textureCoord = OffsetToTextureCoord(new Vector2(coord_x, coord_y));
float height = heightmap.GetPixel((int) textureCoord.x, (int) textureCoord.y).r;
float height = heightmap.GetPixel((int)textureCoord.x, (int)textureCoord.y).r;
SetHeightAtOffset(new Vector2(coord_x, coord_y), height);
}
}
}
public bool IsOffsetCoordValid(Vector2 offsetCoord)
{
return ((int)Math.Clamp(offsetCoord.x, -Size / 2, Size / 2 - 1) == (int)offsetCoord.x
@ -200,14 +219,19 @@ public class TileWorld : Spatial
public void SetHeightAtOffset(Vector2 offsetCoord, float height)
{
Vector2 textureCoord = OffsetToTextureCoord(offsetCoord);
Heightmap.SetPixel((int) textureCoord.x, (int) textureCoord.y, new Color(height, 0f, 0f));
Heightmap.SetPixel((int)textureCoord.x, (int)textureCoord.y, new Color(height, 0f, 0f));
}
public float GetHeightAtOffset(Vector2 offsetCoord)
{
Vector2 textureCoord = OffsetToTextureCoord(offsetCoord);
if (CurrentGenerationState != GenerationState.Done)
{
return 0f;
}
Vector2 textureCoord = OffsetToTextureCoord(offsetCoord);
return Heightmap.GetPixel((int)textureCoord.x, (int)(textureCoord.y)).r * HeightScale;
}

View File

@ -1,8 +1,9 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=5 format=2]
[ext_resource path="res://scenes/TileWorld.cs" type="Script" id=1]
[ext_resource path="res://icon.png" type="Texture" id=2]
[ext_resource path="res://materials/IslandColorRampShader.tres" type="Material" id=3]
[ext_resource path="res://materials/IslandHeightmapFalloffShader.tres" type="Material" id=4]
[node name="TileWorld" type="Spatial"]
script = ExtResource( 1 )
@ -12,7 +13,7 @@ transform = Transform( 0.328059, -0.878387, 0.347583, 0, 0.367946, 0.929847, -0.
shadow_enabled = true
directional_shadow_mode = 0
[node name="OffscreenViewport" type="Viewport" parent="."]
[node name="WorldOffscreenViewport" type="Viewport" parent="."]
size = Vector2( 100, 100 )
own_world = true
handle_input_locally = false
@ -22,8 +23,24 @@ usage = 0
render_target_v_flip = true
render_target_update_mode = 3
[node name="TextureRect" type="TextureRect" parent="OffscreenViewport"]
[node name="TextureRect" type="TextureRect" parent="WorldOffscreenViewport"]
material = ExtResource( 3 )
texture = ExtResource( 2 )
[node name="Camera2D" type="Camera2D" parent="OffscreenViewport"]
[node name="Camera2D" type="Camera2D" parent="WorldOffscreenViewport"]
[node name="HeightmapOffscreenViewport" type="Viewport" parent="."]
size = Vector2( 100, 100 )
own_world = true
handle_input_locally = false
hdr = false
disable_3d = true
usage = 0
render_target_v_flip = true
render_target_update_mode = 3
[node name="TextureRect" type="TextureRect" parent="HeightmapOffscreenViewport"]
material = ExtResource( 4 )
texture = ExtResource( 2 )
[node name="Camera2D" type="Camera2D" parent="HeightmapOffscreenViewport"]