ile-de-test/addons/waterways/system_map_renderer.gd
2024-01-26 21:00:32 +01:00

150 lines
5.8 KiB
GDScript

# Copyright © 2023 Kasper Arnklit Frandsen - MIT License
# See `LICENSE.md` included in the source distribution for details.
@tool
extends SubViewport
const HEIGHT_SHADER_PATH = "res://addons/waterways/shaders/system_renders/system_height.gdshader"
const FLOW_SHADER_PATH = "res://addons/waterways/shaders/system_renders/system_flow.gdshader"
const ALPHA_SHADER_PATH = "res://addons/waterways/shaders/system_renders/alpha.gdshader"
const RiverManager = preload("./river_manager.gd")
var _camera: Camera3D
var _container: Node3D
func grab_height(water_objects: Array[RiverManager], aabb : AABB, resolution : float) -> ImageTexture:
size = Vector2(resolution, resolution)
_camera = $Camera3D as Camera3D
_container = $Container as Node3D
var height_mat := ShaderMaterial.new()
var height_shader := load(HEIGHT_SHADER_PATH) as Shader
height_mat.shader = height_shader
height_mat.set_shader_parameter("lower_bounds", aabb.position.y)
height_mat.set_shader_parameter("upper_bounds", aabb.end.y)
for object in water_objects:
var water_mesh_copy := object.mesh_instance.duplicate(true)
_container.add_child(water_mesh_copy)
water_mesh_copy.transform = object.transform # TODO - This seems unneeded?
water_mesh_copy.material_override = height_mat
var longest_axis := aabb.get_longest_axis_index()
match longest_axis:
Vector3.AXIS_X:
_camera.position = aabb.position + Vector3(aabb.size.x / 2.0, aabb.size.y + 1.0, aabb.size.x / 2.0)
Vector3.AXIS_Y:
# TODO
# This shouldn't happen, we might need some code to handle if it does
pass
Vector3.AXIS_Z:
_camera.position = aabb.position + Vector3(aabb.size.z / 2.0, aabb.size.y + 1.0, aabb.size.z / 2.0)
_camera.size = aabb.get_longest_axis_size()
_camera.far = aabb.size.y + 2.0
render_target_clear_mode = CLEAR_MODE_ALWAYS
render_target_update_mode = SubViewport.UPDATE_ONCE
await get_tree().process_frame
await get_tree().process_frame
var height : Image = get_texture().get_image()
var height_result := ImageTexture.create_from_image(height)
for child in _container.get_children():
_container.remove_child(child)
return height_result
func grab_alpha(water_objects: Array[RiverManager], aabb: AABB, resolution: float) -> ImageTexture:
size = Vector2(resolution, resolution)
_camera = $Camera3D as Camera3D
_container = $Container as Node3D
var alpha_mat := ShaderMaterial.new()
var alpha_shader := load(ALPHA_SHADER_PATH) as Shader
alpha_mat.shader = alpha_shader
for object in water_objects:
var water_mesh_copy = object.mesh_instance.duplicate(true)
_container.add_child(water_mesh_copy)
water_mesh_copy.transform = object.transform
water_mesh_copy.material_override = alpha_mat
var longest_axis := aabb.get_longest_axis_index()
match longest_axis:
Vector3.AXIS_X:
_camera.position = aabb.position + Vector3(aabb.size.x / 2.0, aabb.size.y + 1.0, aabb.size.x / 2.0)
Vector3.AXIS_Y:
# This shouldn't happen, we might need some code to handle if it does
pass
Vector3.AXIS_Z:
_camera.position = aabb.position + Vector3(aabb.size.z / 2.0, aabb.size.y + 1.0, aabb.size.z / 2.0)
_camera.size = aabb.get_longest_axis_size()
_camera.far = aabb.size.y + 2.0
render_target_clear_mode = CLEAR_MODE_ALWAYS
render_target_update_mode = SubViewport.UPDATE_ONCE
await get_tree().process_frame
await get_tree().process_frame
var alpha : Image = get_texture().get_image()
var alpha_result := ImageTexture.create_from_image(alpha)
for child in _container.get_children():
_container.remove_child(child)
return alpha_result
func grab_flow(water_objects: Array[RiverManager], aabb : AABB, resolution : float) -> ImageTexture:
size = Vector2(resolution, resolution)
_camera = $Camera3D as Camera3D
_container = $Container as Node3D
for i in water_objects.size():
var flow_mat := ShaderMaterial.new()
var flow_shader := load(FLOW_SHADER_PATH) as Shader
flow_mat.shader = flow_shader
flow_mat.set_shader_parameter("flowmap", water_objects[i].flow_foam_noise)
flow_mat.set_shader_parameter("distmap", water_objects[i].dist_pressure)
flow_mat.set_shader_parameter("flow_base", water_objects[i].get_shader_parameter("flow_base"))
flow_mat.set_shader_parameter("flow_steepness", water_objects[i].get_shader_parameter("flow_steepness"))
flow_mat.set_shader_parameter("flow_distance", water_objects[i].get_shader_parameter("flow_distance"))
flow_mat.set_shader_parameter("flow_pressure", water_objects[i].get_shader_parameter("flow_pressure"))
flow_mat.set_shader_parameter("flow_max", water_objects[i].get_shader_parameter("flow_max"))
flow_mat.set_shader_parameter("valid_flowmap", water_objects[i].get_shader_parameter("i_valid_flowmap"))
flow_mat.set_shader_parameter("uv2_sides", water_objects[i].get_shader_parameter("i_uv2_sides"))
var water_mesh_copy := water_objects[i].mesh_instance.duplicate(true)
_container.add_child(water_mesh_copy)
water_mesh_copy.transform = water_objects[i].transform
water_mesh_copy.material_override = flow_mat
var longest_axis := aabb.get_longest_axis_index()
match longest_axis:
Vector3.AXIS_X:
_camera.position = aabb.position + Vector3(aabb.size.x / 2.0, aabb.size.y + 1.0, aabb.size.x / 2.0)
Vector3.AXIS_Y:
# This shouldn't happen, we might need some code to handle if it does - TODO
pass
Vector3.AXIS_Z:
_camera.position = aabb.position + Vector3(aabb.size.z / 2.0, aabb.size.y + 1.0, aabb.size.z / 2.0)
_camera.size = aabb.get_longest_axis_size()
_camera.far = aabb.size.y + 2.0
render_target_clear_mode = CLEAR_MODE_ALWAYS
render_target_update_mode = SubViewport.UPDATE_ONCE
await get_tree().process_frame
await get_tree().process_frame
var flow : Image = get_texture().get_image()
var flow_result := ImageTexture.create_from_image(flow)
for child in _container.get_children():
_container.remove_child(child)
return flow_result