| … | … | @@ -21,6 +21,9 @@ |
| 21 | 21 | namespace godot { |
| 22 | 22 | |
| 23 | 23 | void DCTerrainGeneratorProcNodes::_bind_methods() { |
| 24 | ClassDB::bind_method(D_METHOD("set_erosion_minimal", "value"), &DCTerrainGeneratorProcNodes::set_erosion_minimal); |
| 25 | ClassDB::bind_method(D_METHOD("get_erosion_minimal"), &DCTerrainGeneratorProcNodes::get_erosion_minimal); |
| 26 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "erosion_minimal"), "set_erosion_minimal", "get_erosion_minimal"); |
| 24 | 27 | ClassDB::bind_method(D_METHOD("set_erosion_enabled", "value"), &DCTerrainGeneratorProcNodes::set_erosion_enabled); |
| 25 | 28 | ClassDB::bind_method(D_METHOD("get_erosion_enabled"), &DCTerrainGeneratorProcNodes::get_erosion_enabled); |
| 26 | 29 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "erosion_enabled"), "set_erosion_enabled", "get_erosion_enabled"); |
| … | … | @@ -383,6 +386,13 @@ void DCTerrainGeneratorProcNodes::set_lookdev_wrapper(bool p_val) { |
| 383 | 386 | emit_changed(); |
| 384 | 387 | } |
| 385 | 388 | |
| 389 | void DCTerrainGeneratorProcNodes::set_erosion_minimal(bool p_val) { |
| 390 | if (erosion_minimal_ == p_val) return; |
| 391 | erosion_minimal_ = p_val; |
| 392 | _recompile_glsl(); |
| 393 | emit_changed(); |
| 394 | } |
| 395 | |
| 386 | 396 | void DCTerrainGeneratorProcNodes::set_erosion_enabled(bool p_val) { |
| 387 | 397 | if (erosion_enabled_ == p_val) return; |
| 388 | 398 | erosion_enabled_ = p_val; |
| … | … | @@ -914,6 +924,75 @@ void DCTerrainGeneratorProcNodes::_recompile_glsl() { |
| 914 | 924 | // undeclared and the shader does not compile, which the map experiences as |
| 915 | 925 | // a silent fallback. So the wrapper's noise layers are emitted only when |
| 916 | 926 | // there is a library to support them. |
| 927 | // ── EROSION-MINIMAL WRAPPER ──────────────────────────────────────────── |
| 928 | // |
| 929 | // The heightmap is the terrain and the filter is the enhancement, so this |
| 930 | // emits exactly those two and the mapping between them: |
| 931 | // |
| 932 | // proc_density = Heightfield -> Erosion (the graph, unchanged) |
| 933 | // evaluate_density = y-map, call, rescale, clip |
| 934 | // |
| 935 | // No mountain, no relief, no detail, no det_offset. Compare with the |
| 936 | // general path below, which carries all three because it was written when |
| 937 | // the mountain was the terrain -- on this map they contribute nothing but |
| 938 | // branches, and a branch that can be mis-gated is how the filter's own |
| 939 | // parameters went unset for weeks (hyper-games #53 section 2). |
| 940 | // |
| 941 | // The erosion knobs are still emitted, and still gated on the noise library |
| 942 | // that DECLARES them: with erosion_enabled false there is no library, and |
| 943 | // assigning pn_ero_* would name identifiers that do not exist. |
| 944 | if (erosion_minimal_) { |
| 945 | const bool lib = proc_glsl.find("fractal_noise_2d_lod") != -1; |
| 946 | String mm = |
| 947 | "// EROSION-MINIMAL: heightfield + erosion filter, and nothing else.\n" |
| 948 | "int pn_max_octaves;\n\n" |
| 949 | + proc_glsl + "\n" |
| 950 | + hblk_glsl + |
| 951 | "float evaluate_density(float x, float y, float z) {\n" |
| 952 | " float inv_scale = 1.0 / " + th_str + ";\n" |
| 953 | " pn_max_octaves = 99;\n" |
| 954 | + (lib ? String( |
| 955 | " pn_fade_div = 4.8;\n" |
| 956 | " pn_erosion_scale = " + String::num(erosion_scale_, 6) + ";\n" |
| 957 | " pn_ero_input_height_amplitude = " + String::num(input_height_amplitude_, 9) + ";\n" |
| 958 | " pn_ero_octave_lacunarity = " + String::num(octave_lacunarity_, 9) + ";\n" |
| 959 | " pn_ero_gully_depth = " + String::num(gully_depth_, 9) + ";\n" |
| 960 | " pn_ero_fine_gully_slope_restriction = " + String::num(fine_gully_slope_restriction_, 9) + ";\n" |
| 961 | " pn_ero_gully_normalize_threshold = " + String::num(gully_normalize_threshold_, 9) + ";\n" |
| 962 | " pn_ero_height_offset = " + String::num(height_offset_, 9) + ";\n" |
| 963 | " pn_ero_height_offset_follows_altitude = " + String::num(height_offset_follows_altitude_, 9) + ";\n" |
| 964 | " pn_ero_crease_rounding = " + String::num(crease_rounding_, 9) + ";\n" |
| 965 | " pn_ero_ridge_rounding = " + String::num(ridge_rounding_, 9) + ";\n" |
| 966 | " pn_ero_input_feature_rounding = " + String::num(input_feature_rounding_, 9) + ";\n" |
| 967 | " pn_ero_rounding_per_octave = " + String::num(rounding_per_octave_, 9) + ";\n" |
| 968 | " pn_ero_gully_onset_slope = " + String::num(gully_onset_slope_, 9) + ";\n" |
| 969 | " pn_ero_octave_onset_slope = " + String::num(octave_onset_slope_, 9) + ";\n" |
| 970 | " pn_ero_ridge_onset_slope = " + String::num(ridge_onset_slope_, 9) + ";\n" |
| 971 | " pn_ero_ridge_octave_onset = " + String::num(ridge_octave_onset_, 9) + ";\n" |
| 972 | " pn_ero_assumed_slope = " + String::num(assumed_slope_, 9) + ";\n" |
| 973 | " pn_ero_assumed_slope_mix = " + String::num(assumed_slope_mix_, 9) + ";\n" |
| 974 | // The coarsest gully spans terrain_height * gully_band_scale * |
| 975 | // cell_size in world metres and halves per octave; nyquist_octaves |
| 976 | // of that against this chunk's voxel is how many octaves it can |
| 977 | // actually resolve. |
| 978 | " pn_ero_max_octaves = nyquist_octaves(" + |
| 979 | String::num(terrain_height_ * erosion_scale_ * emit_cell_scale, 6) + |
| 980 | ", voxel_scale, 2.0);\n") : String()) |
| 981 | + " float y_mapped = (y - " + floor_str + ") * " + yscale_str + ";\n" |
| 982 | " float d = proc_density(vec3(x * inv_scale, y_mapped, z * inv_scale));\n" |
| 983 | " d *= " + inv_yscale_str + ";\n" |
| 984 | " d = max(d, (" + floor_str + " - y) * 2.0);\n" |
| 985 | " d = min(d, (" + ceil_str + " - y) * 2.0);\n" |
| 986 | " return d;\n" |
| 987 | "}\n"; |
| 988 | CharString u8 = mm.utf8(); |
| 989 | cached_glsl_ = std::string(u8.get_data(), u8.length()); |
| 990 | UtilityFunctions::print("[DCTerrainGeneratorProcNodes] EROSION-MINIMAL: ", |
| 991 | String::num_int64(cached_glsl_.size()), " bytes (erosion ", |
| 992 | erosion_enabled_ ? "ON" : "OFF", ")"); |
| 993 | return; |
| 994 | } |
| 995 | |
| 917 | 996 | const bool has_noise_lib = proc_glsl.find("fractal_noise_2d_lod") != -1; |
| 918 | 997 | const bool want_mountain = has_noise_lib && mountain_height_ != 0.0f; |
| 919 | 998 | const bool want_detail = has_noise_lib && detail_scale_ > 0.0f; |