godot_heightmap_plugin
godot_heightmap_plugin copied to clipboard
Add triplanar to MultiSplat16
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.
Cliifs needs triplanar filtering a lot
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.
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
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);
// }