Compare commits
3 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
0df3c05065 | 3 years ago |
|
|
c67fb43964 | 3 years ago |
|
|
3f0d6efa4b | 3 years ago |
@ -0,0 +1,35 @@ |
|||||||
|
[remap] |
||||||
|
|
||||||
|
importer="texture" |
||||||
|
type="StreamTexture" |
||||||
|
path="res://.import/map.png-9eea34967fae34f4388f4a32a16da936.stex" |
||||||
|
metadata={ |
||||||
|
"vram_texture": false |
||||||
|
} |
||||||
|
|
||||||
|
[deps] |
||||||
|
|
||||||
|
source_file="res://map.png" |
||||||
|
dest_files=[ "res://.import/map.png-9eea34967fae34f4388f4a32a16da936.stex" ] |
||||||
|
|
||||||
|
[params] |
||||||
|
|
||||||
|
compress/mode=0 |
||||||
|
compress/lossy_quality=0.7 |
||||||
|
compress/hdr_mode=0 |
||||||
|
compress/bptc_ldr=0 |
||||||
|
compress/normal_map=0 |
||||||
|
flags/repeat=0 |
||||||
|
flags/filter=true |
||||||
|
flags/mipmaps=false |
||||||
|
flags/anisotropic=false |
||||||
|
flags/srgb=2 |
||||||
|
process/fix_alpha_border=true |
||||||
|
process/premult_alpha=false |
||||||
|
process/HDR_as_SRGB=false |
||||||
|
process/invert_color=false |
||||||
|
process/normal_map_invert_y=false |
||||||
|
stream=false |
||||||
|
size_limit=0 |
||||||
|
detect_3d=true |
||||||
|
svg/scale=1.0 |
||||||
@ -1,113 +1,18 @@ |
|||||||
extends Node2D |
extends TextureRect |
||||||
|
|
||||||
signal map_clicked |
signal map_clicked |
||||||
|
|
||||||
func heightmap(): |
func _ready(): |
||||||
draw_rect(Rect2(Vector2(0, 0), Vector2(2048, 2048)), Color("#0e88bd")) |
var file_name = 'user://terrain/%s/map.png' % (Global.terrain_name) |
||||||
var coastline = PoolVector2Array() |
var image = Image.new() |
||||||
|
var err = image.load(file_name) |
||||||
for center in Global.terrain.get_centers(): |
if err != OK: |
||||||
if not center.get_data("ocean"): |
print('Image load failed : %s' % (file_name)) |
||||||
var colors = Gradient.new() |
texture = ImageTexture.new() |
||||||
colors.add_point(0.999, Color("#9e0142")) # red |
texture.create_from_image(image, Image.FORMAT_RGBA8) |
||||||
colors.add_point(0.5, Color("#dc865d")) # orange |
|
||||||
colors.add_point(0.25, Color("#fbf8b0")) # yellow |
|
||||||
colors.add_point(0.0, Color("#89cfa5")) # green |
|
||||||
colors.add_point(-0.999, Color("#5e4fa2")) # blue |
|
||||||
var color = colors.interpolate(min(center.get_elevation() + 0.001, 0.999)) |
|
||||||
var moisture = center.get_data("moisture") |
|
||||||
if moisture: |
|
||||||
color = colors.interpolate(max(min(moisture + 0.001, 0.999), 0.001)) |
|
||||||
# color = Color.green |
|
||||||
if center.get_data("ocean"): |
|
||||||
# var factor = pow((center.get_elevation()+1.001), 10) / 5.0 |
|
||||||
color = Color("#5e4fa2") |
|
||||||
# if center.get_data("snow"): |
|
||||||
# color = Color.white |
|
||||||
# if center.get_data("coast"): |
|
||||||
# color = Color.black |
|
||||||
if center.polygon().size() > 2: |
|
||||||
draw_polygon(center.polygon(), PoolColorArray([color])) |
|
||||||
|
|
||||||
if center.get_data("coast"): |
|
||||||
for border in center.borders(): |
|
||||||
if (border.end_center().get_data("ocean")): |
|
||||||
coastline.append(border.line()[0]) |
|
||||||
coastline.append(border.line()[1]) |
|
||||||
|
|
||||||
# for edge in Global.terrain.get_edges(): |
|
||||||
# if edge.get_data("coast"): |
|
||||||
|
|
||||||
# if edge.get_data("river"): |
|
||||||
# draw_line(edge.line()[0], edge.line()[1], Color.blue, 5.0) |
|
||||||
draw_multiline(coastline, Color.black) |
|
||||||
|
|
||||||
func draw_triangles_edges(color=Color("#000000")): |
|
||||||
for line in Global.terrain.get_edges_as_line(): |
|
||||||
draw_line(line[0], line[1], color) |
|
||||||
|
|
||||||
func draw_voronoi_edges(color=Color("#000000")): |
|
||||||
for line in Global.terrain.get_voronoi_edges_as_line(): |
|
||||||
draw_line(line[0], line[1], color) |
|
||||||
|
|
||||||
func draw_voronoi_cells_old(): |
|
||||||
var seen = [] |
|
||||||
for edge_idx in Global.terrain.edges(): |
|
||||||
var triangles = [] |
|
||||||
var vertices = [] |
|
||||||
var p = Global.terrain._triangles[Global.terrain.next_half_edge(edge_idx)] |
|
||||||
if not seen.has(p): |
|
||||||
seen.append(p) |
|
||||||
var edges = Global.terrain.edges_around_point(edge_idx) |
|
||||||
for edge_around_idx in edges: |
|
||||||
triangles.append(Global.terrain.triangle_of_edge(edge_around_idx)) |
|
||||||
for triangle in triangles: |
|
||||||
vertices.append(Global.terrain.triangle_center(triangle)) |
|
||||||
|
|
||||||
if triangles.size() > 2: |
|
||||||
var color = Color(randf(), randf(), randf(), 1) |
|
||||||
var voronoi_cell = PoolVector2Array() |
|
||||||
for vertice in vertices: |
|
||||||
voronoi_cell.append(Vector2(vertice.x, vertice.z)) |
|
||||||
draw_polygon(voronoi_cell, PoolColorArray([color])) |
|
||||||
func draw_voronoi_cells(): |
|
||||||
for polygon in Global.terrain.get_voronoi_cells_as_polygon(): |
|
||||||
var color = Color(randf(), randf(), randf(), 1) |
|
||||||
if polygon.size() > 2: |
|
||||||
draw_polygon(polygon, PoolColorArray([color])) |
|
||||||
|
|
||||||
func draw_voronoi_cells_convex_hull(): |
|
||||||
for point_idx in Global.terrain.points(): |
|
||||||
var triangles = [] |
|
||||||
var vertices = [] |
|
||||||
var incoming = Global.terrain._points_to_half_edges.get(point_idx) |
|
||||||
|
|
||||||
if incoming == null: |
|
||||||
triangles.append(0) |
|
||||||
else: |
|
||||||
var edges = Global.terrain.edges_around_point(incoming) |
|
||||||
for edge_idx in edges: |
|
||||||
triangles.append(Global.terrain.triangle_of_edge(edge_idx)) |
|
||||||
|
|
||||||
for triangle_idx in triangles: |
|
||||||
vertices.append(Global.terrain.triangle_center(triangle_idx)) |
|
||||||
|
|
||||||
if triangles.size() > 2: |
|
||||||
var color = Color(randf(), randf(), randf(), 1) |
|
||||||
var voronoi_cell = PoolVector2Array() |
|
||||||
for vertice in vertices: |
|
||||||
voronoi_cell.append(Vector2(vertice[0], vertice[1])) |
|
||||||
draw_polygon(voronoi_cell, PoolColorArray([color])) |
|
||||||
|
|
||||||
func _draw(): |
|
||||||
heightmap() |
|
||||||
# draw_voronoi_cells() |
|
||||||
# draw_triangles_edges() |
|
||||||
# draw_voronoi_cells_convex_hull() |
|
||||||
# draw_voronoi_edges(Color("#ff0000")) |
|
||||||
|
|
||||||
func _process(_delta): |
func _process(_delta): |
||||||
if Input.is_action_pressed("alt_command"): |
if Input.is_action_pressed("alt_command"): |
||||||
var new_position = get_viewport().get_mouse_position() / scale |
var new_position = get_viewport().get_mouse_position() |
||||||
if new_position.x <= 2000 and new_position.y <= 2000: |
if new_position.x <= 512 and new_position.y <= 512: |
||||||
emit_signal("map_clicked", new_position) |
emit_signal("map_clicked", new_position) |
||||||
|
|||||||
@ -0,0 +1,51 @@ |
|||||||
|
extends Reference |
||||||
|
|
||||||
|
# Build terrain from delaunay graph |
||||||
|
class_name Map |
||||||
|
|
||||||
|
var image |
||||||
|
var terrain |
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time. |
||||||
|
func _init(a_terrain): |
||||||
|
self.terrain = a_terrain |
||||||
|
a_terrain.set_data("map",self) |
||||||
|
|
||||||
|
func gen_map(): |
||||||
|
Global.loadings["world_creation"].new_phase("Generation de la carte...", terrain._points.size()) |
||||||
|
image = Image.new() |
||||||
|
image.create(terrain._width,terrain._height,false,Image.FORMAT_RGBA8) |
||||||
|
image.lock() |
||||||
|
image.fill(Color('#5aa6ca')) |
||||||
|
image.unlock() |
||||||
|
var file_name = "user://terrain/%s/map.png" % (terrain.get_name()) |
||||||
|
|
||||||
|
for center in terrain.get_centers(): |
||||||
|
if not center.get_data("water"): |
||||||
|
var voronoi = center.get_data("voronoi") |
||||||
|
var voronoi_bounding_box = center.get_data("voronoi_bounding_box") |
||||||
|
# print_debug("Creat voronoi image") |
||||||
|
var voronoi_image = Image.new() |
||||||
|
voronoi_image.create(int(voronoi_bounding_box.size.x), int(voronoi_bounding_box.size.y),false,Image.FORMAT_RGBA8) |
||||||
|
voronoi_image.lock() |
||||||
|
for x in int(voronoi_bounding_box.size.x): |
||||||
|
for y in int(voronoi_bounding_box.size.y): |
||||||
|
var pixel = [] |
||||||
|
pixel.append(Vector2(voronoi_bounding_box.position.x + x, voronoi_bounding_box.position.y + y)) |
||||||
|
pixel.append(Vector2(voronoi_bounding_box.position.x + x + 1, voronoi_bounding_box.position.y + y)) |
||||||
|
pixel.append(Vector2(voronoi_bounding_box.position.x + x + 1, voronoi_bounding_box.position.y + y + 1)) |
||||||
|
pixel.append(Vector2(voronoi_bounding_box.position.x + x, voronoi_bounding_box.position.y + y + 1)) |
||||||
|
var alpha = Global.pixel_area(voronoi, pixel) |
||||||
|
# print_debug("Alpha : %f" % (alpha)) |
||||||
|
var color |
||||||
|
if center.get_data("coast"): |
||||||
|
color = Color(0.708, 0.646, 0.138, alpha) |
||||||
|
else: |
||||||
|
color = Color(0.253, 0.621, 0.229, alpha) |
||||||
|
voronoi_image.set_pixel(x,y,color) |
||||||
|
image.lock() |
||||||
|
image.blend_rect(voronoi_image,Rect2(0.0,0.0,voronoi_bounding_box.size.x,voronoi_bounding_box.size.y),voronoi_bounding_box.position) |
||||||
|
image.unlock() |
||||||
|
voronoi_image.unlock() |
||||||
|
Global.loadings["world_creation"].increment_step() |
||||||
|
image.save_png(file_name) |
||||||
@ -1,113 +0,0 @@ |
|||||||
extends Spatial |
|
||||||
class_name Chunk |
|
||||||
|
|
||||||
var noise |
|
||||||
var should_remove = true |
|
||||||
var x |
|
||||||
var z |
|
||||||
var empty = true |
|
||||||
|
|
||||||
func _init(x, z): |
|
||||||
self.x = x |
|
||||||
self.z = z |
|
||||||
|
|
||||||
func _ready(): |
|
||||||
# generate_chunk() |
|
||||||
generate_grass() |
|
||||||
pass |
|
||||||
|
|
||||||
func generate_grass(): |
|
||||||
var poisson_disc_sampling: PoissonDiscSampling = PoissonDiscSampling.new() |
|
||||||
var rng := RandomNumberGenerator.new() |
|
||||||
rng.randomize() |
|
||||||
var coords = [] |
|
||||||
for center in Global.terrain.get_chunk(Vector2(x, z)): |
|
||||||
if ( |
|
||||||
not center.get_data("mountain") |
|
||||||
and not center.get_data("water") |
|
||||||
and not center.get_data("coast") |
|
||||||
): |
|
||||||
var points = poisson_disc_sampling.generate_points(0.1, center.polygon(), 2) |
|
||||||
var points3d = [] |
|
||||||
for point in points: |
|
||||||
points3d.append(Vector3(point.x, center.get_elevation() * 120, point.y)) |
|
||||||
coords += points3d |
|
||||||
# var multimesh = MultiMesh.new() |
|
||||||
var multimesh = MultiMesh.new() |
|
||||||
multimesh.mesh = load("res://world/grass.obj") |
|
||||||
multimesh.mesh.surface_set_material(0, load("res://world/materials/wind_grass.tres")) |
|
||||||
multimesh.transform_format = MultiMesh.TRANSFORM_3D |
|
||||||
multimesh.instance_count = coords.size() |
|
||||||
for instance_index in multimesh.instance_count: |
|
||||||
|
|
||||||
var transform := Transform().rotated(Vector3.UP, rng.randf_range(-PI / 2, PI / 2)) |
|
||||||
transform.origin = Vector3(coords[instance_index].x, coords[instance_index].y, coords[instance_index].z) |
|
||||||
# transform.scaled(Vector3()) |
|
||||||
|
|
||||||
multimesh.set_instance_transform(instance_index, transform) |
|
||||||
var multimesh_instance = MultiMeshInstance.new() |
|
||||||
multimesh_instance.multimesh = multimesh |
|
||||||
add_child(multimesh_instance) |
|
||||||
pass |
|
||||||
|
|
||||||
func generate_chunk(): |
|
||||||
var file = File.new() |
|
||||||
file.open("res://world/materials/materials.json", File.READ) |
|
||||||
var materials = JSON.parse(file.get_as_text()).result |
|
||||||
|
|
||||||
var st = SurfaceTool.new() |
|
||||||
|
|
||||||
st.begin(Mesh.PRIMITIVE_TRIANGLES) |
|
||||||
var factor = Vector3(1, 120, 1) |
|
||||||
# print(x) |
|
||||||
# print(z) |
|
||||||
for center in Global.terrain.get_chunk(Vector2(x, z)): |
|
||||||
# print(center.get_data("water")) |
|
||||||
if not center.get_data("water"): |
|
||||||
empty = false |
|
||||||
# print(center.get_data("material")) |
|
||||||
var material_id = materials[center.get_data("material")] |
|
||||||
var top_uv = Vector2(0, float(material_id) / (materials.size()-1)) |
|
||||||
var border_uv = Vector2(1, float(material_id) / (materials.size()-1)) |
|
||||||
|
|
||||||
for edge in center.borders(): |
|
||||||
if edge.end_center().get_elevation() < edge.start_center().get_elevation(): |
|
||||||
var top = edge.start_center().get_elevation() |
|
||||||
# if edge.start_center().get_data("ocean"): |
|
||||||
# top = -1.0 |
|
||||||
var bottom = edge.end_center().get_elevation() |
|
||||||
if edge.end_center().get_data("ocean"): |
|
||||||
bottom = 0.0 |
|
||||||
st.add_uv(border_uv) |
|
||||||
st.add_vertex(Vector3(edge.start_corner().point3d().x, bottom, edge.start_corner().point3d().z) * factor) |
|
||||||
st.add_vertex(Vector3(edge.end_corner().point3d().x, top, edge.end_corner().point3d().z) * factor) |
|
||||||
st.add_vertex(Vector3(edge.start_corner().point3d().x, top, edge.start_corner().point3d().z) * factor) |
|
||||||
|
|
||||||
st.add_vertex(Vector3(edge.start_corner().point3d().x, bottom, edge.start_corner().point3d().z) * factor) |
|
||||||
st.add_vertex(Vector3(edge.end_corner().point3d().x, bottom, edge.end_corner().point3d().z) * factor) |
|
||||||
st.add_vertex(Vector3(edge.end_corner().point3d().x, top, edge.end_corner().point3d().z) * factor) |
|
||||||
|
|
||||||
for corner_count in center.corners().size(): |
|
||||||
var current_corner = center.corners()[corner_count] |
|
||||||
var next_corner |
|
||||||
if corner_count < center.corners().size() - 1: |
|
||||||
next_corner = center.corners()[corner_count+1] |
|
||||||
else: |
|
||||||
next_corner = center.corners()[0] |
|
||||||
|
|
||||||
st.add_uv(Vector2(top_uv)) |
|
||||||
st.add_vertex(Vector3(current_corner.point2d().x, center.get_elevation(), current_corner.point2d().y) * factor) |
|
||||||
st.add_vertex(Vector3(next_corner.point2d().x, center.get_elevation(), next_corner.point2d().y) * factor) |
|
||||||
st.add_vertex(Vector3(center.point2d().x, center.get_elevation(), center.point2d().y) * factor) |
|
||||||
|
|
||||||
if not empty: |
|
||||||
st.generate_normals() |
|
||||||
st.index() |
|
||||||
|
|
||||||
var mi = MeshInstance.new() |
|
||||||
mi.mesh = st.commit() |
|
||||||
var material = load("res://world/materials/world.material") |
|
||||||
mi.set_surface_material(0, material) |
|
||||||
mi.create_trimesh_collision() |
|
||||||
mi.cast_shadow = GeometryInstance.SHADOW_CASTING_SETTING_ON |
|
||||||
add_child(mi) |
|
||||||
Binary file not shown.
@ -1,29 +0,0 @@ |
|||||||
extends MultiMeshInstance |
|
||||||
|
|
||||||
var extents = Vector2(10, 10) |
|
||||||
|
|
||||||
func _ready(): |
|
||||||
return |
|
||||||
var poisson_disc_sampling: PoissonDiscSampling = PoissonDiscSampling.new() |
|
||||||
var rng := RandomNumberGenerator.new() |
|
||||||
rng.randomize() |
|
||||||
var coords = [] |
|
||||||
for center in Global.terrain.get_centers(): |
|
||||||
if ( |
|
||||||
not center.get_data("mountain") |
|
||||||
and not center.get_data("water") |
|
||||||
and not center.get_data("coast") |
|
||||||
): |
|
||||||
var points = poisson_disc_sampling.generate_points(2, center.polygon(), 2) |
|
||||||
var points3d = [] |
|
||||||
for point in points: |
|
||||||
points3d.append(Vector3(point.x, center.get_elevation() * 120, point.y)) |
|
||||||
coords += points3d |
|
||||||
multimesh.instance_count = coords.size() |
|
||||||
for instance_index in multimesh.instance_count: |
|
||||||
|
|
||||||
var transform := Transform().rotated(Vector3.UP, rng.randf_range(-PI / 2, PI / 2)) |
|
||||||
transform.origin = Vector3(coords[instance_index].x, coords[instance_index].y, coords[instance_index].z) |
|
||||||
# transform.scaled(Vector3()) |
|
||||||
|
|
||||||
multimesh.set_instance_transform(instance_index, transform) |
|
||||||
File diff suppressed because one or more lines are too long
@ -1,12 +0,0 @@ |
|||||||
# Blender MTL File: 'None' |
|
||||||
# Material Count: 1 |
|
||||||
|
|
||||||
newmtl Default_OBJ |
|
||||||
Ns 250.000000 |
|
||||||
Ka 1.000000 1.000000 1.000000 |
|
||||||
Kd 0.800000 0.800000 0.800000 |
|
||||||
Ks 0.500000 0.500000 0.500000 |
|
||||||
Ke 0.000000 0.000000 0.000000 |
|
||||||
Ni 1.450000 |
|
||||||
d 1.000000 |
|
||||||
illum 2 |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
# Blender v3.2.2 OBJ File: '' |
|
||||||
# www.blender.org |
|
||||||
mtllib grass.mtl |
|
||||||
o grass_triangle |
|
||||||
v 0.012754 0.302056 0.000000 |
|
||||||
v 0.000000 0.402742 0.000000 |
|
||||||
v -0.012754 0.302056 0.000000 |
|
||||||
v 0.025508 0.201371 0.000000 |
|
||||||
v -0.038262 0.100685 0.000000 |
|
||||||
v 0.038262 0.100685 0.000000 |
|
||||||
v -0.051016 0.000000 0.000000 |
|
||||||
v 0.051016 0.000000 0.000000 |
|
||||||
v -0.025508 0.201371 0.000000 |
|
||||||
vt 0.621057 0.520384 |
|
||||||
vt 0.497980 0.979655 |
|
||||||
vt 0.376628 0.520384 |
|
||||||
vt 0.744133 0.238847 |
|
||||||
vt 0.133923 0.098911 |
|
||||||
vt 0.867209 0.098911 |
|
||||||
vt 0.012570 0.013663 |
|
||||||
vt 0.990286 0.013663 |
|
||||||
vt 0.255275 0.238847 |
|
||||||
vn 0.0000 -0.0000 1.0000 |
|
||||||
usemtl Default_OBJ |
|
||||||
s 1 |
|
||||||
f 1/1/1 2/2/1 3/3/1 |
|
||||||
f 4/4/1 5/5/1 6/6/1 |
|
||||||
f 6/6/1 7/7/1 8/8/1 |
|
||||||
f 1/1/1 9/9/1 4/4/1 |
|
||||||
f 4/4/1 9/9/1 5/5/1 |
|
||||||
f 6/6/1 5/5/1 7/7/1 |
|
||||||
f 1/1/1 3/3/1 9/9/1 |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
[remap] |
|
||||||
|
|
||||||
importer="wavefront_obj" |
|
||||||
type="Mesh" |
|
||||||
path="res://.import/grass.obj-b367f86df935fca9f4b72c7070d3608f.mesh" |
|
||||||
|
|
||||||
[deps] |
|
||||||
|
|
||||||
files=[ "res://.import/grass.obj-b367f86df935fca9f4b72c7070d3608f.mesh" ] |
|
||||||
|
|
||||||
source_file="res://world/grass.obj" |
|
||||||
dest_files=[ "res://.import/grass.obj-b367f86df935fca9f4b72c7070d3608f.mesh", "res://.import/grass.obj-b367f86df935fca9f4b72c7070d3608f.mesh" ] |
|
||||||
|
|
||||||
[params] |
|
||||||
|
|
||||||
generate_tangents=true |
|
||||||
scale_mesh=Vector3( 1, 1, 1 ) |
|
||||||
offset_mesh=Vector3( 0, 0, 0 ) |
|
||||||
octahedral_compression=true |
|
||||||
optimize_mesh_flags=4286 |
|
||||||
@ -1,29 +0,0 @@ |
|||||||
# Blender v2.83.0 OBJ File: '' |
|
||||||
# www.blender.org |
|
||||||
v -0.255078 0.000000 0.000000 |
|
||||||
v 0.255078 0.000000 0.000000 |
|
||||||
v 0.000000 2.013708 0.000000 |
|
||||||
v -0.127539 1.006854 0.000000 |
|
||||||
v 0.127539 1.006854 0.000000 |
|
||||||
v -0.191308 0.503427 0.000000 |
|
||||||
v 0.063769 1.510281 0.000000 |
|
||||||
v -0.063769 1.510281 0.000000 |
|
||||||
v 0.191308 0.503427 0.000000 |
|
||||||
vt 0.621057 0.520384 |
|
||||||
vt 0.497980 0.979655 |
|
||||||
vt 0.376628 0.520384 |
|
||||||
vt 0.744133 0.238847 |
|
||||||
vt 0.133923 0.098911 |
|
||||||
vt 0.867209 0.098911 |
|
||||||
vt 0.012570 0.013663 |
|
||||||
vt 0.990286 0.013663 |
|
||||||
vt 0.255275 0.238847 |
|
||||||
vn 0.0000 0.0000 1.0000 |
|
||||||
s 1 |
|
||||||
f 7/1/1 3/2/1 8/3/1 |
|
||||||
f 5/4/1 6/5/1 9/6/1 |
|
||||||
f 9/6/1 1/7/1 2/8/1 |
|
||||||
f 7/1/1 4/9/1 5/4/1 |
|
||||||
f 5/4/1 4/9/1 6/5/1 |
|
||||||
f 9/6/1 6/5/1 1/7/1 |
|
||||||
f 7/1/1 8/3/1 4/9/1 |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
[remap] |
|
||||||
|
|
||||||
importer="wavefront_obj" |
|
||||||
type="Mesh" |
|
||||||
path="res://.import/grass_triangle.obj-46b3ab3674e3d39ea8727b7c5a77c4a9.mesh" |
|
||||||
|
|
||||||
[deps] |
|
||||||
|
|
||||||
files=[ "res://.import/grass_triangle.obj-46b3ab3674e3d39ea8727b7c5a77c4a9.mesh" ] |
|
||||||
|
|
||||||
source_file="res://world/grass_triangle.obj" |
|
||||||
dest_files=[ "res://.import/grass_triangle.obj-46b3ab3674e3d39ea8727b7c5a77c4a9.mesh", "res://.import/grass_triangle.obj-46b3ab3674e3d39ea8727b7c5a77c4a9.mesh" ] |
|
||||||
|
|
||||||
[params] |
|
||||||
|
|
||||||
generate_tangents=true |
|
||||||
scale_mesh=Vector3( 1, 1, 1 ) |
|
||||||
offset_mesh=Vector3( 0, 0, 0 ) |
|
||||||
octahedral_compression=true |
|
||||||
optimize_mesh_flags=4286 |
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.7 KiB |
@ -1,77 +0,0 @@ |
|||||||
shader_type spatial; |
|
||||||
render_mode cull_disabled, unshaded; |
|
||||||
|
|
||||||
uniform float wind_speed = 0.2; |
|
||||||
uniform float wind_strength = 2.0; |
|
||||||
// How big, in world space, is the noise texture |
|
||||||
// wind will tile every wind_texture_tile_size |
|
||||||
uniform float wind_texture_tile_size = 20.0; |
|
||||||
uniform float wind_vertical_strength = 0.3; |
|
||||||
uniform vec2 wind_horizontal_direction = vec2(1.0, 0.5); |
|
||||||
|
|
||||||
uniform sampler2D color_ramp : hint_black_albedo; |
|
||||||
// we need a tiling noise here! |
|
||||||
uniform sampler2D wind_noise : hint_black; |
|
||||||
|
|
||||||
uniform vec3 character_position; |
|
||||||
uniform float character_radius = 3.0; |
|
||||||
uniform sampler2D character_distance_falloff_curve : hint_black_albedo; |
|
||||||
uniform float character_push_strength = 1.0; |
|
||||||
|
|
||||||
varying float debug_wind; |
|
||||||
|
|
||||||
void vertex() { |
|
||||||
vec3 world_vert = (WORLD_MATRIX * vec4(VERTEX, 1.0)).xyz; |
|
||||||
|
|
||||||
vec2 normalized_wind_direction = normalize(wind_horizontal_direction); |
|
||||||
vec2 world_uv = world_vert.xz / wind_texture_tile_size + normalized_wind_direction * TIME * wind_speed; |
|
||||||
// we displace only the top part of the mesh |
|
||||||
// note that this means that the mesh needs to have UV in a way that the bottom of UV space |
|
||||||
// is at the top of the mesh |
|
||||||
float displacement_affect = (1.0 - UV.y); |
|
||||||
float wind_noise_intensity = (textureLod(wind_noise, world_uv, 0.0).r - 0.5); |
|
||||||
|
|
||||||
// We convert the direction of the wind into vertex space from world space |
|
||||||
// if we used it directly in vertex space, rotated blades of grass wouldn't behave properly |
|
||||||
vec2 vert_space_horizontal_dir = |
|
||||||
(inverse(WORLD_MATRIX) * vec4(wind_horizontal_direction, 0.0, 0.0)).xy; |
|
||||||
|
|
||||||
vert_space_horizontal_dir = normalize(vert_space_horizontal_dir); |
|
||||||
|
|
||||||
vec3 bump_wind = vec3( |
|
||||||
wind_noise_intensity * vert_space_horizontal_dir.x, |
|
||||||
1.0 - wind_noise_intensity, |
|
||||||
wind_noise_intensity * vert_space_horizontal_dir.y); |
|
||||||
|
|
||||||
normalize(bump_wind); |
|
||||||
|
|
||||||
bump_wind *= vec3(wind_strength, wind_vertical_strength, wind_strength); |
|
||||||
|
|
||||||
VERTEX += bump_wind * displacement_affect; |
|
||||||
|
|
||||||
// At the moment the blades are pushed away in a perfectly circular manner. |
|
||||||
// We could distort the distance to the character based on a noise, to break a bit the |
|
||||||
// circular shape. We could distort the falloff by sampling in a noise based on the xz coordinates. |
|
||||||
// The task is left to the reader |
|
||||||
|
|
||||||
vec3 dir_to_character = character_position - WORLD_MATRIX[3].xyz; |
|
||||||
// uncomment the following line to have a horizontal only character push |
|
||||||
//dir_to_character.y = 0.0; |
|
||||||
float distance_to_character = length(dir_to_character); |
|
||||||
float falloff = 1.0 - smoothstep(0.0, 1.0, distance_to_character/character_radius); |
|
||||||
// Because we operate in vertex space, we need to convert the direction to the character |
|
||||||
// in vertex space. Otherwise, it wouldn't work for rotated blades of grass. |
|
||||||
// comment the next line to observe how the blades are not all facing away from the character. |
|
||||||
dir_to_character = (inverse(WORLD_MATRIX) * vec4(dir_to_character, 0.0)).xyz; |
|
||||||
dir_to_character = normalize(dir_to_character); |
|
||||||
|
|
||||||
// sample the curve based on how far we are from the character, in normalized coordinates |
|
||||||
float falloff_curve = texture(character_distance_falloff_curve, vec2(falloff)).x; |
|
||||||
// direction to character is inverted because we want to point away from it |
|
||||||
VERTEX += normalize(-dir_to_character) * falloff_curve * character_push_strength * displacement_affect; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
void fragment() { |
|
||||||
ALBEDO = texture(color_ramp, vec2(1.0 - UV.y, 0)).rgb ; |
|
||||||
} |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
[gd_resource type="ShaderMaterial" load_steps=8 format=2] |
|
||||||
|
|
||||||
[ext_resource path="res://world/materials/wind_grass.shader" type="Shader" id=1] |
|
||||||
|
|
||||||
[sub_resource type="Curve" id=1] |
|
||||||
_data = [ Vector2( 0, 0 ), 0.0, 2.71765, 0, 0, Vector2( 1, 1 ), -0.129412, 0.0, 0, 0 ] |
|
||||||
|
|
||||||
[sub_resource type="CurveTexture" id=2] |
|
||||||
width = 128 |
|
||||||
curve = SubResource( 1 ) |
|
||||||
|
|
||||||
[sub_resource type="Gradient" id=3] |
|
||||||
offsets = PoolRealArray( 0, 0.486339, 0.966102 ) |
|
||||||
colors = PoolColorArray( 0.054902, 0.556863, 0.439216, 1, 0.321569, 0.886275, 0.341176, 1, 0.498039, 0.921569, 0.356863, 1 ) |
|
||||||
|
|
||||||
[sub_resource type="GradientTexture" id=4] |
|
||||||
gradient = SubResource( 3 ) |
|
||||||
|
|
||||||
[sub_resource type="OpenSimplexNoise" id=5] |
|
||||||
period = 109.1 |
|
||||||
persistence = 0.138 |
|
||||||
lacunarity = 0.44 |
|
||||||
|
|
||||||
[sub_resource type="NoiseTexture" id=6] |
|
||||||
seamless = true |
|
||||||
noise = SubResource( 5 ) |
|
||||||
|
|
||||||
[resource] |
|
||||||
shader = ExtResource( 1 ) |
|
||||||
shader_param/wind_speed = 0.2 |
|
||||||
shader_param/wind_strength = 2.0 |
|
||||||
shader_param/wind_texture_tile_size = 20.0 |
|
||||||
shader_param/wind_vertical_strength = 0.3 |
|
||||||
shader_param/wind_horizontal_direction = Vector2( 1, 0.5 ) |
|
||||||
shader_param/character_position = Vector3( 0, 1.22062, 0 ) |
|
||||||
shader_param/character_radius = 3.0 |
|
||||||
shader_param/character_push_strength = 1.0 |
|
||||||
shader_param/color_ramp = SubResource( 4 ) |
|
||||||
shader_param/wind_noise = SubResource( 6 ) |
|
||||||
shader_param/character_distance_falloff_curve = SubResource( 2 ) |
|
||||||
Loading…
Reference in new issue