godot_heightmap_plugin icon indicating copy to clipboard operation
godot_heightmap_plugin copied to clipboard

Add triplanar to MultiSplat16

Open Favkis opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe. Add ability to add triplanar flag for textures.

Describe the solution you'd like Either add an array of texture IDs that have triplanar enabled, or at the very list add few slots for triplanar filtering.

Describe alternatives you've considered I tried to add it myself but I couldn't

Additional context Add any other context or screenshots about the feature request here. image Cliifs needs triplanar filtering a lot

Favkis avatar Aug 19 '22 08:08 Favkis

It shouldn't be hard to add, I could give this a try. There is already some triplanar code in there, it's only a matter of adapting it to texture arrays (they just take a layer index, otherwise the logic is the same).

However, this will bump the amount of texture fetches in the shader from 7 to 21, or 42 if antitile is enabled (without counting fetches Godot does under the hood). Unlike other shaders where one slot can be dedicated to cliffs, here a texture array is used, so forcing only some textures to have the feature adds complexity.

Also, it is starting to have quite a lof of combinations. As usual in Godot 3, without preprocessor with inspector options support which could eliminate options that remain constant throughout the game, adding any option to a shader requires to make a entire copy of it (there are lots of copies already), or use if (There are already several nested ifs in the shader, lots of ifs in a shader is often a bad idea). Here there was already 2 branches just to combine textures, if triplanar is added as an option it will have to handle 4 different combinations.

Note: even with triplanar, cliffs will always look better with so-called "cliff meshes", but depends how you want the game to look like.

MGilleronFJ avatar Aug 19 '22 09:08 MGilleronFJ

It shouldn't be hard to add, I could give this a try. There is already some triplanar code in there, it's only a matter of adapting it to texture arrays (they just take a layer index, otherwise the logic is the same).

However, this will bump the amount of texture fetches in the shader from 7 to 21, or 42 if antitile is enabled (without counting fetches Godot does under the hood). Unlike other shaders where one slot can be dedicated to cliffs, here a texture array is used, so forcing only some textures to have the feature adds complexity.

Also, it is starting to have quite a lof of combinations. As usual in Godot 3, without preprocessor with inspector options support which could eliminate options that remain constant throughout the game, adding any option to a shader requires to make a entire copy of it (there are lots of copies already), or use if (There are already several nested ifs in the shader, lots of ifs in a shader is often a bad idea). Here there was already 2 branches just to combine textures, if triplanar is added as an option it will have to handle 4 different combinations.

Note: even with triplanar, cliffs will always look better with so-called "cliff meshes", but depends how you want the game to look like.

As for cliff meshes, they add too many objects, I tried adding very large stones there but for cliff on screenshot it took like 100 models, which in godot added 1 mil polys. Maybe I jsut didnt find good cliff meshes tho, I'll search, thank you

Favkis avatar Aug 19 '22 10:08 Favkis

Here is a version of multisplat16 that uses triplanar mapping for all textures. I didn't implement it with tile reduction though, it needs to be turned off multisplat16_triplanar.txt To use it, assign it to the custom shader property and change shader type to Custom.

Differences with the original:

--- a/addons/zylann.hterrain/shaders/multisplat16.shader
+++ b/tests/test_multisplat/multisplat16_triplanar.gdshader
@@ -79,10 +79,10 @@ vec3 get_triplanar_blend(vec3 world_normal) {
        return blending / vec3(b, b, b);
 }

-vec4 texture_triplanar(sampler2D tex, vec3 world_pos, vec3 blend) {
-       vec4 xaxis = texture(tex, world_pos.yz);
-       vec4 yaxis = texture(tex, world_pos.xz);
-       vec4 zaxis = texture(tex, world_pos.xy);
+vec4 texture_array_triplanar(sampler2DArray tex, vec3 world_pos, vec3 blend, float layer) {
+       vec4 xaxis = texture(tex, vec3(world_pos.yz, layer));
+       vec4 yaxis = texture(tex, vec3(world_pos.xz, layer));
+       vec4 zaxis = texture(tex, vec3(world_pos.xy, layer));
        // blend the results of the 3 planar projections.
        return xaxis * blend.x + yaxis * blend.y + zaxis * blend.z;
 }
@@ -288,15 +288,17 @@ void fragment() {
                                vec3(v_ground_uv.xz, high_indices.w), nr3);

                } else {
-                       ab0 = texture(u_ground_albedo_bump_array, vec3(v_ground_uv.xz, high_indices.x));
-                       ab1 = texture(u_ground_albedo_bump_array, vec3(v_ground_uv.xz, high_indices.y));
-                       ab2 = texture(u_ground_albedo_bump_array, vec3(v_ground_uv.xz, high_indices.z));
-                       ab3 = texture(u_ground_albedo_bump_array, vec3(v_ground_uv.xz, high_indices.w));
-
-                       nr0 = texture(u_ground_normal_roughness_array, vec3(v_ground_uv.xz, high_indices.x));
-                       nr1 = texture(u_ground_normal_roughness_array, vec3(v_ground_uv.xz, high_indices.y));
-                       nr2 = texture(u_ground_normal_roughness_array, vec3(v_ground_uv.xz, high_indices.z));
-                       nr3 = texture(u_ground_normal_roughness_array, vec3(v_ground_uv.xz, high_indices.w));
+                       vec3 triplanar_blending = get_triplanar_blend(terrain_normal_world);
+
+                       ab0 = texture_array_triplanar(u_ground_albedo_bump_array, v_ground_uv, triplanar_blending, high_indices.x);
+                       ab1 = texture_array_triplanar(u_ground_albedo_bump_array, v_ground_uv, triplanar_blending, high_indices.y);
+                       ab2 = texture_array_triplanar(u_ground_albedo_bump_array, v_ground_uv, triplanar_blending, high_indices.z);
+                       ab3 = texture_array_triplanar(u_ground_albedo_bump_array, v_ground_uv, triplanar_blending, high_indices.w);
+
+                       nr0 = texture_array_triplanar(u_ground_normal_roughness_array, v_ground_uv, triplanar_blending, high_indices.x);
+                       nr1 = texture_array_triplanar(u_ground_normal_roughness_array, v_ground_uv, triplanar_blending, high_indices.y);
+                       nr2 = texture_array_triplanar(u_ground_normal_roughness_array, v_ground_uv, triplanar_blending, high_indices.z);
+                       nr3 = texture_array_triplanar(u_ground_normal_roughness_array, v_ground_uv, triplanar_blending, high_indices.w);
                }

                vec3 col0 = ab0.rgb * v_tint;
@@ -355,7 +357,7 @@ void fragment() {

                ALBEDO = mix(ALBEDO, global_albedo, globalmap_factor);
                ROUGHNESS = mix(ROUGHNESS, 1.0, globalmap_factor);
-
+
 //             if(count < 3) {
 //                     ALBEDO = vec3(1.0, 0.0, 0.0);
 //             }

Zylann avatar Aug 24 '22 19:08 Zylann