fix river water direction2
This commit is contained in:
@@ -8,6 +8,19 @@ const CHUNK_GENERATION_STEPS_PER_FRAME: int = 2
|
|||||||
const CHUNK_CLEANUP_STEPS_PER_FRAME: int = 4
|
const CHUNK_CLEANUP_STEPS_PER_FRAME: int = 4
|
||||||
const LAMPPOST_WIRE_STEPS_PER_FRAME: int = 1
|
const LAMPPOST_WIRE_STEPS_PER_FRAME: int = 1
|
||||||
const RAILWAY_SCENE_DIRECTORY: String = "res://tgcc/chunk/railway/scene"
|
const RAILWAY_SCENE_DIRECTORY: String = "res://tgcc/chunk/railway/scene"
|
||||||
|
const RIVER_SIDE_ORDER: Array[String] = ["north", "est", "south", "west"]
|
||||||
|
const RIVER_DIRECTIONS: Dictionary = {
|
||||||
|
"north": Vector2(0.0, -1.0),
|
||||||
|
"est": Vector2(1.0, 0.0),
|
||||||
|
"south": Vector2(0.0, 1.0),
|
||||||
|
"west": Vector2(-1.0, 0.0),
|
||||||
|
}
|
||||||
|
const RIVER_NEIGHBOUR_OFFSETS: Dictionary = {
|
||||||
|
"north": Vector2i(0, -1),
|
||||||
|
"est": Vector2i(1, 0),
|
||||||
|
"south": Vector2i(0, 1),
|
||||||
|
"west": Vector2i(-1, 0),
|
||||||
|
}
|
||||||
|
|
||||||
@export_group("Rails")
|
@export_group("Rails")
|
||||||
@export var rail_path: Path3D
|
@export var rail_path: Path3D
|
||||||
@@ -617,10 +630,14 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
|||||||
if info_new != null and "have_lamppost" in info_new:
|
if info_new != null and "have_lamppost" in info_new:
|
||||||
have_lamppost = info_new.have_lamppost
|
have_lamppost = info_new.have_lamppost
|
||||||
|
|
||||||
|
var river_flow_direction = _calculate_river_flow_direction(grid_pos, choise.data["river_connections"])
|
||||||
|
_apply_river_flow_direction(new_chunk, river_flow_direction)
|
||||||
|
|
||||||
board[grid_pos] = {
|
board[grid_pos] = {
|
||||||
"type": "bioma",
|
"type": "bioma",
|
||||||
"exit": choise.data["connections"],
|
"exit": choise.data["connections"],
|
||||||
"river_exit": choise.data["river_connections"],
|
"river_exit": choise.data["river_connections"],
|
||||||
|
"river_flow_direction": river_flow_direction,
|
||||||
"heights": choise.data["heights"],
|
"heights": choise.data["heights"],
|
||||||
"node": new_chunk,
|
"node": new_chunk,
|
||||||
"info": info_new,
|
"info": info_new,
|
||||||
@@ -647,12 +664,109 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
|||||||
"type": "biome",
|
"type": "biome",
|
||||||
"exit": {"north":false, "est":false, "south":false, "west":false},
|
"exit": {"north":false, "est":false, "south":false, "west":false},
|
||||||
"river_exit": {"north":false, "est":false, "south":false, "west":false},
|
"river_exit": {"north":false, "est":false, "south":false, "west":false},
|
||||||
|
"river_flow_direction": Vector2.ZERO,
|
||||||
"heights": safe_heights,
|
"heights": safe_heights,
|
||||||
"node": backup,
|
"node": backup,
|
||||||
"info": info_backup,
|
"info": info_backup,
|
||||||
"have_lamppost": false
|
"have_lamppost": false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _calculate_river_flow_direction(grid_pos: Vector2i, river_connections: Dictionary) -> Vector2:
|
||||||
|
var connected_sides: Array[String] = []
|
||||||
|
for side in RIVER_SIDE_ORDER:
|
||||||
|
if river_connections.has(side) and river_connections[side]:
|
||||||
|
connected_sides.append(side)
|
||||||
|
|
||||||
|
if connected_sides.is_empty():
|
||||||
|
return Vector2.ZERO
|
||||||
|
|
||||||
|
var neighbour_flow = _get_connected_neighbour_river_flow(grid_pos, connected_sides)
|
||||||
|
if not neighbour_flow.is_zero_approx():
|
||||||
|
var continued_flow = _continue_river_flow_from_neighbour(grid_pos, connected_sides, neighbour_flow)
|
||||||
|
if not continued_flow.is_zero_approx():
|
||||||
|
return continued_flow.normalized()
|
||||||
|
|
||||||
|
var default_flow = _get_default_river_flow(connected_sides)
|
||||||
|
if default_flow.is_zero_approx():
|
||||||
|
return Vector2.ZERO
|
||||||
|
return default_flow.normalized()
|
||||||
|
|
||||||
|
func _get_connected_neighbour_river_flow(grid_pos: Vector2i, connected_sides: Array[String]) -> Vector2:
|
||||||
|
for side in connected_sides:
|
||||||
|
var neighbour_pos: Vector2i = grid_pos + RIVER_NEIGHBOUR_OFFSETS[side]
|
||||||
|
if not board.has(neighbour_pos):
|
||||||
|
continue
|
||||||
|
var neighbour = board[neighbour_pos]
|
||||||
|
if not neighbour.has("river_flow_direction"):
|
||||||
|
continue
|
||||||
|
var neighbour_flow: Vector2 = neighbour["river_flow_direction"]
|
||||||
|
if not neighbour_flow.is_zero_approx():
|
||||||
|
return neighbour_flow.normalized()
|
||||||
|
return Vector2.ZERO
|
||||||
|
|
||||||
|
func _continue_river_flow_from_neighbour(grid_pos: Vector2i, connected_sides: Array[String], neighbour_flow: Vector2) -> Vector2:
|
||||||
|
for side in connected_sides:
|
||||||
|
var neighbour_pos: Vector2i = grid_pos + RIVER_NEIGHBOUR_OFFSETS[side]
|
||||||
|
if not board.has(neighbour_pos):
|
||||||
|
continue
|
||||||
|
var neighbour = board[neighbour_pos]
|
||||||
|
if not neighbour.has("river_flow_direction"):
|
||||||
|
continue
|
||||||
|
var side_direction: Vector2 = RIVER_DIRECTIONS[side]
|
||||||
|
var neighbour_direction: Vector2 = neighbour["river_flow_direction"]
|
||||||
|
if neighbour_direction.is_zero_approx():
|
||||||
|
continue
|
||||||
|
neighbour_direction = neighbour_direction.normalized()
|
||||||
|
var other_sides = connected_sides.duplicate()
|
||||||
|
other_sides.erase(side)
|
||||||
|
if other_sides.is_empty():
|
||||||
|
return neighbour_direction
|
||||||
|
|
||||||
|
var other_direction = _get_average_river_side_direction(other_sides)
|
||||||
|
if neighbour_direction.dot(-side_direction) > 0.25:
|
||||||
|
return other_direction - side_direction
|
||||||
|
if neighbour_direction.dot(side_direction) > 0.25:
|
||||||
|
return side_direction - other_direction
|
||||||
|
|
||||||
|
var default_flow = _get_default_river_flow(connected_sides)
|
||||||
|
if default_flow.dot(neighbour_flow) < 0.0:
|
||||||
|
return -default_flow
|
||||||
|
return default_flow
|
||||||
|
|
||||||
|
func _get_default_river_flow(connected_sides: Array[String]) -> Vector2:
|
||||||
|
if connected_sides.size() == 1:
|
||||||
|
return RIVER_DIRECTIONS[connected_sides[0]]
|
||||||
|
|
||||||
|
if connected_sides.has("north") and connected_sides.has("south"):
|
||||||
|
return Vector2(0.0, 1.0)
|
||||||
|
if connected_sides.has("est") and connected_sides.has("west"):
|
||||||
|
return Vector2(1.0, 0.0)
|
||||||
|
|
||||||
|
var start_direction: Vector2 = RIVER_DIRECTIONS[connected_sides[0]]
|
||||||
|
var end_direction = _get_average_river_side_direction(connected_sides.slice(1))
|
||||||
|
return end_direction - start_direction
|
||||||
|
|
||||||
|
func _get_average_river_side_direction(sides: Array[String]) -> Vector2:
|
||||||
|
var direction := Vector2.ZERO
|
||||||
|
for side in sides:
|
||||||
|
direction += RIVER_DIRECTIONS[side]
|
||||||
|
if direction.is_zero_approx():
|
||||||
|
return Vector2.ZERO
|
||||||
|
return direction / float(sides.size())
|
||||||
|
|
||||||
|
func _apply_river_flow_direction(root: Node, flow_direction: Vector2) -> void:
|
||||||
|
if flow_direction.is_zero_approx():
|
||||||
|
return
|
||||||
|
_set_river_flow_direction_recursive(root, flow_direction.normalized())
|
||||||
|
|
||||||
|
func _set_river_flow_direction_recursive(node: Node, flow_direction: Vector2) -> void:
|
||||||
|
if node is MeshInstance3D and node.name.begins_with("Water_F"):
|
||||||
|
var mesh_instance := node as MeshInstance3D
|
||||||
|
mesh_instance.set_instance_shader_parameter("river_flow_direction", flow_direction)
|
||||||
|
|
||||||
|
for child in node.get_children():
|
||||||
|
_set_river_flow_direction_recursive(child, flow_direction)
|
||||||
|
|
||||||
func _needed_connection(near_pos: Vector2i, side_needed: String) -> int:
|
func _needed_connection(near_pos: Vector2i, side_needed: String) -> int:
|
||||||
if not board.has(near_pos):
|
if not board.has(near_pos):
|
||||||
_register_cell_with_ray(near_pos)
|
_register_cell_with_ray(near_pos)
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ uniform float foam_roughness : hint_range(0.0, 1.0, 0.01) = 0.05;
|
|||||||
|
|
||||||
group_uniforms Wave;
|
group_uniforms Wave;
|
||||||
uniform sampler2D wave_texture;
|
uniform sampler2D wave_texture;
|
||||||
#if !USE_UNSHADED
|
|
||||||
uniform sampler2D wave_normal_texture;
|
|
||||||
#endif
|
|
||||||
uniform float wave_softness : hint_range(0.0, 10.0, 0.1) = 3.0;
|
uniform float wave_softness : hint_range(0.0, 10.0, 0.1) = 3.0;
|
||||||
uniform vec2 wave_scale = vec2(0.2);
|
uniform vec2 wave_scale = vec2(0.2);
|
||||||
uniform vec2 wave_layer_scale = vec2(1.5);
|
uniform vec2 wave_layer_scale = vec2(1.5);
|
||||||
@@ -42,6 +39,7 @@ uniform float wave_highlight : hint_range(0.0, 1.0, 0.05) = 0.5;
|
|||||||
|
|
||||||
group_uniforms Wave.Motion;
|
group_uniforms Wave.Motion;
|
||||||
uniform vec2 wave_velocity = vec2(0.02);
|
uniform vec2 wave_velocity = vec2(0.02);
|
||||||
|
instance uniform vec2 river_flow_direction = vec2(0.0, 0.0);
|
||||||
|
|
||||||
group_uniforms Foam;
|
group_uniforms Foam;
|
||||||
uniform sampler2D foam_texture;
|
uniform sampler2D foam_texture;
|
||||||
@@ -72,6 +70,7 @@ uniform float foam_exponent = 2.0;
|
|||||||
|
|
||||||
uniform sampler2D screen_texture : hint_screen_texture;
|
uniform sampler2D screen_texture : hint_screen_texture;
|
||||||
varying vec3 world_pos;
|
varying vec3 world_pos;
|
||||||
|
varying vec2 world_wave_velocity;
|
||||||
|
|
||||||
#if USE_CAUSTICS
|
#if USE_CAUSTICS
|
||||||
vec3 sample_caustics(vec2 uv){
|
vec3 sample_caustics(vec2 uv){
|
||||||
@@ -103,17 +102,47 @@ vec4 sample_wave(sampler2D tex, vec2 uv, vec2 velocity, float lod){
|
|||||||
return wave2;
|
return wave2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 sample_wave_normal(vec2 uv, vec2 velocity, float center_wave) {
|
||||||
|
vec2 normal_offset = vec2(0.25, 0.0);
|
||||||
|
float wave_x = sample_wave(wave_texture, uv + normal_offset.xy, velocity, wave_softness).r;
|
||||||
|
float wave_z = sample_wave(wave_texture, uv + normal_offset.yx, velocity, wave_softness).r;
|
||||||
|
vec2 slope = vec2(center_wave - wave_x, center_wave - wave_z) * 0.35;
|
||||||
|
return normalize(vec3(slope, 1.0)) * 0.5 + 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 get_world_wave_velocity(mat4 model_matrix) {
|
||||||
|
float velocity_length = length(wave_velocity);
|
||||||
|
if (velocity_length <= 0.0001) {
|
||||||
|
return vec2(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float flow_direction_length = length(river_flow_direction);
|
||||||
|
if (flow_direction_length > 0.0001) {
|
||||||
|
return (river_flow_direction / flow_direction_length) * velocity_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 world_direction_3d = (model_matrix * vec4(0.0, 1.0, 0.0, 0.0)).xyz;
|
||||||
|
vec2 world_direction = world_direction_3d.xz;
|
||||||
|
float world_direction_length = length(world_direction);
|
||||||
|
if (world_direction_length <= 0.0001) {
|
||||||
|
return wave_velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (world_direction / world_direction_length) * velocity_length;
|
||||||
|
}
|
||||||
|
|
||||||
void vertex(){
|
void vertex(){
|
||||||
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||||
|
world_wave_velocity = get_world_wave_velocity(MODEL_MATRIX);
|
||||||
|
|
||||||
#if USE_DISPLACEMENT
|
#if USE_DISPLACEMENT
|
||||||
float wave = sample_wave(wave_texture, world_pos.xz, wave_velocity, wave_softness).r;
|
float wave = sample_wave(wave_texture, world_pos.xz, world_wave_velocity, wave_softness).r;
|
||||||
VERTEX.y += wave*displacement_amount;
|
VERTEX.y += wave*displacement_amount;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void fragment() {
|
void fragment() {
|
||||||
float wave = sample_wave(wave_texture, world_pos.xz, wave_velocity, wave_softness).r;
|
float wave = sample_wave(wave_texture, world_pos.xz, world_wave_velocity, wave_softness).r;
|
||||||
wave = smoothstep(0.0,1.0,wave);
|
wave = smoothstep(0.0,1.0,wave);
|
||||||
|
|
||||||
vec2 screen_uv = SCREEN_UV;
|
vec2 screen_uv = SCREEN_UV;
|
||||||
@@ -141,8 +170,8 @@ void fragment() {
|
|||||||
|
|
||||||
// Caustics
|
// Caustics
|
||||||
#if USE_CAUSTICS
|
#if USE_CAUSTICS
|
||||||
vec3 caustics1 = sample_caustics(surface_uv + (TIME * -wave_velocity));
|
vec3 caustics1 = sample_caustics(surface_uv + (TIME * -world_wave_velocity));
|
||||||
vec3 caustics2 = sample_caustics((surface_uv + (caustics1.r*0.05)) + (TIME * (wave_velocity*0.5)));
|
vec3 caustics2 = sample_caustics((surface_uv + (caustics1.r*0.05)) + (TIME * (world_wave_velocity*0.5)));
|
||||||
vec3 caustics = caustics2 * (1.0 - depth);
|
vec3 caustics = caustics2 * (1.0 - depth);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -170,7 +199,7 @@ void fragment() {
|
|||||||
color = mix(color, foam_color.rgb, foam);
|
color = mix(color, foam_color.rgb, foam);
|
||||||
|
|
||||||
#if !USE_UNSHADED
|
#if !USE_UNSHADED
|
||||||
vec3 wave_normal_map = sample_wave(wave_normal_texture, world_pos.xz, wave_velocity, wave_softness).rgb;
|
vec3 wave_normal_map = sample_wave_normal(world_pos.xz, world_wave_velocity, wave);
|
||||||
NORMAL_MAP = wave_normal_map;
|
NORMAL_MAP = wave_normal_map;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user