#!/usr/bin/env python3
"""Generate shaders/terrain_noise.gdshaderinc from proc-nodes' erosion_filter.inc.
THE MATERIAL CANNOT CALL THE DENSITY FUNCTION. The terrain's density GLSL runs
in a compute pipeline on dc-terrain's own RenderingDevice; dc_erosion_color is
a Godot spatial shader on the main device. There is no runtime path between
them. So for the material to shade using the SAME field the terrain is built
from, the field's text has to reach it as source.
GENERATED, NOT COPIED BY HAND, for the reason the whole .inc discipline exists:
a hand-synced copy is a copy, and copies of these functions are what shipped a
60x divergence between the meshed surface and the collidable one. If this file
is stale the shader is stale; there is no path where the material and the
density silently disagree.
erosion_filter.inc is ALREADY compiled three ways -- GLSL 450, C++ (through
erosion_cpp_shim.h) and a Godot fog shader (see its PN_TAU note, which exists
because Godot reserves TAU). A spatial shader is the fourth consumer, not a
new risk.
python3 tools/gen_terrain_noise_shaderinc.py
"""
import os, sys
SRC = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..",
"proc-nodes", "src", "shared", "erosion_filter.inc")
DST = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..",
"shaders", "terrain_noise.gdshaderinc")
def main():
src = os.path.normpath(SRC)
if not os.path.exists(src):
sys.exit("erosion_filter.inc not found at %s" % src)
text = open(src, encoding="utf-8").read()
header = (
"// GENERATED by tools/gen_terrain_noise_shaderinc.py — DO NOT EDIT.\n"
"// Source: proc-nodes/src/shared/erosion_filter.inc\n"
"//\n"
"// The SAME text the density shader compiles. Included here so the\n"
"// terrain MATERIAL can evaluate the same field per-fragment and\n"
"// recover the surface normal the geometry is too coarse to carry.\n"
"// Re-run the generator after editing the .inc.\n\n")
out = os.path.normpath(DST)
open(out, "w", encoding="utf-8").write(header + text)
print("wrote %s (%d bytes)" % (out, len(header) + len(text)))
if __name__ == "__main__":
main()