OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / density_viewer.gd

89 lines · gd ref:
extends SceneTree
## INTERACTIVE preview of the density field's normals, on a full-window plane.
##
## The probe shaders elsewhere are painted on a 1 m cube and a 4 m quad, so they
## sample one flat spot of a 60 km world and correctly show one flat colour.
## This maps the plane's UV across a real world span instead, and lets you move
## it, so the shading can be judged before any of it reaches a map.
##
##   DISPLAY=:0 "$HYPER_TPS_GODOT" --path . --rendering-driver vulkan \
##       --script res://scenes/test/density_viewer.gd
##
##   W A S D   pan            Z / X   zoom out / in
##   Q / E     sample Y down / up
##   V         view: normal-RGB / lambert / lookdev material / hypso ramp
##   arrows    move the sun        T   1-tap analytic vs 4-tap central diffs
##   R         reset               ESC quit
var _mat: ShaderMaterial
var _origin := Vector2(0, 0)
var _span := 60000.0
var _y := 0.0
var _view := 2
var _sun_az := 0.9
var _sun_el := 0.6
var _taps := 4
var _dirty := true

func _initialize() -> void:
	var mi := MeshInstance3D.new()
	var q := QuadMesh.new(); q.size = Vector2(4, 4)
	mi.mesh = q
	mi.extra_cull_margin = 1e5
	_mat = ShaderMaterial.new()
	_mat.shader = load("res://shaders/density_probe.gdshader")
	mi.material_override = _mat
	root.add_child(mi)
	var cam := Camera3D.new(); cam.position = Vector3(0, 0, 1.9); cam.current = true
	root.add_child(cam)
	var w := root.get_window()
	if w:
		w.size = Vector2i(1280, 1280)
		w.title = "density field — normals"
	print("VIEWER: WASD pan · Z/X zoom · Q/E sample Y · N view · T taps · R reset · ESC quit")

func _process(dt: float) -> bool:
	if Input.is_key_pressed(KEY_ESCAPE):
		quit(0); return true
	var pan := _span * 0.5 * dt
	if Input.is_key_pressed(KEY_A): _origin.x -= pan; _dirty = true
	if Input.is_key_pressed(KEY_D): _origin.x += pan; _dirty = true
	if Input.is_key_pressed(KEY_W): _origin.y -= pan; _dirty = true
	if Input.is_key_pressed(KEY_S): _origin.y += pan; _dirty = true
	if Input.is_key_pressed(KEY_Z): _span *= 1.0 + dt; _dirty = true
	if Input.is_key_pressed(KEY_X): _span /= 1.0 + dt; _dirty = true
	if Input.is_key_pressed(KEY_Q): _y -= 2000.0 * dt; _dirty = true
	if Input.is_key_pressed(KEY_E): _y += 2000.0 * dt; _dirty = true
	_edge(KEY_V, "_view")
	_edge(KEY_T, "_taps")
	if Input.is_key_pressed(KEY_LEFT):  _sun_az -= 1.5 * dt; _dirty = true
	if Input.is_key_pressed(KEY_RIGHT): _sun_az += 1.5 * dt; _dirty = true
	if Input.is_key_pressed(KEY_DOWN):  _sun_el = max(0.05, _sun_el - 1.0 * dt); _dirty = true
	if Input.is_key_pressed(KEY_UP):    _sun_el = min(1.50, _sun_el + 1.0 * dt); _dirty = true
	if Input.is_key_pressed(KEY_R):
		_origin = Vector2(0, 0); _span = 60000.0; _y = 0.0
		_sun_az = 0.9; _sun_el = 0.6; _dirty = true
	if _dirty:
		_span = clamp(_span, 200.0, 200000.0)
		_mat.set_shader_parameter("probe_world_span", _span)
		_mat.set_shader_parameter("probe_world_origin", _origin)
		_mat.set_shader_parameter("probe_world_y", _y)
		_mat.set_shader_parameter("probe_view", _view)
		_mat.set_shader_parameter("probe_taps", _taps)
		_mat.set_shader_parameter("probe_sun", Vector3(
			cos(_sun_el) * cos(_sun_az), sin(_sun_el), cos(_sun_el) * sin(_sun_az)))
		var vn := ["normal-RGB", "lambert", "lookdev material", "hypso ramp"]
		print("  span %8.0f m (%5.1f m/px)  origin (%7.0f,%7.0f)  y %6.0f  sun %4.2f/%4.2f  %s  %d-tap"
			% [_span, _span / 1280.0, _origin.x, _origin.y, _y,
			   _sun_az, _sun_el, vn[_view], _taps])
		_dirty = false
	return false

var _held := {}
func _edge(key: int, which: String) -> void:
	var down: bool = Input.is_key_pressed(key)
	if down and not _held.get(key, false):
		if which == "_view": _view = (_view + 1) % 4
		else: _taps = 1 if _taps == 4 else 4
		_dirty = true
	_held[key] = down