Skip to content

Commit

Permalink
Replace region_blend_map with shader function
Browse files Browse the repository at this point in the history
  • Loading branch information
Xtarsia authored and TokisanGames committed Aug 28, 2024
1 parent 1cc7b97 commit 54605eb
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 102 deletions.
14 changes: 0 additions & 14 deletions doc/api/class_terrain3dmaterial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ Methods
+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`RID<class_RID>` | :ref:`get_material_rid<class_Terrain3DMaterial_method_get_material_rid>`\ (\ ) |const| |
+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`RID<class_RID>` | :ref:`get_region_blend_map<class_Terrain3DMaterial_method_get_region_blend_map>`\ (\ ) |const| |
+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`Variant<class_Variant>` | :ref:`get_shader_param<class_Terrain3DMaterial_method_get_shader_param>`\ (\ name\: :ref:`StringName<class_StringName>`\ ) |const| |
+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| :ref:`RID<class_RID>` | :ref:`get_shader_rid<class_Terrain3DMaterial_method_get_shader_rid>`\ (\ ) |const| |
Expand Down Expand Up @@ -565,18 +563,6 @@ Returns the RID of the material used with the Rendering Server. This is set per

----

.. _class_Terrain3DMaterial_method_get_region_blend_map:

.. rst-class:: classref-method

:ref:`RID<class_RID>` **get_region_blend_map**\ (\ ) |const| :ref:`🔗<class_Terrain3DMaterial_method_get_region_blend_map>`

Returns the RID of the 512x512 texture used with the RenderingServer. It depicts a blurry map of region locations and is used for smoothly blending world noise into sculpted terrain.

.. rst-class:: classref-item-separator

----

.. _class_Terrain3DMaterial_method_get_shader_param:

.. rst-class:: classref-method
Expand Down
6 changes: 0 additions & 6 deletions doc/classes/Terrain3DMaterial.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@
Returns the RID of the material used with the Rendering Server. This is set per instance of this class.
</description>
</method>
<method name="get_region_blend_map" qualifiers="const">
<return type="RID" />
<description>
Returns the RID of the 512x512 texture used with the RenderingServer. It depicts a blurry map of region locations and is used for smoothly blending world noise into sculpted terrain.
</description>
</method>
<method name="get_shader_param" qualifiers="const">
<return type="Variant" />
<param index="0" name="name" type="StringName" />
Expand Down
6 changes: 3 additions & 3 deletions project/demo/Demo.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,12 @@ _shader_parameters = {
"noise_texture": SubResource("NoiseTexture2D_bov7h"),
"tri_scale_reduction": 0.3,
"vertex_normals_distance": 128.0,
"world_noise_blend_far": 1.0,
"world_noise_blend_near": 0.7,
"world_noise_height": 34.0,
"world_noise_lod_distance": 7500.0,
"world_noise_max_octaves": 4,
"world_noise_min_octaves": 2,
"world_noise_offset": Vector3(1.485, -1.01, 1.9),
"world_noise_offset": Vector3(2.17, -1.225, 1.9),
"world_noise_region_blend": 0.33,
"world_noise_scale": 9.85
}
world_background = 2
Expand Down Expand Up @@ -90,3 +89,4 @@ render_cull_margin = 1000.0
collision_mask = 3
mesh_size = 64
top_level = true
metadata/_edit_lock_ = true
11 changes: 0 additions & 11 deletions project/demo/components/UI.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,3 @@ offset_bottom = 23.0
theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.662745)
theme_override_constants/shadow_offset_x = 1
theme_override_constants/shadow_offset_y = 1

[node name="TextureRect" type="TextureRect" parent="."]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -128.0
offset_bottom = 128.0
grow_horizontal = 0
expand_mode = 1
7 changes: 0 additions & 7 deletions project/demo/src/CodeGenerated.gd
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,3 @@ func _ready():
$RuntimeNavigationBaker.terrain = terrain
$RuntimeNavigationBaker.enabled = true

# Retreive 512x512 region blur map showing where the regions are
var rbmap_rid: RID = terrain.material.get_region_blend_map()
img = RenderingServer.texture_2d_get(rbmap_rid)
$UI/TextureRect.texture = ImageTexture.create_from_image(img)



