Automatic Seamless Texture on a 3D Object through MaterialShader?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Corruptinator
:warning: Old Version Published before Godot 3 was released.

Hello! After messing around with Blender, I learned that its possible to automatically wrap a seamless texture to an object (Using Cycles Nodes), whether it has UV Mapping or Not:

The way it works is that it uses the Object’s Texture Coordinates to tell the mapping of how the texture should be automatically wrapped around the object.

So is there any way to somehow recreate the automatic texturing in Godot’s MaterialShader Language or the MaterialShader Graph? If so then it would save a lot of headaches in UV mapping. If not then I could always bake this to a separate texture and export it through DAE exporter. But I just wanted to ask out of curiosity.

As far as I can tell, this kind of method would be useful for natural elements such as hills, caves, a dark cavern, or an evil dungeon…

P.S. If anybody is curious about the “Blend” Slider in the Image Tex Node, that’s to blend the texture to eliminate the noticeable seams.

Aren’t texture coordinates usually baked into the vertices? I haven’t used Blender though so I don’t really know how that works, but maybe you can associate the texture coordinates with the vertices of the exported model somehow.

raymoo | 2017-03-06 18:58

“whether it has UV Mapping or Not:” ; “it uses the Object’s Texture Coordinates”
Well… how are you texturing if there are no UVs? ^^ To clarify: UV = texture coordinates = an attribute found on all vertices of a mesh (usually) that are then used in the shader.
I don’t think Godot has any built-in tool to generate UVs like that.
You can eventually program a shader that uses another attribute to map textures (positions? Colors?) but that’s pretty specific.

Also I can’t see your image, the link is maybe private, oversized or something.

Zylann | 2017-03-06 20:26

Hang on, I’ll see what’s wrong with the image.

Corruptinator | 2017-03-07 01:32

Image Fixed, Hopefully…

Corruptinator | 2017-03-07 01:45

Any idea on how that can be done?

Corruptinator | 2017-03-07 01:50

:bust_in_silhouette: Reply From: mollusca

One way of doing this is by tri-planar mapping. Basically you project your texture(s) in the X, Y and Z directions and blend them according to the surface normal. Here’s a basic version:

Vertex shader:

VAR1 = vec4(SRC_NORMAL.x, SRC_NORMAL.y, SRC_NORMAL.z, 0.0);
VAR2 = vec4(SRC_VERTEX.x, SRC_VERTEX.y, SRC_VERTEX.z, 0.0);

Fragment shader:

uniform texture diffuse;
uniform float sharpness;
uniform float texture_scale;

vec2 uv_x = vec2(VAR2.z, 1.0 - VAR2.y) / texture_scale;
vec2 uv_y = vec2(VAR2.z, 1.0 - VAR2.x) / texture_scale;
vec2 uv_z = vec2(VAR2.x, 1.0 - VAR2.y) / texture_scale;

vec3 col_x = tex(diffuse, uv_x).xyz;
vec3 col_y = tex(diffuse, uv_y).xyz;
vec3 col_z = tex(diffuse, uv_z).xyz;

vec3 weights = abs(VAR1.xyz) - vec3(0.2); // the 0.2 adds additional sharpness, not necessarily needed
weights.x = pow(weights.x, sharpness);
weights.y = pow(weights.y, sharpness);
weights.z = pow(weights.z, sharpness);
weights = max(weights, vec3(0.0));
weights /= dot(weights, vec3(1.0));

DIFFUSE = (weights.x * col_x + weights.y * col_y + weights.z * col_z);

Nice! It actually works! One thing for heads up is to make sure the “Repeat” Flags are enabled so then you don’t experience stretched areas.

Corruptinator | 2017-03-07 16:56