22 changes: 9 additions & 13 deletions src/shaders/main.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,22 @@ varying float v_region_border_mask;
// Takes in UV world space coordinates, returns ivec3 with:
// XY: (0 to _region_size) coordinates within a region
// Z: layer index used for texturearrays, -1 if not in a region
ivec3 get_region_uv(vec2 uv) {
uv *= _region_texel_size;
ivec2 pos = ivec2(floor(uv)) + (_region_map_size / 2);
int bounds = int(pos.x >= 0 && pos.x < _region_map_size && pos.y >= 0 && pos.y < _region_map_size);
ivec3 get_region_uv(const vec2 uv) {
ivec2 pos = ivec2(floor(uv * _region_texel_size)) + (_region_map_size / 2);
int bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
int layer_index = _region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1;
return ivec3(ivec2((uv - _region_offsets[layer_index]) * _region_size), layer_index);
return ivec3(ivec2(mod(uv,_region_size)), layer_index);
}

// Takes in UV2 region space coordinates, returns vec3 with:
// XY: (0 to 1) coordinates within a region
// Z: layer index used for texturearrays, -1 if not in a region
vec3 get_region_uv2(vec2 uv) {
// Vertex function added half a texel to UV2, to center the UV's. vertex(), fragment() and get_height()
// call this with reclaimed versions of UV2, so to keep the last row/column within the correct
// window, take back the half pixel before the floor().
ivec2 pos = ivec2(floor(uv - vec2(_region_texel_size * 0.5))) + (_region_map_size / 2);
int bounds = int(pos.x >= 0 && pos.x < _region_map_size && pos.y >= 0 && pos.y < _region_map_size);
vec3 get_region_uv2(const vec2 uv2) {
// Remove Texel Offset to ensure correct region index.
ivec2 pos = ivec2(floor(uv2 - vec2(_region_texel_size * 0.5))) + (_region_map_size / 2);
int bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
int layer_index = _region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1;
// The return value is still texel-centered.
return vec3(uv - _region_offsets[layer_index], float(layer_index));
return vec3(uv2 - _region_offsets[layer_index], float(layer_index));
}

//INSERT: WORLD_NOISE1
Expand Down
56 changes: 37 additions & 19 deletions src/shaders/world_noise.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,36 @@ R"(

//INSERT: WORLD_NOISE1
// World Noise

uniform sampler2D _region_blend_map : hint_default_black, filter_linear, repeat_disable;
uniform float world_noise_region_blend : hint_range(0.05, 0.95, 0.01) = 0.33;
uniform int world_noise_max_octaves : hint_range(0, 15) = 4;
uniform int world_noise_min_octaves : hint_range(0, 15) = 2;
uniform float world_noise_lod_distance : hint_range(0, 40000, 1) = 7500.;
uniform float world_noise_scale : hint_range(0.25, 20, 0.01) = 5.0;
uniform float world_noise_height : hint_range(0, 1000, 0.1) = 64.0;
uniform vec3 world_noise_offset = vec3(0.0);
uniform float world_noise_blend_near : hint_range(0, .95, 0.01) = 0.5;
uniform float world_noise_blend_far : hint_range(.05, 1, 0.01) = 1.0;

// Takes in UV2 region space coordinates, returns 1.0 or 0.0 if a region is present or not.
float check_region(const vec2 uv2) {
ivec2 pos = ivec2(floor(uv2)) + (_region_map_size / 2);
int layer_index = 0;
if (uint(pos.x | pos.y) < uint(_region_map_size)) {
layer_index = clamp(_region_map[ pos.y * _region_map_size + pos.x ] - 1, -1, 0) + 1;
}
return float(layer_index);
}

// Takes in UV2 region space coordinates, returns a blend value (0 - 1 range) between empty, and valid regions
float region_blend(vec2 uv2) {
uv2 -= 0.5;
const vec2 offset = vec2(0.0,1.0);
float a = check_region(uv2 + offset.xy);
float b = check_region(uv2 + offset.yy);
float c = check_region(uv2 + offset.yx);
float d = check_region(uv2 + offset.xx);
vec2 w = smoothstep(vec2(0.0), vec2(1.0), fract(uv2));
float blend = mix(mix(d, c, w.x), mix(a, b, w.x), w.y);
return 1.0 - blend;
}

float hashf(float f) {
return fract(sin(f) * 1e4);
Expand Down Expand Up @@ -66,25 +86,23 @@ float world_noise(vec2 p) {
return a;
}

float get_noise_height(const vec2 uv) {
float weight = region_blend(uv);
// only calculate world noise when it could be visibile.
if (weight <= 1.0 - world_noise_region_blend) {
return 0.0;
}
float noise = world_noise((uv + world_noise_offset.xz) * world_noise_scale * .1) *
world_noise_height * 10. + world_noise_offset.y * 100.;
weight = smoothstep(1.0 - world_noise_region_blend, 1.0, weight);
return mix(0.0, noise, weight);
}

// World Noise end

//INSERT: WORLD_NOISE2
// World Noise
if (_background_mode == 2u) {
float weight = texture(_region_blend_map, (uv / float(_region_map_size)) + 0.5).r;
float rmap_half_size = float(_region_map_size) * .5;
if (abs(uv.x) > rmap_half_size + .5 || abs(uv.y) > rmap_half_size + .5) {
weight = 0.;
} else {
if (abs(uv.x) > rmap_half_size - .5) {
weight = mix(weight, 0., abs(uv.x) - (rmap_half_size-.5));
}
if (abs(uv.y) > rmap_half_size - .5) {
weight = mix(weight, 0., abs(uv.y) - (rmap_half_size-.5));
}
}
height = mix(height, world_noise((uv + world_noise_offset.xz) * world_noise_scale * .1) *
world_noise_height * 10. + world_noise_offset.y * 100.,
clamp(smoothstep(world_noise_blend_near, world_noise_blend_far, 1.0 - weight), 0.0, 1.0));
height += get_noise_height(uv);
}
)"
26 changes: 0 additions & 26 deletions src/terrain_3d_material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,30 +335,6 @@ void Terrain3DMaterial::_update_regions() {
LOG(DEBUG_CONT, "Setting mesh vertex spacing in material: ", spacing);
RS->material_set_param(_material, "_mesh_vertex_spacing", spacing);
RS->material_set_param(_material, "_mesh_vertex_density", 1.0f / spacing);

_generate_region_blend_map();
}

void Terrain3DMaterial::_generate_region_blend_map() {
IS_STORAGE_INIT_MESG("Material not initialized", VOID);
PackedInt32Array region_map = _terrain->get_storage()->get_region_map();
int rsize = Terrain3DStorage::REGION_MAP_SIZE;
if (region_map.size() == rsize * rsize) {
LOG(DEBUG_CONT, "Regenerating ", Vector2i(512, 512), " region blend map");
Ref<Image> region_blend_img = Image::create(rsize, rsize, false, Image::FORMAT_RH);
for (int y = 0; y < rsize; y++) {
for (int x = 0; x < rsize; x++) {
if (region_map[y * rsize + x] > 0) {
region_blend_img->set_pixel(x, y, COLOR_WHITE);
}
}
}
region_blend_img->resize(512, 512, Image::INTERPOLATE_TRILINEAR);
_generated_region_blend_map.clear();
_generated_region_blend_map.create(region_blend_img);
RS->material_set_param(_material, "_region_blend_map", _generated_region_blend_map.get_rid());
Util::dump_gentex(_generated_region_blend_map, "blend_map", DEBUG_CONT);
}
}

// Called from signal connected in Terrain3D, emitted by texture_list
Expand Down Expand Up @@ -420,7 +396,6 @@ Terrain3DMaterial::~Terrain3DMaterial() {
IS_INIT(VOID);
LOG(INFO, "Destroying material");
RS->free_rid(_material);
_generated_region_blend_map.clear();
}

void Terrain3DMaterial::update() {
Expand Down Expand Up @@ -735,7 +710,6 @@ void Terrain3DMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("update"), &Terrain3DMaterial::update);
ClassDB::bind_method(D_METHOD("get_material_rid"), &Terrain3DMaterial::get_material_rid);
ClassDB::bind_method(D_METHOD("get_shader_rid"), &Terrain3DMaterial::get_shader_rid);
ClassDB::bind_method(D_METHOD("get_region_blend_map"), &Terrain3DMaterial::get_region_blend_map);

ClassDB::bind_method(D_METHOD("set_world_background", "background"), &Terrain3DMaterial::set_world_background);
ClassDB::bind_method(D_METHOD("get_world_background"), &Terrain3DMaterial::get_world_background);
Expand Down
3 changes: 0 additions & 3 deletions src/terrain_3d_material.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class Terrain3DMaterial : public Resource {
Ref<Shader> _shader_override; // User's shader we copy code from
mutable TypedArray<StringName> _active_params; // All shader params in the current shader
mutable Dictionary _shader_params; // Public shader params saved to disk
GeneratedTexture _generated_region_blend_map; // 512x512 blurred image of region_map

// Material Features
WorldBackground _world_background = FLAT;
Expand Down Expand Up @@ -74,7 +73,6 @@ class Terrain3DMaterial : public Resource {
String _inject_editor_code(const String &p_shader) const;
void _update_shader();
void _update_regions();
void _generate_region_blend_map();
void _update_texture_arrays();
void _set_shader_parameters(const Dictionary &p_dict);
Dictionary _get_shader_parameters() const { return _shader_params; }
Expand All @@ -87,7 +85,6 @@ class Terrain3DMaterial : public Resource {
void update();
RID get_material_rid() const { return _material; }
RID get_shader_rid() const { return _shader->get_rid(); }
RID get_region_blend_map() const { return _generated_region_blend_map.get_rid(); }

// Material settings
void set_world_background(const WorldBackground p_background);
Expand Down

0 comments on commit 54605eb

Please sign in to comment.